diff options
| author | Prakash Dhavali <pdhavali@codeaurora.org> | 2014-01-24 09:57:22 -0800 |
|---|---|---|
| committer | Prakash Dhavali <pdhavali@codeaurora.org> | 2014-01-24 09:57:22 -0800 |
| commit | 5af7cf592cd5ac53c0eef51c5be8182133b74112 (patch) | |
| tree | a5a0da067325eaa4e7d7438948784aa851602624 | |
| parent | a9053b62b2fcfebd1c9089c590d2191ea358d43d (diff) | |
| parent | dc21a9afb59e0117924f0dcb9187204ed981b8e2 (diff) | |
Merge remote-tracking branch 'origin/caf/caf-wlan/master'
154 files changed, 15405 insertions, 17459 deletions
diff --git a/CORE/BAP/src/btampFsm.c b/CORE/BAP/src/btampFsm.c index f6c29373dc70..f052f157e190 100644 --- a/CORE/BAP/src/btampFsm.c +++ b/CORE/BAP/src/btampFsm.c @@ -1175,7 +1175,7 @@ regStaWithTl if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, - "%s: WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08lX]", + "%s: WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]", __func__, vosStatus, vosStatus ); } diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c index f8f40ea86974..dcce0648fe31 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -43,6 +43,7 @@ #endif #include "adf_nbuf.h" #include "wma_api.h" +#include "vos_utils.h" #define ENTER() VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__) @@ -389,13 +390,18 @@ next_nbuf: #define TLSHIM_TGT_NOISE_FLOOR_DBM (-96) static int tlshim_mgmt_rx_process(void *context, u_int8_t *data, - u_int32_t data_len, bool saved_beacon) + u_int32_t data_len, bool saved_beacon, u_int32_t vdev_id) { void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL); struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL; wmi_mgmt_rx_hdr *hdr = NULL; +#ifdef WLAN_FEATURE_11W + struct wma_txrx_node *iface = NULL; + tp_wma_handle wma; + u_int8_t *efrm, *orig_hdr; +#endif /* WLAN_FEATURE_11W */ vos_pkt_t *rx_pkt; adf_nbuf_t wbuf; @@ -515,20 +521,82 @@ static int tlshim_mgmt_rx_process(void *context, u_int8_t *data, tl_shim->last_beacon_len = data_len; } } + +#ifdef WLAN_FEATURE_11W + wma = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (wma) + iface = &wma->interfaces[vdev_id]; + if (iface && iface->rmfEnabled && mgt_type == IEEE80211_FC0_TYPE_MGT && + (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC || + mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH || + mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) + { + if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) + { + orig_hdr = (u_int8_t*) adf_nbuf_data(wbuf); + + /* Strip privacy headers (and trailer) + for a received frame */ + vos_mem_move(orig_hdr + IEEE80211_CCMP_HEADERLEN, + wh, sizeof(*wh)); + adf_nbuf_pull_head(wbuf, IEEE80211_CCMP_HEADERLEN); + adf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN); + + rx_pkt->pkt_meta.mpdu_hdr_ptr = adf_nbuf_data(wbuf); + rx_pkt->pkt_meta.mpdu_data_ptr = + rx_pkt->pkt_meta.mpdu_hdr_ptr + + rx_pkt->pkt_meta.mpdu_hdr_len; + rx_pkt->pkt_buf = wbuf; + } + else + { + if (IEEE80211_IS_BROADCAST(wh->i_addr1) || + IEEE80211_IS_MULTICAST(wh->i_addr1)) + { + efrm = adf_nbuf_data(wbuf) + adf_nbuf_len(wbuf); + if (vos_is_mmie_valid(iface->key.key, + iface->key.ipn, + (u_int8_t *)wh, efrm)) + { + TLSHIM_LOGD("Protected BC/MC frame MMIE" + " validation successful"); + + /* Remove MMIE */ + adf_nbuf_trim_tail(wbuf, + vos_get_mmie_size()); + } + else + { + TLSHIM_LOGE("BC/MC MIC error or MMIE" + " not present, dropping the frame"); + vos_pkt_return_packet(rx_pkt); + return 0; + } + } + else + { + TLSHIM_LOGD("Rx unprotected unicast mgmt frame"); + rx_pkt->pkt_meta.dpuFeedback = + DPU_FEEDBACK_UNPROTECTED_ERROR; + } + + } + } +#endif /* WLAN_FEATURE_11W */ return tl_shim->mgmt_rx(vos_ctx, rx_pkt); } static int tlshim_mgmt_rx_wmi_handler(void *context, u_int8_t *data, u_int32_t data_len) { - return (tlshim_mgmt_rx_process(context, data, data_len, FALSE)); + return (tlshim_mgmt_rx_process(context, data, data_len, FALSE, 0)); } #endif /* * tlshim_mgmt_roam_event_ind() is called from WMA layer when * BETTER_AP_FOUND event is received from roam engine. */ -int tlshim_mgmt_roam_event_ind(void *context) +int tlshim_mgmt_roam_event_ind(void *context, u_int32_t vdev_id) { void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL); struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, @@ -536,7 +604,7 @@ int tlshim_mgmt_roam_event_ind(void *context) VOS_STATUS ret = VOS_STATUS_SUCCESS; if (tl_shim->last_beacon_data && tl_shim->last_beacon_len) { - ret = tlshim_mgmt_rx_process(context, tl_shim->last_beacon_data, tl_shim->last_beacon_len, TRUE); + ret = tlshim_mgmt_rx_process(context, tl_shim->last_beacon_data, tl_shim->last_beacon_len, TRUE, vdev_id); } return ret; } @@ -763,7 +831,19 @@ adf_nbuf_t WLANTL_SendSTA_DataFrame(void *vos_ctx, u_int8_t sta_id, } /* Zero out skb's context buffer for the driver to use */ +#ifdef IPA_OFFLOAD + if ((NBUF_OWNER_ID(skb) == IPA_NBUF_OWNER_ID) + && NBUF_CALLBACK_FN(skb)) { + uint32_t skb_owner_id = NBUF_OWNER_ID(skb); + __adf_nbuf_callback_fn skb_cb_fn = NBUF_CALLBACK_FN(skb); + adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); + NBUF_OWNER_ID(skb) = skb_owner_id; + NBUF_CALLBACK_FN(skb) = skb_cb_fn; + } else + adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); +#else adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); +#endif adf_nbuf_map_single(adf_ctx, skb, ADF_OS_DMA_TO_DEVICE); if ((tl_shim->ip_checksum_offload) && (skb->protocol == htons(ETH_P_IP)) @@ -782,32 +862,6 @@ adf_nbuf_t WLANTL_SendSTA_DataFrame(void *vos_ctx, u_int8_t sta_id, return NULL; } -#ifdef IPA_OFFLOAD -adf_nbuf_t WLANTL_SendIPA_DataFrame(void *vos_ctx, void *vdev, - adf_nbuf_t skb) -{ - struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, - vos_ctx); - adf_nbuf_t ret; - - ENTER(); - - if ((tl_shim->ip_checksum_offload) && (skb->protocol == htons(ETH_P_IP)) - && (skb->ip_summed == CHECKSUM_PARTIAL)) - skb->ip_summed = CHECKSUM_COMPLETE; - - /* Terminate the (single-element) list of tx frames */ - skb->next = NULL; - ret = tl_shim->tx((struct ol_txrx_vdev_t *)vdev, skb); - if (ret) { - TLSHIM_LOGW("Failed to tx"); - return ret; - } - - return NULL; -} -#endif - VOS_STATUS WLANTL_ResumeDataTx(void *vos_ctx, u_int8_t *sta_id) { return VOS_STATUS_SUCCESS; diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c index 182312ff4662..90f55b17d873 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -771,6 +771,13 @@ ol_txrx_vdev_attach( TAILQ_INIT(&vdev->peer_list); vdev->last_real_peer = NULL; + #ifndef CONFIG_QCA_WIFI_ISOC + #ifdef QCA_IBSS_SUPPORT + vdev->ibss_peer_num = 0; + vdev->ibss_peer_heart_beat_timer = 0; + #endif + #endif + #if defined(CONFIG_HL_SUPPORT) if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { u_int8_t i; @@ -1085,6 +1092,17 @@ ol_txrx_peer_state_update(ol_txrx_pdev_handle pdev, u_int8_t *peer_mac, struct ol_txrx_peer_t *peer; peer = ol_txrx_peer_find_hash_find(pdev, peer_mac, 0, 1); + + if (NULL == peer) + { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, "%s: peer is null for peer_mac" + " 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, + peer_mac[0], peer_mac[1], peer_mac[2], peer_mac[3], + peer_mac[4], peer_mac[5]); + return; + } + + /* TODO: Should we send WMI command of the connection state? */ /* avoid multiple auth state change. */ if (peer->state == state) { diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h index 23f40c008aa9..7c757b43012e 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h +++ b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ /** * @file ol_txrx_types.h @@ -707,6 +692,14 @@ struct ol_txrx_vdev_t { enum wlan_op_mode opmode; +#ifndef CONFIG_QCA_WIFI_ISOC +#ifdef QCA_IBSS_SUPPORT + /* ibss mode related */ + int16_t ibss_peer_num; /* the number of active peers */ + int16_t ibss_peer_heart_beat_timer; /* for detecting peer departure */ +#endif +#endif + #if defined(CONFIG_HL_SUPPORT) struct ol_tx_frms_queue_t txqs[OL_TX_VDEV_NUM_QUEUES]; #endif diff --git a/CORE/CLD_TXRX/TXRX/txrx_api.c b/CORE/CLD_TXRX/TXRX/txrx_api.c index dbb32fa79588..23840ead0eb7 100644 --- a/CORE/CLD_TXRX/TXRX/txrx_api.c +++ b/CORE/CLD_TXRX/TXRX/txrx_api.c @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ /* * This file has the implementation of TXRX api for HDD<->TXRX and diff --git a/CORE/DXE/htt_dxe.c b/CORE/DXE/htt_dxe.c deleted file mode 100644 index bf22d1f40506..000000000000 --- a/CORE/DXE/htt_dxe.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** - * @file htt_dxe.c - * @brief Provide functions to create+init and destroy a HTT instance. - * @details - * This file contains functions for creating a HTT instance; initializing - * the HTT instance, e.g. by allocating a pool of HTT tx descriptors, and - * and deleting a HTT instance. - */ - -#include <adf_os_mem.h> /* adf_os_mem_alloc */ -#include <adf_os_types.h> /* adf_os_device_t, adf_os_print */ - -#include <ol_cfg.h> /* ol_cfg_max_vdevs, etc. */ -#include <ol_htt_api.h> -#include <ol_txrx_htt_api.h> /* ol_tx_target_credit_update */ - -#include <htt_dxe_types.h> -#include <htt_dxe_internal.h> - -#define htt_dxe_attach htt_attach -#define htt_dxe_attach_target htt_attach_target -#define htt_dxe_detach htt_detach -#define htt_dxe_detach_target htt_detach_target -#define htt_dxe_vdev_attach htt_vdev_attach -#define htt_dxe_vdev_detach htt_vdev_detach -#define htt_dxe_peer_qos_update htt_peer_qos_update -#define htt_dxe_peer_uapsdmask_update htt_peer_uapsdmask_update -#define htt_dxe_display htt_display - - -htt_pdev_handle -htt_dxe_attach( - ol_txrx_pdev_handle txrx_pdev, - ol_pdev_handle ctrl_pdev, - HTC_HANDLE htc_pdev, - adf_os_device_t osdev, - int desc_pool_size) -{ - int i; - int tx_credit; - A_STATUS status; - struct htt_dxe_pdev_t *pdev; - S_HIFDXE_CALLBACK hif_dxe_cbs = {0}; - - pdev = adf_os_mem_alloc(osdev, sizeof(*pdev)); - if (!pdev) { - return NULL; - } - - /* - * Zero out all pointers within the pdev object, so it will be - * obvious which pointers have been initialized and which haven't. - * This allows the htt_dxe_detach function to be used to clean up - * when the htt_dxe_attach initializations fail halfway through. - */ - adf_os_mem_zero(pdev, sizeof(*pdev)); - - pdev->osdev = osdev; - pdev->ctrl_pdev = ctrl_pdev; - pdev->txrx_pdev = txrx_pdev; - - pdev->vdevs = adf_os_mem_alloc(osdev, - sizeof(struct htt_dxe_vdev_t) * ol_cfg_max_vdevs(ctrl_pdev)); - if (!pdev->vdevs) { - goto fail; - } - for (i = 0; i < ol_cfg_max_vdevs(ctrl_pdev); i++) { - pdev->vdevs[i].valid = 0; - } - - pdev->peers = adf_os_mem_alloc(osdev, - sizeof(struct htt_dxe_peer_t) * (ol_cfg_max_peer_id(ctrl_pdev) + 1)); - if (!pdev->peers) { - goto fail; - } - for (i = 0; i <= ol_cfg_max_peer_id(ctrl_pdev); i++) { - pdev->peers[i].valid = 0; - pdev->peers[i].qos_capable = 0; /* default */ - } - - if (htt_dxe_tx_attach(pdev, desc_pool_size)) { - goto fail; - } - - if (htt_dxe_rx_attach(pdev)) { - goto fail; - } - - adf_os_spinlock_init(&pdev->tx_mutex); - pdev->tx_mutex_valid = 1; - - pdev->hif_dxe_pdev = hif_dxe_attach(osdev); - - if (!pdev->hif_dxe_pdev) { - goto fail; - } - - hif_dxe_cbs.HifTxCompleteCb = htt_dxe_tx_download_done; - hif_dxe_cbs.HifTxCompleteCtx = pdev; - hif_dxe_cbs.HifLowResourceCb = htt_dxe_tx_low_rsrc; - hif_dxe_cbs.HifLowResourceCtx = pdev; - - status = hif_dxe_client_registration(pdev->hif_dxe_pdev, &hif_dxe_cbs); - if (status != A_OK) { - goto fail; - } - - pdev->dmux_dxe_pdev = dmux_dxe_attach(pdev->osdev); - if (!pdev->dmux_dxe_pdev) { - goto fail; - } - if ((dmux_dxe_register_callback_rx_data( - pdev->dmux_dxe_pdev, htt_dxe_rx, (void *) pdev) != A_OK) || - (dmux_dxe_register_callback_rx_ctrl( - pdev->dmux_dxe_pdev, htt_dxe_rx_ctrl, (void *) pdev) != A_OK) || - (dmux_dxe_register_callback_msg( - pdev->dmux_dxe_pdev, htt_dxe_t2h_msg_handler, (void *) pdev) - != A_OK)) - { - goto fail; - } - - pdev->cfg.flags.sw_tx_encap = ol_cfg_tx_encap(pdev->ctrl_pdev); - /* - * For Riva, don't use HW frame translation. - * NOTE: for Pronto and Northstar we'll want to enable HW frame - * translation for certain cases. - * In particular, if the input frame format is 802.3, we'll enable - * the HW's frame translation, but if the input frame format is - * native WiFi (basic 802.11), we'll disable HW frame translation, - * and rely on SW to add a QoS control field when appropriate. - */ - pdev->cfg.flags.do_frame_translate = 0; // FOR NOW - - /* initialize the txrx credit count */ - /* - * FOR NOW, consider only the space in the LOW_PRI ring. - * We eventually want to manage the credit such that we can avoid - * overflowing the target and thus stalling the DXE download ring. - * Once this is done, then we don't need separate LOW_PRI vs. HIGH_PRI - * channels, since there will be a negligible delay to download data - * through the single channel, since it will never stall. - */ - tx_credit = hif_dxe_get_resources( - pdev->hif_dxe_pdev, HIFDXE_CHANNEL_TX_LOW_PRI); - ol_tx_target_credit_update(pdev->txrx_pdev, tx_credit); - - return pdev; - -fail: - htt_dxe_detach(pdev); - return NULL; -} - -A_STATUS -htt_dxe_attach_target(htt_pdev_handle pdev) -{ - A_STATUS status; - status = hif_dxe_start(pdev->hif_dxe_pdev); - return status; -} - -void -htt_dxe_vdev_attach( - htt_pdev_handle pdev, - u_int8_t vdev_id, - enum htt_op_mode op_mode) -{ - pdev->vdevs[vdev_id].valid = 1; - pdev->vdevs[vdev_id].op_mode = op_mode; -} - - -void -htt_vdev_detach(htt_pdev_handle pdev, u_int8_t vdev_id) -{ - pdev->vdevs[vdev_id].valid = 0; -} - -void htt_dxe_peer_qos_update( - struct htt_dxe_pdev_t *pdev, int peer_id, u_int8_t qos_capable) -{ - struct htt_dxe_peer_t *peer; - - HTT_DXE_ASSERT3(peer_id <= ol_cfg_max_peer_id(pdev->ctrl_pdev)); - peer = &pdev->peers[peer_id]; - HTT_DXE_ASSERT2(peer->valid); - peer->qos_capable = qos_capable; -} - -void htt_dxe_peer_uapsdmask_update( - struct htt_dxe_pdev_t *pdev, int peer_id, u_int8_t uapsd_mask) -{ - /* TO be implemented */ - return; -} - -void -htt_dxe_detach(htt_pdev_handle pdev) -{ - htt_dxe_rx_detach(pdev); - htt_dxe_tx_detach(pdev); - if (pdev->dmux_dxe_pdev) { - dmux_dxe_detach(pdev->dmux_dxe_pdev); - } - if (pdev->hif_dxe_pdev) { - hif_dxe_detach(pdev->hif_dxe_pdev); - } - if (pdev->tx_mutex_valid) { - adf_os_spinlock_destroy(&pdev->tx_mutex); - } - if (pdev->peers) { - adf_os_mem_free(pdev->peers); - } - if (pdev->vdevs) { - adf_os_mem_free(pdev->vdevs); - } - /* - * Zero out the pdev object before freeing it. - * This will make it more obvious if anyone tries to use it - * after it has been freed. - */ - adf_os_mem_zero(pdev, sizeof(*pdev)); - adf_os_mem_free(pdev); -} - -void -htt_dxe_detach_target(htt_pdev_handle pdev) -{ - /* FILL HERE */ - return; -} - -static void -htt_dxe_vdev_display( - struct htt_dxe_pdev_t *pdev, - int vdev_id, - int indent) -{ - struct htt_dxe_vdev_t *vdev = &pdev->vdevs[vdev_id]; - adf_os_print( - "%*sID: %d, op mode: %s, self-peer ID: %d, bcast peer ID: %d\n", - indent, " ", - vdev_id, - (vdev->op_mode == htt_op_mode_ap) ? "AP" : - (vdev->op_mode == htt_op_mode_sta) ? "STA" : - (vdev->op_mode == htt_op_mode_ibss) ? "IBSS" : - "other", - vdev->self_peer_id, vdev->bcast_peer_id); -} - -static void -htt_dxe_peer_display( - struct htt_dxe_pdev_t *pdev, - int peer_id, - int indent) -{ - struct htt_dxe_peer_t *peer = &pdev->peers[peer_id]; - adf_os_print( - "%*sID: %d, type: %s, QoS capable: %d, robust mgmt: %d\n", - indent, " ", - peer_id, - (peer->type == HTT_ISOC_T2H_PEER_TYPE_ASSOC) ? "real peer" : - (peer->type == HTT_ISOC_T2H_PEER_TYPE_SELF) ? "self peer" : - (peer->type == HTT_ISOC_T2H_PEER_TYPE_BCAST) ? "bcast peer" : - "(other)", - peer->qos_capable, - peer->robust_mgmt); -} - -void -htt_dxe_display(htt_pdev_handle pdev, int indent) -{ - int i; - struct htt_dxe_tx_desc_t *sw_desc; - char *vaddr; - u_int32_t paddr; - - adf_os_print( - "HTT tx descs: %d bytes each (HW desc), %d total, %d allocated\n", - pdev->tx_descs.size, - pdev->tx_descs.pool_elems, - pdev->tx_descs.alloc_cnt); - sw_desc = pdev->tx_descs.sw_descs_pool; - vaddr = pdev->tx_descs.tx_bds.pool_vaddr; - paddr = pdev->tx_descs.tx_bds.pool_paddr; - for (i = 0; i < pdev->tx_descs.pool_elems; i++) { - if (pdev->tx_descs.pool_elems > 10) { - if (i == 4) { - adf_os_print(" ...\n"); - } - if (i >= 4 && i < pdev->tx_descs.pool_elems - 4) { - continue; - } - } - adf_os_print(" %d: sw desc = %p, hw desc vaddr = %p, paddr = %#x\n", - i, sw_desc, vaddr, paddr); - sw_desc++; - vaddr += pdev->tx_descs.size; - paddr += pdev->tx_descs.size; - } - adf_os_print("HTT vdevs:\n"); - for (i = 0; i < ol_cfg_max_vdevs(pdev->ctrl_pdev); i++) { - if (pdev->vdevs[i].valid) { - htt_dxe_vdev_display(pdev, i, indent+4); - } - } - adf_os_print("HTT peers:\n"); - for (i = 0; i <= ol_cfg_max_peer_id(pdev->ctrl_pdev); i++) { - if (pdev->peers[i].valid) { - htt_dxe_peer_display(pdev, i, indent+4); - } - } -} diff --git a/CORE/DXE/htt_dxe_fw_stats.c b/CORE/DXE/htt_dxe_fw_stats.c deleted file mode 100644 index ba642f2ce590..000000000000 --- a/CORE/DXE/htt_dxe_fw_stats.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** - * @file htt_fw_stats.c - * @brief Provide functions to process FW status retrieved from FW. - */ - -#include <ol_htt_api.h> - -void -htt_t2h_dbg_stats_hdr_parse( - u_int8_t *stats_info_list, - enum htt_dbg_stats_type *type, - enum htt_dbg_stats_status *status, - int *length, - u_int8_t **stats_data) -{ -} - -void -htt_t2h_stats_print(u_int8_t *stats_data, int concise) -{ -} - - diff --git a/CORE/DXE/htt_dxe_h2t.c b/CORE/DXE/htt_dxe_h2t.c deleted file mode 100644 index 217c74102022..000000000000 --- a/CORE/DXE/htt_dxe_h2t.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** - * @file htt_dxe_h2t.c - * @brief Provide dummy functions for host->target HTT messages. - * @details - * For the Riva family of targets supported by this hif_dxe module, - * no host->target HTT messages are required. - * This file provides dummy versions of the HTT H2T message - * construction functions called by txrx, just so the txrx code will - * link successfully. - */ - -#include <adf_os_util.h> -#include <ol_htt_api.h> - -int -htt_h2t_dbg_stats_get( - struct htt_pdev_t *pdev, - u_int32_t stats_type_upload_mask, - u_int32_t stats_type_reset_mask, - u_int8_t cfg_stat_type, - u_int32_t cfg_val, - u_int64_t cookie) -{ - adf_os_assert(0); - return 0; -} - -A_STATUS -htt_h2t_sync_msg(struct htt_pdev_t *pdev, u_int8_t sync_cnt) -{ - adf_os_assert(0); - return A_OK; -} - -#if defined(TEMP_AGGR_CFG) -int -htt_h2t_aggr_cfg_msg(struct htt_pdev_t *pdev, - int max_subfrms_ampdu, - int max_subfrms_amsdu) -{ - adf_os_assert(0); - return 0; -} -#endif diff --git a/CORE/DXE/htt_dxe_internal.h b/CORE/DXE/htt_dxe_internal.h deleted file mode 100644 index 7c048cc9604c..000000000000 --- a/CORE/DXE/htt_dxe_internal.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -#ifndef _HTT_DXE_INTERNAL__H_ -#define _HTT_DXE_INTERNAL__H_ - -#include <athdefs.h> /* A_STATUS */ - -#include <adf_nbuf.h> /* adf_nbuf_t */ - -#include <hif_dxe.h> /* E_HIFDXE_CHANNELTYPE */ - -#include <htt_dxe_types.h> - - -#define HTT_MAC_ADDR_LEN 6 - -/*--- utilities ---*/ - -#ifndef ARRAY_LEN -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) -#endif - - -#ifndef HTT_DXE_ASSERT_LEVEL -#define HTT_DXE_ASSERT_LEVEL 3 -#endif - -#define HTT_DXE_ASSERT_ALWAYS(condition) adf_os_assert_always((condition)) - -#define HTT_DXE_ASSERT0(condition) adf_os_assert((condition)) -#if HTT_DXE_ASSERT_LEVEL > 0 -#define HTT_DXE_ASSERT1(condition) adf_os_assert((condition)) -#else -#define HTT_DXE_ASSERT1(condition) -#endif - -#if HTT_DXE_ASSERT_LEVEL > 1 -#define HTT_DXE_ASSERT2(condition) adf_os_assert((condition)) -#else -#define HTT_DXE_ASSERT2(condition) -#endif - -#if HTT_DXE_ASSERT_LEVEL > 2 -#define HTT_DXE_ASSERT3(condition) adf_os_assert((condition)) -#else -#define HTT_DXE_ASSERT3(condition) -#endif - -/*--- aliases ---*/ - -#define htt_dxe_tx_desc_alloc htt_tx_desc_alloc -#define htt_dxe_tx_desc_free htt_tx_desc_free -#define htt_dxe_tx_desc_display htt_tx_desc_display - -/*--- tx ---*/ - -A_STATUS -htt_dxe_tx_attach(struct htt_dxe_pdev_t *pdev, int desc_pool_elems); - -void -htt_dxe_tx_detach(struct htt_pdev_t *pdev); - -A_STATUS -htt_dxe_tx_download_done( - void *context, - adf_nbuf_t tx_list, - E_HIFDXE_CHANNELTYPE chan, - A_STATUS status); - -A_STATUS -htt_dxe_tx_low_rsrc( - void *context, - E_HIFDXE_CHANNELTYPE chan, - A_BOOL is_low_resource); - -/*--- rx ---*/ - -A_STATUS -htt_dxe_rx_attach(struct htt_pdev_t *pdev); - -void -htt_dxe_rx_detach(struct htt_dxe_pdev_t *pdev); - -void -htt_dxe_rx(void *context, adf_nbuf_t rx_msdus, E_HIFDXE_CHANNELTYPE chan); - -void -htt_dxe_rx_ctrl(void *context, adf_nbuf_t rx_ctrl_msg); - -#if HTT_DXE_RX_LOG -#define HTT_DXE_RX_REORDER_LOG_INIT htt_dxe_rx_reorder_log_init -void htt_dxe_rx_reorder_log_init(struct htt_pdev_t *pdev); -#define HTT_DXE_RX_REORDER_LOG_ADD htt_dxe_rx_reorder_log_add -void -htt_dxe_rx_reorder_log_add( - struct htt_pdev_t *pdev, - u_int16_t peer_id, - u_int8_t tid, - isoc_rx_bd_t *rx_bd); - -#else -#define HTT_DXE_RX_REORDER_LOG_INIT(pdev) /* no-op */ -#define HTT_DXE_RX_REORDER_LOG_ADD(pdev, peer_id, tid, rx_bd) /* no-op */ -#endif /* HTT_DXE_RX_LOG */ - -/*--- t2h ---*/ - -void -htt_dxe_t2h_msg_handler(void *context, adf_nbuf_t htt_t2h_msg); - - -#endif /* _HTT_DXE_INTERNAL__H_ */ diff --git a/CORE/DXE/htt_dxe_rx.c b/CORE/DXE/htt_dxe_rx.c deleted file mode 100644 index 98c670559f73..000000000000 --- a/CORE/DXE/htt_dxe_rx.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** - * @file htt_dxe_rx.c - * @brief Implement receive aspects of HTT. - * @details - * This file contains three categories of HTT rx code: - * 1. An abstraction of the rx descriptor - * 2. Functions for providing access to the (series of) - * rx descriptor(s) and rx frame(s) associated with - * an rx indication message. - * 3. Functions for receiving rx callbacks from the underlying - * dmux_dxe and hif_dxe layers. - */ - -/* OS utility / primitive abstraction header files */ -#include <adf_os_mem.h> /* adf_os_mem_alloc,free, etc. */ -#include <adf_os_util.h> /* adf_os_assert */ -#include <adf_os_types.h> /* adf_os_print */ -#include <adf_nbuf.h> /* adf_nbuf_t, etc. */ - -#include <athdefs.h> /* A_STATUS */ -#include <isoc_hw_desc.h> /* isoc_rx_bd_t, etc. */ -#include <ieee80211.h> /* IEEE80211_FC0_SUBTYPE_BAR, ieee80211_frame */ -#include <enet.h> /* ethernet_hdr_t */ - -/* API header files to other modules called from this file */ -#include <dmux_dxe_api.h> /* dmux_dxe_attach, etc. */ -#include <htt_isoc.h> /* Rx BD format */ -#include <hif_dxe.h> /* E_HIFDXE_CHANNELTYPE */ -#include <ol_htt_rx_api.h> /* htt_rx_msdu_desc_free */ -#include <ol_txrx_htt_api.h> /* ol_rx_indication_handler */ - -/* internal header files */ -#include <htt_dxe_types.h> /* htt_dxe_pdev_t, etc */ -#include <htt_dxe_internal.h> /* HTT_DXE_ASSERT */ - - -/* - * If bit 0 of the first byte of the MAC address is set, then the address - * is multicast or broadcast rather than unicast. - */ -#define HTT_DXE_IS_MCAST_MAC_ADDR(mac_addr) ((*mac_addr) & 0x1) - -static int -htt_dxe_reorder_opcode_is_flush(isoc_rx_opcode reorder_opcode); - - -#if HTT_DXE_RX_LOG -#define HTT_DXE_RX_PSEUDO_OPCODE_DELBA 99 -char *htt_dxe_rx_reorder_opcode_str(unsigned reorder_opcode) -{ - switch (reorder_opcode) { - case ISOC_RX_OPCODE_INVALID: - return "invld"; - case ISOC_RX_OPCODE_QUEUECUR_FWDBUF: - return "QC,FB"; - case ISOC_RX_OPCODE_FWDBUF_FWDCUR: - return "FB,FC"; - case ISOC_RX_OPCODE_QUEUECUR: - return " QC "; - case ISOC_RX_OPCODE_FWDBUF_QUEUECUR: - return "FB,QC"; - case ISOC_RX_OPCODE_FWDBUF_DROPCUR: - return "FB,DC"; - case ISOC_RX_OPCODE_FWDALL_DROPCUR: - return "FA,DC"; - case ISOC_RX_OPCODE_FWDALL_QUEUECUR: - return "FA,QC"; - case ISOC_RX_OPCODE_TEARDOWN: - return "trdwn"; - case ISOC_RX_OPCODE_DROPCUR: - return " DC "; - case HTT_DXE_RX_PSEUDO_OPCODE_DELBA: - return "delba"; - default: - return " n/a "; - }; -} -#endif /* HTT_DXE_RX_LOG */ - -void -htt_dxe_rx_frm_dump(adf_nbuf_t rx_msdu, int max) -{ - u_int8_t *data; - int i; - - if (adf_nbuf_len(rx_msdu) < max) { - max = adf_nbuf_len(rx_msdu); - } - adf_os_print("rx frame contents (bytes 0-%d of %d):\n ", - max - 1, (int) adf_nbuf_len(rx_msdu)); - data = adf_nbuf_data(rx_msdu); - for (i = 1; max > 0; i++, max--) { - adf_os_print("0x%02x ", *data++); - if (i == 12) { - i = 0; - adf_os_print("\n "); - } - } - adf_os_print("\n"); -} - - -/*--- rx indication event functions -----------------------------------------*/ - -static inline isoc_rx_bd_t * -htt_dxe_rx_nbuf_prep(adf_nbuf_t rx_msdu) -{ - isoc_rx_bd_t *rx_bd; - - - /* the rx descriptor (Rx BD) is at the front of the rx network buffer */ - rx_bd = (isoc_rx_bd_t *) adf_nbuf_data(rx_msdu); - - /* FOR NOW, operate on the Rx BD in its original location. - * TBD: - * If the original location is uncacheable, make a copy in regular memory, - * and operate on that copy? - */ - - /* - * The dmux_dxe code already handled endianness conversion on the Rx BD; - * no further endianness correction is needed. - */ - - /* set the length of the network buffer */ - adf_nbuf_put_tail(rx_msdu, rx_bd->mpdu_header_offset + rx_bd->mpdu_length); - - /* advance the data pointer to the L2 header (skip the Rx BD) */ - adf_nbuf_pull_head(rx_msdu, rx_bd->mpdu_header_offset); - - //isoc_rx_bd_dump(rx_bd); - //htt_dxe_rx_frm_dump(rx_msdu, 64); - - return rx_bd; -} - -void -htt_dxe_rx_discard_pending(struct htt_pdev_t *pdev, int chan_idx) -{ - adf_nbuf_t pending = pdev->rx.pending_amsdus[chan_idx].head; - while (pending) { - adf_nbuf_t next = adf_nbuf_next(pending); - htt_rx_msdu_desc_free(pdev, pending); - pending = next; - } - pdev->rx.pending_amsdus[chan_idx].head = - pdev->rx.pending_amsdus[chan_idx].tail = NULL; -} - -static inline void -htt_dxe_rx_pending_append( - struct htt_dxe_pdev_t *pdev, - int chan_idx, - adf_nbuf_t rx_msdu) -{ - if (!pdev->rx.pending_amsdus[chan_idx].head) { - pdev->rx.pending_amsdus[chan_idx].head = rx_msdu; - } else { - adf_nbuf_set_next(pdev->rx.pending_amsdus[chan_idx].tail, rx_msdu); - } - pdev->rx.pending_amsdus[chan_idx].tail = rx_msdu; -} - -#if 1 /* for now, support 2 parallel rx data channels */ -#define HTT_DXE_RX_CHAN(chan) ((chan) == HIFDXE_CHANNEL_RX_LOW_PRI ? 0 : 1) -#else -#define HTT_DXE_RX_CHAN(chan) \ - 0; \ - adf_os_assert((chan) == HIFDXE_CHANNEL_RX_LOW_PRI) -#endif - -void -htt_dxe_rx(void *context, adf_nbuf_t rx_msdu, E_HIFDXE_CHANNELTYPE chan) -{ - struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; - int chan_idx; - - chan_idx = HTT_DXE_RX_CHAN(chan); - - /* the delivery list should start empty and end up empty */ - adf_os_assert(pdev->rx.delivery.head == NULL); - - while (rx_msdu) { - u_int16_t peer_id; - u_int8_t vdev_id; - isoc_rx_bd_t *rx_bd; - adf_nbuf_t next; - struct htt_dxe_peer_t *peer; - struct htt_dxe_vdev_t *vdev; - - next = adf_nbuf_next(rx_msdu); - adf_nbuf_set_next(rx_msdu, NULL); - - rx_bd = htt_dxe_rx_nbuf_prep(rx_msdu); - - HTT_DXE_ASSERT2( - rx_bd->reorder_opcode != ISOC_RX_OPCODE_TEARDOWN && - rx_bd->reorder_opcode != ISOC_RX_OPCODE_DROPCUR && - rx_bd->reorder_opcode != ISOC_RX_OPCODE_FWDBUF_DROPCUR && - rx_bd->reorder_opcode != ISOC_RX_OPCODE_FWDALL_DROPCUR); - - HTT_DXE_ASSERT2(!rx_bd->addr2_invalid); - peer_id = rx_bd->addr2_index; - peer = &pdev->peers[peer_id]; - vdev_id = peer->vdev_id; - vdev = &pdev->vdevs[vdev_id]; - - /* - * STA: discard multicasts that are echoes of frames the STA sent. - */ - if (vdev->op_mode == htt_op_mode_sta && - rx_bd->not_unicast && - rx_bd->addr3_index == vdev_id) - { - rx_bd->sw_flag_discard = 1; - } else { - rx_bd->sw_flag_discard = 0; - } - - /* - * If this is an AP and it has received a frame with a - * multicast/broadcast destination address, then it needs to - * transmit this received frame, so that it will be broadcast - * throughout the BSS (the rx frame was unicast to the AP's RA). - * This is referred to as "multicast echo". - */ - if (vdev->op_mode == htt_op_mode_ap) { - u_int8_t *dest_addr; - u_int8_t *l2_hdr_ptr; - - l2_hdr_ptr = ((u_int8_t *) rx_bd) + rx_bd->mpdu_header_offset; - if (rx_bd->frame_translate) { - /* frame is in 802.3 format */ - dest_addr = ((struct ethernet_hdr_t *) l2_hdr_ptr)->dest_addr; - } else { - if ((!rx_bd->amsdu) || rx_bd->amsdu_first) { - /* - * initial MSDU of an A-MSDU is in 802.11 format; - * for STA->AP, DA is addr3 - */ - dest_addr = - ((struct ieee80211_frame *) l2_hdr_ptr)->i_addr3; - } else { - /* subsequent MSDUs of an A-MSU are in 802.3 format */ - dest_addr = - ((struct ethernet_hdr_t *) l2_hdr_ptr)->dest_addr; - } - } - rx_bd->sw_flag_forward = - HTT_DXE_IS_MCAST_MAC_ADDR(dest_addr) ? 1 : 0; - } else { - rx_bd->sw_flag_forward = 0; - } - - /* determine whether this MSDU completes a MPDU / A-MSDU */ - if (!rx_bd->amsdu) { - /* there should be no old subframes in the pending list */ - if (pdev->rx.pending_amsdus[chan_idx].head) { - adf_os_print( - "Error: discarding incomplete A-MSDU " - "that was followed by non-A-MSDU\n"); - htt_dxe_rx_discard_pending(pdev, chan_idx); - } - pdev->rx.delivery.head = - pdev->rx.delivery.tail = rx_msdu; - } else { - /* - * Sanity checks: - * If this is the first subframe, then the pending list - * should be empty. - * If this is not the first subframe, the pending list - * should not be empty. - */ - if (rx_bd->amsdu_first) { - if (pdev->rx.pending_amsdus[chan_idx].head) { - adf_os_print( - "Error: discarding incomplete A-MSDU " - "that was followed by a new A-MSDU\n"); - htt_dxe_rx_discard_pending(pdev, chan_idx); - } - } else { - if (!pdev->rx.pending_amsdus[chan_idx].head) { - adf_os_print( - "Error: discarding non-initial A-MSDU subframe " - "which had no initial subframe\n"); - htt_rx_msdu_desc_free(pdev, rx_msdu); - goto loop_end; - } - } - - htt_dxe_rx_pending_append(pdev, chan_idx, rx_msdu); - - if (rx_bd->amsdu_last) { - /* - * Move the complete MPDU from the pending location - * to the delivery location. - */ - pdev->rx.delivery.head = pdev->rx.pending_amsdus[chan_idx].head; - pdev->rx.delivery.tail = pdev->rx.pending_amsdus[chan_idx].tail; - pdev->rx.pending_amsdus[chan_idx].head = - pdev->rx.pending_amsdus[chan_idx].tail = NULL; - } - } - if (pdev->rx.delivery.head) { - u_int8_t tid; - /* - * Send an rx indication for the completed A-MSDU to txrx. - * Note that the txrx SW will issue several calls to htt_dxe - * inside this function call. - */ - rx_bd = (isoc_rx_bd_t *) adf_nbuf_head(pdev->rx.delivery.head); - - /* - * The TA (transmitter address) specifies which peer sent - * this data frame. - * Since we only can receive data frames once we're - * associated, the peer index based on the TA should always - * be valid. - */ - /* - * There should never be a frame rx from an uninitialized - * peer object. Do a sanity check that the peer object - * has been initialized via a PEER_INFO message. - */ - HTT_DXE_ASSERT2(pdev->peers[peer_id].valid); - - /* TID */ - if (rx_bd->frame_type_subtype & IEEE80211_FC0_SUBTYPE_QOS) { - tid = rx_bd->tid; - } else { - tid = rx_bd->not_unicast ? OL_HTT_TID_NON_QOS_MCAST_BCAST : - OL_HTT_TID_NON_QOS_UNICAST; - } - HTT_DXE_RX_REORDER_LOG_ADD(pdev, peer_id, tid, rx_bd); - - /* remember which rx ind is being handled */ - pdev->rx.cur.rx_bd = rx_bd; - pdev->rx.cur.peer_id = peer_id; - pdev->rx.cur.tid = tid; - pdev->rx.cur.rx_aggr_enabled = - ((pdev->peers[peer_id].rx_aggr_enabled_tids_bitmap >> tid) & 0x1); - - if (pdev->rx.cur.rx_aggr_enabled && - (rx_bd->reorder_opcode == ISOC_RX_OPCODE_INVALID)) - { - adf_os_print( - "Error: discarding frame " - "with reorder_opcode = ISOC_RX_OPCODE_INVALID\n"); - HTT_DXE_ASSERT2(pdev->rx.cur.rx_aggr_enabled && rx_bd->reorder_opcode != ISOC_RX_OPCODE_INVALID); - htt_rx_msdu_desc_free(pdev, rx_msdu); - goto loop_end; - } - - ol_rx_indication_handler( - pdev->txrx_pdev, NULL, peer_id, tid, 1); - } -loop_end: - rx_msdu = next; - } -} - -void -htt_dxe_rx_ctrl(void *context, adf_nbuf_t rx_ctrl_msg) -{ - struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; - - /* we expect a single control frame at a time, but iterate just in case */ - while (rx_ctrl_msg) { - isoc_rx_bd_t *rx_bd; - adf_nbuf_t next; - unsigned ctrl_bar_subtype; - u_int16_t peer_id; - unsigned idx_start, idx_end; - - /* the only control frames we expect are BAR */ - next = adf_nbuf_next(rx_ctrl_msg); - adf_nbuf_set_next(rx_ctrl_msg, NULL); - - rx_bd = (isoc_rx_bd_t *) adf_nbuf_data(rx_ctrl_msg); - - if (rx_bd->reorder_opcode != ISOC_RX_OPCODE_FWDBUF_DROPCUR && - rx_bd->reorder_opcode != ISOC_RX_OPCODE_FWDALL_DROPCUR) - { - adf_os_print("Warning: unexpected rx reorder opcode (%d)", - rx_bd->reorder_opcode); - goto loop_end; - } - - ctrl_bar_subtype = IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_BAR; - if (rx_bd->frame_type_subtype != ctrl_bar_subtype) { - adf_os_print("Warning: unexpected control frame (%#x)", - rx_bd->frame_type_subtype); - goto loop_end; - } - - /* - * Flush MPDUs queued in the rx reorder array which are not covered - * by the repositioned block ack window. - */ - peer_id = rx_bd->addr2_index; - idx_start = 0xffff; /* start from where the last release left off */ - idx_end = (rx_bd->reorder_opcode == ISOC_RX_OPCODE_FWDBUF_DROPCUR) ? - rx_bd->reorder_fwd_idx : /* flush only to the specified index */ - 0xffff; /* flush entire reorder array */ - - HTT_DXE_RX_REORDER_LOG_ADD(pdev, peer_id, rx_bd->tid, rx_bd); - - ol_rx_flush_handler( - pdev->txrx_pdev, peer_id, rx_bd->tid, - idx_start, idx_end, htt_rx_flush_release); - -loop_end: - htt_rx_desc_frame_free(pdev, rx_ctrl_msg); - rx_ctrl_msg = next; - } -} - -/*--- rx indication info functions ------------------------------------------*/ - -static int -htt_dxe_reorder_opcode_is_flush(isoc_rx_opcode reorder_opcode) -{ - switch (reorder_opcode) - { - case ISOC_RX_OPCODE_QUEUECUR_FWDBUF: - case ISOC_RX_OPCODE_QUEUECUR: - return 0; - case ISOC_RX_OPCODE_FWDBUF_FWDCUR: - case ISOC_RX_OPCODE_FWDBUF_QUEUECUR: - case ISOC_RX_OPCODE_FWDBUF_DROPCUR: - case ISOC_RX_OPCODE_FWDALL_DROPCUR: - case ISOC_RX_OPCODE_FWDALL_QUEUECUR: - return 1; - default: - adf_os_print( - "Warning: %s unexpected opcode (%d)\n", __func__, reorder_opcode); - return 0; - }; -} - -static int -htt_dxe_reorder_opcode_is_release(isoc_rx_opcode reorder_opcode) -{ - switch (reorder_opcode) - { - case ISOC_RX_OPCODE_QUEUECUR_FWDBUF: - case ISOC_RX_OPCODE_FWDBUF_FWDCUR: - return 1; - case ISOC_RX_OPCODE_FWDBUF_QUEUECUR: - case ISOC_RX_OPCODE_QUEUECUR: - case ISOC_RX_OPCODE_FWDBUF_DROPCUR: - case ISOC_RX_OPCODE_FWDALL_DROPCUR: - case ISOC_RX_OPCODE_FWDALL_QUEUECUR: - return 0; - default: - adf_os_print( - "Warning: %s unexpected opcode (%d)\n", __func__, reorder_opcode); - return 0; - - }; -} - -int -htt_rx_ind_flush(struct htt_pdev_t *pdev, adf_nbuf_t rx_ind_msg) -{ - /* check whether the current peer-TID has aggregation enabled */ - if (!pdev->rx.cur.rx_aggr_enabled) { - return 0; /* flush doesn't apply unless aggregation is enabled */ - } - - /* - * The rx opcode specifies whether to flush old MPDUs before processing - * new ones. - */ - return htt_dxe_reorder_opcode_is_flush(pdev->rx.cur.rx_bd->reorder_opcode); -} - -void -htt_rx_ind_flush_seq_num_range( - struct htt_pdev_t *pdev, - adf_nbuf_t rx_ind_msg, - unsigned *seq_num_start, - unsigned *seq_num_end) -{ - isoc_rx_opcode reorder_opcode = pdev->rx.cur.rx_bd->reorder_opcode; - - /* see if the opcode specifies to release all the queued MPDUs */ - if (/* reorder_opcode == ISOC_RX_OPCODE_FWDALL_DROPCUR || */ // n/a - BAR - reorder_opcode == ISOC_RX_OPCODE_FWDALL_QUEUECUR) { - *seq_num_start = 0xffff; - *seq_num_end = 0xffff; - return; - } - - /* the range to flush is specified by the reorder_fwd_idx */ - *seq_num_start = 0xffff; /* start from the last-released sequence number */ - *seq_num_end = pdev->rx.cur.rx_bd->reorder_fwd_idx; -} - -int -htt_rx_ind_release(struct htt_pdev_t *pdev, adf_nbuf_t rx_ind_msg) -{ - /* check whether the current peer-TID has aggregation enabled */ - if (!pdev->rx.cur.rx_aggr_enabled) { - return 1; /* release always applies if aggregation is not enabled */ - } - - /* the rx opcode specifies whether to release queued MPDUs */ - return - htt_dxe_reorder_opcode_is_release(pdev->rx.cur.rx_bd->reorder_opcode); -} - -void -htt_rx_ind_release_seq_num_range( - struct htt_pdev_t *pdev, - adf_nbuf_t rx_ind_msg, - unsigned *seq_num_start, - unsigned *seq_num_end) -{ - if (!pdev->rx.cur.rx_aggr_enabled) { - /* - * For non-aggregation, rx reorder array has a single element, so - * the sequence number range is not relevant. - * Just for clarity, return a well-defined value (0). - */ - *seq_num_start = 0; - *seq_num_end = 1; - return; - } - - /* release up to (but not including) the reorder_fwd_idx */ - *seq_num_start = 0xffff; /* start from the last-released sequence number */ - *seq_num_end = pdev->rx.cur.rx_bd->reorder_fwd_idx; -} - -void -htt_rx_ind_mpdu_range_info( - struct htt_pdev_t *pdev, - adf_nbuf_t rx_ind_msg, - int mpdu_range_num, - enum htt_rx_status *status, - int *mpdu_count) -{ - *mpdu_count = 1; /* htt_dxe_rx delivers one MPDU at a time */ - *status = htt_rx_status_ok; /* error frames are filtered out by HW */ -} - -int16_t -htt_rx_ind_rssi_dbm(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) -{ - /* - * The RSSIs only come from the rx descriptors (Rx BDs). - * Return an invalid value to show that there is no separate - * RSSI provided as a field in the HTT T2H RX_IND message. - */ - return HTT_RSSI_INVALID; -} - -/*--- rx descriptor field access functions ----------------------------------*/ -/* - * These functions need to use bit masks and shifts to extract fields - * from the rx descriptors, rather than directly using the bitfields. - * For example, use - * (desc & FIELD_MASK) >> FIELD_LSB - * rather than - * desc.field - * This allows the functions to work correctly on either little-endian - * machines (no endianness conversion needed) or big-endian machines - * (endianness conversion provided automatically by the HW DMA's - * byte-swizzling). - */ -u_int16_t -(*htt_rx_mpdu_desc_seq_num)(htt_pdev_handle pdev, void *mpdu_desc); -u_int16_t -_htt_rx_mpdu_desc_seq_num(htt_pdev_handle pdev, void *mpdu_desc) -{ - isoc_rx_bd_t *rx_bd = mpdu_desc; - return (u_int16_t)rx_bd->current_pkt_seqno; -} - -int -htt_rx_mpdu_desc_reorder_idx(htt_pdev_handle pdev, void *mpdu_desc) -{ - isoc_rx_bd_t *rx_bd; - - if (!pdev->rx.cur.rx_aggr_enabled) { - /* no aggregation - rx reorder array only has a single element (0) */ - return 0; - } - rx_bd = mpdu_desc; - return rx_bd->reorder_slot_idx; -} - -void -(*htt_rx_mpdu_desc_pn)( - htt_pdev_handle pdev, - void *mpdu_desc, - union htt_rx_pn_t *pn, - int pn_len_bits); -void -_htt_rx_mpdu_desc_pn( - htt_pdev_handle pdev, - void *mpdu_desc, - union htt_rx_pn_t *pn, - int pn_len_bits) -{ - isoc_rx_bd_t *rx_bd = mpdu_desc; - u_int32_t iv32; - u_int16_t iv16; - - switch (pn_len_bits) { - case 24: - adf_os_print( - "Error: PN length (%d bits) not implemented\n", pn_len_bits); - pn->pn24 = 0; - adf_os_assert(0); - break; - case 48: - /* - * 48-bit replay counter is created as follows - * from RX BD 6 byte PMI command: - * Addr : AES/TKIP - * 0x38 : pn3/tsc3 - * 0x39 : pn2/tsc2 - * 0x3a : pn1/tsc1 - * 0x3b : pn0/tsc0 - * - * 0x3c : pn5/tsc5 - * 0x3d : pn4/tsc4 - */ - iv32 = rx_bd->pmi_cmd4to23[4]; /* PN0-3 */ - iv16 = rx_bd->pmi_cmd24to25; /* PN4-5 */ - pn->pn48 = (((u_int64_t)iv16) << 32) | iv32; - break; - - case 128: - adf_os_print( - "Error: PN length (%d bits) not implemented\n", pn_len_bits); - pn->pn128[0] = 0; - pn->pn128[1] = 0; - adf_os_assert(0); - break; - default: - adf_os_print( - "Error: invalid length spec (%d bits) for PN\n", pn_len_bits); - }; -} - -u_int32_t -htt_rx_mpdu_desc_tsf32( - htt_pdev_handle pdev, - void *mpdu_desc) -{ - isoc_rx_bd_t *rx_bd = mpdu_desc; - return rx_bd->rx_timestamp; -} - -a_bool_t -(*htt_rx_msdu_desc_completes_mpdu)(htt_pdev_handle pdev, void *msdu_desc); -a_bool_t -_htt_rx_msdu_desc_completes_mpdu(htt_pdev_handle pdev, void *msdu_desc) -{ - isoc_rx_bd_t *rx_bd = msdu_desc; - - if (!rx_bd->amsdu) { - return A_TRUE; - } else { - return rx_bd->amsdu_last ? A_TRUE : A_FALSE; - } -} - -a_bool_t -(*htt_rx_mpdu_is_encrypted)(htt_pdev_handle pdev, void *mpdu_desc); -a_bool_t -_htt_rx_mpdu_is_encrypted(htt_pdev_handle pdev, void *msdu_desc) -{ - isoc_rx_bd_t *rx_bd = msdu_desc; - /* FIXME: Does this flag mean that this RX packet is a encrypted pakcet */ - return rx_bd->dpu_no_encrypt ? A_FALSE : A_TRUE; -} - -a_bool_t -(*htt_rx_msdu_first_msdu_flag)(htt_pdev_handle pdev, void *msdu_desc); -a_bool_t -_htt_rx_msdu_first_msdu_flag(htt_pdev_handle pdev, void *msdu_desc) -{ - isoc_rx_bd_t *rx_bd = msdu_desc; - return (a_bool_t)(rx_bd->amsdu_first); // This casts is safe only because - // amsdu_first is one bit wide - // and a_bool_t is only 0 or 1 -} - -#define HTT_DXE_RSSI_TO_DBM(rssi) rssi /* FIX THIS */ -int16_t -htt_rx_mpdu_desc_rssi_dbm(htt_pdev_handle pdev, void *mpdu_desc) -{ - isoc_rx_bd_t *rx_bd = mpdu_desc; - u_int8_t rssi; - - /* - * * Return the RSSI only for the first MPDU within an A-MPDU, and the - * * first MSDU within an A-MSDU. - * */ - if ((rx_bd->rxp_flags_ampdu_flag && ! rx_bd->rxp_flags_first_mpdu) || - (rx_bd->amsdu && ! rx_bd->amsdu_first)) - { - /* not the initial subframe */ - return HTT_RSSI_INVALID; - } - /* CHECK THIS - choose whether to use rssi0, rssi1, rssi2, or rssi3 */ - rssi = rx_bd->rssi0; - if (rssi < rx_bd->rssi1) { - rssi = rx_bd->rssi1; - } - if (rssi < rx_bd->rssi2) { - rssi = rx_bd->rssi2; - } - if (rssi < rx_bd->rssi3) { - rssi = rx_bd->rssi3; - } - - return HTT_DXE_RSSI_TO_DBM(rssi); -} - -int -(*htt_rx_msdu_has_wlan_mcast_flag)(htt_pdev_handle pdev, void *msdu_desc); -int -_htt_rx_msdu_has_wlan_mcast_flag(htt_pdev_handle pdev, void *msdu_desc) -{ - isoc_rx_bd_t *rx_bd = msdu_desc; - /* - * If this is a standalone MPDU or the initial subframe of an A-MSDU, - * the frame had a 802.11 MAC header, and based on the RA in the - * 802.11 header the frame has a valid specification of WLAN multicast - * vs. unicast. - */ - return (!rx_bd->amsdu) || (rx_bd->amsdu_first); -} - -a_bool_t -(*htt_rx_msdu_is_wlan_mcast)(htt_pdev_handle pdev, void *msdu_desc); -a_bool_t -_htt_rx_msdu_is_wlan_mcast(htt_pdev_handle pdev, void *msdu_desc) -{ - isoc_rx_bd_t *rx_bd = msdu_desc; - return rx_bd->not_unicast ? A_TRUE : A_FALSE; -} - -int -(*htt_rx_msdu_is_frag)(htt_pdev_handle pdev, void *msdu_desc); -int -_htt_rx_msdu_is_frag(htt_pdev_handle pdev, void *msdu_desc) -{ - return 0; -} - -static inline int -_htt_rx_msdu_discard(htt_pdev_handle pdev, void *msdu_desc) -{ - /* check if this frame was flagged as a multicast echo - if so, discard */ - isoc_rx_bd_t *rx_bd = msdu_desc; - return rx_bd->sw_flag_discard; -} - -int -htt_rx_msdu_discard(htt_pdev_handle pdev, void *msdu_desc) -{ - return _htt_rx_msdu_discard(pdev, msdu_desc); -} - -int -_htt_rx_msdu_forward(htt_pdev_handle pdev, void *msdu_desc) -{ - /* - * Check if this frame was flagged for forwarding, due to: - * 1. AP echo of multicast frames, i.e. transmission of unicast - * rx frames that carry a multicast DA - * 2. STA to STA forwarding within an AP (NOT CURRENTLY SUPPORTED) - */ - isoc_rx_bd_t *rx_bd = msdu_desc; - return rx_bd->sw_flag_forward; -} - -int -htt_rx_msdu_forward(htt_pdev_handle pdev, void *msdu_desc) -{ - return _htt_rx_msdu_forward(pdev, msdu_desc); -} - -int -htt_rx_msdu_inspect(htt_pdev_handle pdev, void *msdu_desc) -{ -/* FIX THIS (probably okay as is) */ - return 0; -} - -void -htt_rx_msdu_actions( - htt_pdev_handle pdev, - void *msdu_desc, - int *discard, - int *forward, - int *inspect) -{ - *discard = _htt_rx_msdu_discard(pdev, msdu_desc); - *forward = _htt_rx_msdu_forward(pdev, msdu_desc); -/* FIX THIS (probably okay as is) */ - *inspect = 0; -} - -int -(*htt_rx_amsdu_pop)( - htt_pdev_handle pdev, - adf_nbuf_t rx_ind_msg, - adf_nbuf_t *head_msdu, - adf_nbuf_t *tail_msdu); -int -_htt_rx_amsdu_pop( - htt_pdev_handle pdev, - adf_nbuf_t rx_ind_msg, - adf_nbuf_t *head_msdu, - adf_nbuf_t *tail_msdu) -{ - *head_msdu = pdev->rx.delivery.head; - *tail_msdu = pdev->rx.delivery.tail; - return 0; -} - -int -(*htt_rx_offload_msdu_pop)( - htt_pdev_handle pdev, - adf_nbuf_t offload_deliver_msg, - int *vdev_id, - int *peer_id, - int *tid, - u_int8_t *fw_desc, - adf_nbuf_t *head_buf, - adf_nbuf_t *tail_buf); - -int -_htt_rx_offload_msdu_pop( - htt_pdev_handle pdev, - adf_nbuf_t offload_deliver_msg, - int *vdev_id, - int *peer_id, - int *tid, - u_int8_t *fw_desc, - adf_nbuf_t *head_buf, - adf_nbuf_t *tail_buf) -{ - return 0; -} - - -void * -(*htt_rx_mpdu_desc_list_next)(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); -void * -_htt_rx_mpdu_desc_list_next(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) -{ - adf_nbuf_t rx_msdu; - - adf_os_assert(pdev->rx.delivery.head); - rx_msdu = pdev->rx.delivery.head; - - /* - * If this MPDU is an A-MSDU, then rx.delivery.head points to the - * head of a linked-list of MSDUs comprising the A-MSDU. - * Since htt_dxe_rx currently indicates one A-MSDU at a time, - * there is no further MPDU chained on the rx.delivery list, - * so just set rx.delivery to NULL. - * If, for some reason htt_dxe_rx were changed to deliver multiple - * MPDUs at a time, then this would need to be changed to walk the - * list of MSDUs until the MSDU with rx_bd->amsdu_last is seen. - */ - pdev->rx.delivery.head = NULL; - - /* the rx netbuf has the Rx BD in its headroom */ - return adf_nbuf_head(rx_msdu); -} - -void * -(*htt_rx_msdu_desc_retrieve)(htt_pdev_handle pdev, adf_nbuf_t msdu); -void * -_htt_rx_msdu_desc_retrieve(htt_pdev_handle pdev, adf_nbuf_t msdu) -{ - /* the rx netbuf has the Rx BD in its headroom */ - return adf_nbuf_head(msdu); -} - -void -htt_rx_desc_frame_free( - htt_pdev_handle htt_pdev, - adf_nbuf_t msdu) -{ - adf_nbuf_free(msdu); -} - -void -htt_rx_msdu_desc_free(htt_pdev_handle htt_pdev, adf_nbuf_t msdu) -{ -} - -void -htt_rx_msdu_buff_replenish(htt_pdev_handle pdev) -{ -} - -void -htt_rx_get_vowext_stats(adf_nbuf_t msdu, struct vow_extstats *vowstats) -{ - /* FIXME: Need to set vowstats correctly */ -} - -u_int16_t -htt_rx_msdu_rx_desc_size_hl( - htt_pdev_handle pdev, - void *msdu_desc) -{ -/* HACK WORKAROUND - * The HL TXRX SW assumes the rx desc is present at adf_nbuf_data. - * Until that is fixed, pretend that the descriptor is zero size, - * so the call to adf_nbuf_pull_head in ol_rx_deliver will have no - * effect. - */ -return 0; -} - -adf_nbuf_t -htt_rx_restitch_mpdu_from_msdus( - htt_pdev_handle pdev, - adf_nbuf_t head_msdu, - struct ieee80211_rx_status *rx_status, - unsigned clone_not_reqd) -{ - adf_os_assert(0); - return NULL; -} - -/*--- setup / tear-down functions -------------------------------------------*/ - -A_STATUS -htt_dxe_rx_attach(struct htt_pdev_t *pdev) -{ - htt_rx_mpdu_desc_seq_num = _htt_rx_mpdu_desc_seq_num; - htt_rx_msdu_desc_completes_mpdu = _htt_rx_msdu_desc_completes_mpdu; - htt_rx_msdu_has_wlan_mcast_flag = _htt_rx_msdu_has_wlan_mcast_flag; - htt_rx_msdu_is_wlan_mcast = _htt_rx_msdu_is_wlan_mcast; - htt_rx_mpdu_desc_pn = _htt_rx_mpdu_desc_pn; - htt_rx_amsdu_pop = _htt_rx_amsdu_pop; - htt_rx_offload_msdu_pop = _htt_rx_offload_msdu_pop; - htt_rx_mpdu_desc_list_next = _htt_rx_mpdu_desc_list_next; - htt_rx_msdu_desc_retrieve = _htt_rx_msdu_desc_retrieve; - htt_rx_msdu_is_frag = _htt_rx_msdu_is_frag; - htt_rx_mpdu_is_encrypted = _htt_rx_mpdu_is_encrypted; - htt_rx_msdu_first_msdu_flag = _htt_rx_msdu_first_msdu_flag; - - HTT_DXE_RX_REORDER_LOG_INIT(pdev); - - /* The pdev object was already set to zero in htt_dxe_attach, - * so the following explicit inits of pdev->rx fields are not needed. - * pdev->rx.delivery.head = NULL; - * pdev->rx.delivery.tail = NULL; - * adf_os_mem_zero( - * &pdev->rx.pending_amsdus[0], sizeof(pdev->rx.pending_amsdus)); - */ - - return A_OK; -} - -void -htt_dxe_rx_detach(struct htt_dxe_pdev_t *pdev) -{ -} - - -char * -htt_rx_mpdu_wifi_hdr_retrieve(htt_pdev_handle pdev, void *mpdu_desc) -{ - //ToDO: Need to fix this function - adf_os_print( - "Error: %s is not implemented\n", __FUNCTION__); - return NULL; -} - -/*--- debug functions -------------------------------------------------------*/ - -#if HTT_DXE_RX_LOG - -void -htt_dxe_rx_reorder_log_init(struct htt_pdev_t *pdev) -{ - pdev->reorder_log.idx = 0; - pdev->reorder_log.wrap = 1; /* ?? */ - pdev->reorder_log.wrapped = 0; - pdev->reorder_log.enable = 1; -} - -void -htt_dxe_rx_reorder_log_add( - struct htt_pdev_t *pdev, - u_int16_t peer_id, - u_int8_t tid, - isoc_rx_bd_t *rx_bd) -{ - struct htt_dxe_rx_log_elem_t *log_elem; - - if (!pdev->reorder_log.enable || - pdev->reorder_log.idx >= HTT_DXE_RX_LOG_LEN) - { - return; - } - log_elem = &pdev->reorder_log.data[pdev->reorder_log.idx]; - - log_elem->peer_id = peer_id; - log_elem->tid = tid; - - if (rx_bd) { /* rx frame */ - log_elem->seq_num = rx_bd->current_pkt_seqno; - log_elem->reorder_opcode = rx_bd->reorder_opcode; - log_elem->slot_idx = rx_bd->reorder_slot_idx; - log_elem->fwd_idx = rx_bd->reorder_fwd_idx; - } else { /* DELBA message */ - log_elem->seq_num = -1; - log_elem->reorder_opcode = HTT_DXE_RX_PSEUDO_OPCODE_DELBA; - log_elem->slot_idx = -1; - log_elem->fwd_idx = -1; - } - - pdev->reorder_log.idx++; - if (pdev->reorder_log.idx == HTT_DXE_RX_LOG_LEN && pdev->reorder_log.wrap) { - pdev->reorder_log.idx = 0; - pdev->reorder_log.wrapped = 1; - } -} - -#define htt_dxe_rx_reorder_log_print htt_rx_reorder_log_print -void -htt_dxe_rx_reorder_log_print(struct htt_pdev_t *pdev) -{ - int num, idx; - - if (pdev->reorder_log.wrapped) { - idx = pdev->reorder_log.idx; - num = HTT_DXE_RX_LOG_LEN; - } else { - idx = 0; - num = pdev->reorder_log.idx; - } - - if (num > 0) { - adf_os_print( - "htt_dxe_rx reorder log:\n" - " " - "peer | | seq | | slot | fwd | flush | release |\n" - " " - " id | TID | num | opcode | idx | idx | y? | to | y? | to |\n" - " " - "-------------------------------------------------------------\n"); - } - while (num-- > 0) { - int is_flush, is_rel, seq_num; - unsigned reorder_opcode; - struct htt_dxe_rx_log_elem_t *log_elem; - - log_elem = &pdev->reorder_log.data[idx]; - - seq_num = log_elem->seq_num; - reorder_opcode = log_elem->reorder_opcode; - if (reorder_opcode == HTT_DXE_RX_PSEUDO_OPCODE_DELBA) { - is_flush = 1; - is_rel = 0; - } else { - is_flush = htt_dxe_reorder_opcode_is_flush(reorder_opcode); - is_rel = htt_dxe_reorder_opcode_is_release(reorder_opcode); - } - if (reorder_opcode == ISOC_RX_OPCODE_FWDBUF_DROPCUR || - reorder_opcode == ISOC_RX_OPCODE_FWDALL_DROPCUR) - { - seq_num = -1; - } - adf_os_print( - " %3d | %2d | %4d | %s | %2d | %2d |" - " %s | %2d | %s | %2d |\n", - log_elem->peer_id, - log_elem->tid, - seq_num, - htt_dxe_rx_reorder_opcode_str(reorder_opcode), - log_elem->slot_idx, - log_elem->fwd_idx, - is_flush ? "Y" : "n", - is_flush ? log_elem->fwd_idx : -1, - is_rel ? "Y" : "n", - is_rel ? log_elem->fwd_idx : -1); - idx++; - idx &= HTT_DXE_RX_LOG_LEN_MASK; - } -} - -#endif /* HTT_DXE_RX_LOG */ diff --git a/CORE/DXE/htt_dxe_t2h.c b/CORE/DXE/htt_dxe_t2h.c deleted file mode 100644 index af67595bf0a9..000000000000 --- a/CORE/DXE/htt_dxe_t2h.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** - * @file htt_dxe_t2h.c - * @brief Provide functions to process target->host HTT messages. - * @details - * This file contains functions related to target->host HTT messages. - * There are two categories of functions: - * 1. A function that receives a HTT message from HTC, and dispatches it - * based on the HTT message type. - * 2. functions that provide the info elements from specific HTT messages. - */ - -#include <htt_isoc.h> /* HTT_ISOC_T2H_MSG_TYPE, etc. */ -#include <adf_os_util.h> /* adf_os_assert */ -#include <adf_nbuf.h> /* adf_nbuf_t */ - -#include <ol_htt_rx_api.h> -#include <ol_txrx_htt_api.h> /* htt_tx_status */ - -#include <ol_cfg.h> /* ol_cfg_max_peer_id */ - -/* internal header files */ -#include <htt_dxe_types.h> -#include <htt_dxe_internal.h> - - -/* - * The HTT_T2H message payload will arrive at the host in big-endian order. - * - * Firmware - creates HTT_T2H message in little-endian order. - * DXE - byteswap while copying. HTT_T2H message now in big-endian order. - */ -#ifdef BIG_ENDIAN_HOST -/* big-endian - bytes are naturally in the correct order, no swap needed */ -#define HTT_DXE_T2H_MSG_BYTESWAP(msg, bytes) /* no-op */ -#else -/* little-endian - byte swap */ -static inline void -HTT_DXE_T2H_MSG_BYTESWAP(u_int8_t *msg, int bytes) -{ - isoc_hw_bd_swap_bytes32((char *) msg, bytes); -} -#endif /* BIG_ENDIAN_HOST */ - - -static u_int8_t * -htt_t2h_mac_addr_deswizzle(u_int8_t *tgt_mac_addr, u_int8_t *buffer) -{ -#ifdef BIG_ENDIAN_HOST - /* - * The host endianness is opposite of the target endianness. - * To make u_int32_t elements come out correctly, the target->host - * upload has swizzled the bytes in each u_int32_t element of the - * message. - * For byte-array message fields like the MAC address, this - * upload swizzling puts the bytes in the wrong order, and needs - * to be undone. - */ - buffer[0] = tgt_mac_addr[3]; - buffer[1] = tgt_mac_addr[2]; - buffer[2] = tgt_mac_addr[1]; - buffer[3] = tgt_mac_addr[0]; - buffer[4] = tgt_mac_addr[7]; - buffer[5] = tgt_mac_addr[6]; - return buffer; -#else - /* - * The host endianness matches the target endianness - - * we can use the mac addr directly from the message buffer. - */ - return tgt_mac_addr; -#endif -} - -void -htt_dxe_t2h_msg_handler(void *context, adf_nbuf_t htt_t2h_msg) -{ - struct htt_dxe_pdev_t *pdev = (struct htt_dxe_pdev_t *) context; - enum htt_isoc_t2h_msg_type msg_type; - isoc_rx_bd_t *rx_bd; - u_int8_t *msg_addr; - - rx_bd = (isoc_rx_bd_t *)adf_nbuf_data(htt_t2h_msg); - msg_addr = (u_int8_t *)rx_bd + rx_bd->mpdu_data_offset; - - /* confirm alignment */ - HTT_DXE_ASSERT3((((unsigned long) msg_addr) & 0x3) == 0); - - /* Convert HTT_T2H message from little-endian to host format */ - HTT_DXE_T2H_MSG_BYTESWAP(msg_addr, (rx_bd->mpdu_length + 3) & (~0x3)); - - msg_type = HTT_ISOC_T2H_MSG_TYPE_GET(msg_addr); - - switch (msg_type) { - case HTT_ISOC_T2H_MSG_TYPE_RX_ADDBA: - { - u_int16_t peer_id; - u_int16_t start_seq_num, reorder_idx; - u_int8_t tid; - u_int8_t win_sz; - u_int8_t status; - - peer_id = HTT_ISOC_T2H_ADDBA_PEER_ID_GET(msg_addr); - tid = HTT_ISOC_T2H_ADDBA_TID_GET(msg_addr); - start_seq_num = HTT_ISOC_T2H_ADDBA_START_SEQ_NUM_GET(msg_addr); - win_sz = HTT_ISOC_T2H_ADDBA_WIN_SIZE_GET(msg_addr); - status = HTT_ISOC_T2H_ADDBA_STATUS_GET(msg_addr); - - if (status == htt_isoc_addba_success) { - /* - * Remember which peer-TIDs are doing aggregation, to see - * whether the aggregation-related parts of the Rx BD - * (reorder_opcode, reorder_slot_idx, reorder_fwd_idx) - * are valid. - */ - pdev->peers[peer_id].rx_aggr_enabled_tids_bitmap |= (1 << tid); - } - reorder_idx = start_seq_num % win_sz; - ol_rx_addba_handler( - pdev->txrx_pdev, peer_id, tid, win_sz, reorder_idx, - status != htt_isoc_addba_success); - break; - } - case HTT_ISOC_T2H_MSG_TYPE_RX_DELBA: - { - u_int16_t peer_id; - u_int8_t tid; - - peer_id = HTT_ISOC_T2H_DELBA_PEER_ID_GET(msg_addr); - tid = HTT_ISOC_T2H_DELBA_TID_GET(msg_addr); - - pdev->peers[peer_id].rx_aggr_enabled_tids_bitmap &= ~(1 << tid); - - /* - * Before deleting the rx reorder array, we need to - * flush (i.e. release, not drop) any rx MPDUs that are - * currently waiting in the rx reorder array for missing - * prior MPDUs to arrive. - * Now that the rx aggregation is terminated, the missing - * MPDUs will not arrive, so any waiting MPDUs should be - * released for the remaining steps of rx processing. - */ - HTT_DXE_RX_REORDER_LOG_ADD(pdev, peer_id, tid, NULL); - ol_rx_flush_handler( - pdev->txrx_pdev, peer_id, tid, - 0xffff, 0xffff, htt_rx_flush_release); - ol_rx_delba_handler(pdev->txrx_pdev, peer_id, tid); - - break; - } - case HTT_ISOC_T2H_MSG_TYPE_PEER_INFO: - { - struct htt_dxe_peer_t *peer; - u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; - u_int8_t *peer_mac_addr; - u_int16_t peer_id; - u_int8_t vdev_id; - - /* extract fields relevent for txrx */ - peer_id = HTT_ISOC_T2H_PEER_INFO_PEER_ID_GET(msg_addr); - HTT_DXE_ASSERT3(peer_id <= ol_cfg_max_peer_id(pdev->ctrl_pdev)); - vdev_id = HTT_ISOC_T2H_PEER_INFO_VDEV_ID_GET(msg_addr); - HTT_DXE_ASSERT3(vdev_id < ol_cfg_max_vdevs(pdev->ctrl_pdev)); - peer_mac_addr = htt_t2h_mac_addr_deswizzle( - msg_addr + sizeof(u_int32_t) * - HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_OFFSET32 + - (HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_S >> 3), - mac_addr_deswizzle_buf); - - /* extract fields relevant just for htt_dxe */ - peer = &pdev->peers[peer_id]; - peer->vdev_id = vdev_id; - peer->type = HTT_ISOC_T2H_PEER_INFO_PEER_TYPE_GET(msg_addr); - - peer->security[HTT_DXE_PEER_KEY_UCAST].id = - HTT_ISOC_T2H_PEER_INFO_DPU_IDX_GET(msg_addr); - peer->security[HTT_DXE_PEER_KEY_UCAST].signature = - HTT_ISOC_T2H_PEER_INFO_DPU_SIG_GET(msg_addr); - - peer->security[HTT_DXE_PEER_KEY_MCAST].id = - HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_IDX_GET(msg_addr); - peer->security[HTT_DXE_PEER_KEY_MCAST].signature = - HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_SIG_GET(msg_addr); - - peer->security[HTT_DXE_PEER_KEY_MGMT].id = - HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_IDX_GET(msg_addr); - peer->security[HTT_DXE_PEER_KEY_MGMT].signature = - HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_SIG_GET(msg_addr); - - /* - * The qos_capable flag is already set to its default: 0 - * If the peer is found to be QoS capable, then this will - * be specified through a call to htt_dxe_peer_qos_update. - */ - - peer->robust_mgmt = - HTT_ISOC_T2H_PEER_INFO_RMF_ENABLED_GET(msg_addr); - - peer->rx_aggr_enabled_tids_bitmap = 0x0; /* no aggr until ADDBA */ - - /* if this is a real peer, inform txrx */ - /* peer_info may come multiple times for the same peer. - we shall only pass it once to upper layer*/ - /* ToDO: We need to check if a peer needs to be updated multiple times - If not, this check for valid bit is not needed. With other fixes, FW - only sends one indication per peer. - */ - if (peer->type == HTT_ISOC_T2H_PEER_TYPE_ASSOC && !peer->valid) { - /*Assign it here to keep the sequence intact*/ - peer->valid = 1; - ol_rx_peer_map_handler( - pdev->txrx_pdev, peer_id, vdev_id, peer_mac_addr, - 0 /* no tx until PEER_TX_READY is received */); - } else if (peer->type == HTT_ISOC_T2H_PEER_TYPE_SELF) { - pdev->vdevs[vdev_id].self_peer_id = peer_id; - } else if (peer->type == HTT_ISOC_T2H_PEER_TYPE_BCAST) { - pdev->vdevs[vdev_id].bcast_peer_id = peer_id; - } - peer->valid = 1; - break; - } - case HTT_ISOC_T2H_MSG_TYPE_PEER_TX_READY: - { - struct htt_dxe_peer_t *peer; - u_int16_t peer_id; - - peer_id = HTT_ISOC_T2H_PEER_TX_READY_PEER_ID_GET(msg_addr); - HTT_DXE_ASSERT3(peer_id <= ol_cfg_max_peer_id(pdev->ctrl_pdev)); - peer = &pdev->peers[peer_id]; - HTT_DXE_ASSERT3(peer->valid); - - /* if this is a real peer, inform txrx */ - if (peer->type == HTT_ISOC_T2H_PEER_TYPE_ASSOC) { - ol_txrx_peer_tx_ready_handler(pdev->txrx_pdev, peer_id); - } - break; - } - case HTT_ISOC_T2H_MSG_TYPE_PEER_UNMAP: - { - struct htt_dxe_peer_t *peer; - u_int16_t peer_id; - - peer_id = HTT_ISOC_T2H_PEER_UNMAP_PEER_ID_GET(msg_addr); - HTT_DXE_ASSERT3(peer_id <= ol_cfg_max_peer_id(pdev->ctrl_pdev)); - peer = &pdev->peers[peer_id]; - peer->valid = 0; - /* - * Set the qos_capable flag back to its default value (0). - */ - peer->qos_capable = 0; - - /* if this is a real peer, inform txrx */ - if (peer->type == HTT_ISOC_T2H_PEER_TYPE_ASSOC) { - ol_rx_peer_unmap_handler(pdev->txrx_pdev, peer_id); - } - break; - } - case HTT_ISOC_T2H_MSG_TYPE_TX_COMPL_IND: - { -/* FILL IN HERE */ - break; - } - case HTT_ISOC_T2H_MSG_TYPE_SEC_IND: - { - u_int16_t peer_id; - enum htt_sec_type sec_type; - int is_unicast; - u_int32_t mic_key[2]; - - peer_id = HTT_ISOC_T2H_SEC_IND_PEER_ID_GET(msg_addr); - sec_type = HTT_ISOC_T2H_SEC_IND_SEC_TYPE_GET(msg_addr); - is_unicast = HTT_ISOC_T2H_SEC_IND_IS_UNICAST_GET(msg_addr); - mic_key[0] = HTT_ISOC_T2H_SEC_IND_MIC1_GET(msg_addr); - mic_key[1] = HTT_ISOC_T2H_SEC_IND_MIC2_GET(msg_addr); - - adf_os_print("SEC_IND (%d) peer_id %d sec_type %d is_unicast %d\n", msg_type, peer_id,sec_type, is_unicast ); - - ol_rx_sec_ind_handler(pdev->txrx_pdev, peer_id, sec_type, - is_unicast, mic_key, NULL); - - break; - } - default: - adf_os_print("Error: Unknown HTT_T2H message type = %d\n", msg_type); - adf_os_assert(0); - break; - }; - - /* Free the indication buffer */ - adf_nbuf_free(htt_t2h_msg); -} - -/*--- target->host HTT message Info Element access methods ------------------*/ - -/* htt_rx_frag_ind - - * The fragment indication not relevant for htt_dxe, since defragmentation - * is handled within the HW. - * Just provide a dummy function for txrx to link against. - */ -void -htt_rx_frag_ind_flush_seq_num_range( - struct htt_dxe_pdev_t *pdev, - adf_nbuf_t rx_frag_ind_msg, - int *seq_num_start, - int *seq_num_end) -{ - adf_os_assert(0); -} - diff --git a/CORE/DXE/htt_dxe_tx.c b/CORE/DXE/htt_dxe_tx.c deleted file mode 100644 index 0a072a3713fd..000000000000 --- a/CORE/DXE/htt_dxe_tx.c +++ /dev/null @@ -1,809 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** - * @file htt_dxe_tx.c - * @brief Implement transmit aspects of HTT. - * @details - * This file contains three categories of HTT tx code: - * 1. An abstraction of the tx descriptor - * 2. Functions for allocating and freeing HTT tx descriptors. - * 3. The function that accepts a tx frame from txrx and sends the - * tx frame to hif_dxe. - */ -#include <osdep.h> /* u_int32_t, offsetof, etc. */ -#include <adf_os_types.h> /* adf_os_dma_addr_t */ -#include <adf_os_mem.h> /* adf_os_mem_alloc_consistent,free_consistent */ -#include <adf_os_util.h> /* adf_os_likely */ -#include <adf_nbuf.h> /* adf_nbuf_t, etc. */ - -#include <athdefs.h> /* A_STATUS */ - -#include <ol_cfg.h> /* ol_cfg_sw_encap_hdr_max_size */ -#include <hif_dxe.h> /* hif_dxe_send */ -#include <isoc_hw_desc.h> /* isoc_tx_bd_t, etc. */ -#include <ol_htt_tx_api.h> -#include <ol_txrx_htt_api.h> /* ol_tx_download_done_hl_free, etc. */ - -#include <htt_dxe_internal.h> /* HTT_DXE_ASSERT */ - -/*--- utilities -------------------------------------------------------------*/ - -#ifndef ARRAY_LEN -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) -#endif - - -/*--- constants -------------------------------------------------------------*/ - -enum { - HTT_DXE_TX_SSN_FILL_HOST = 0, - HTT_DXE_TX_SSN_FILL_DPU_NON_QOS = 1, - HTT_DXE_TX_SSN_FILL_DPU_QOS = 2, -}; - -enum { - HTT_DXE_TX_BDRATE_DEFAULT = 0, - HTT_DXE_TX_BDRATE_BCDATA_FRAME = 1, /* unused */ - HTT_DXE_TX_BDRATE_BCMGMT_FRAME = 2, - HTT_DXE_TX_BDRATE_CTRL_FRAME = 3, -}; - -enum { - HTT_DXE_ACK_POLICY_ACK = 0, - HTT_DXE_ACK_POLICY_NO_ACK = 1, -}; - -enum { - HTT_DXE_TX_BTQM_QID0 = 0, - HTT_DXE_TX_BTQM_QID1 = 1, - HTT_DXE_TX_BTQM_QID2 = 2, - HTT_DXE_TX_BTQM_QID3 = 3, - HTT_DXE_TX_BTQM_QID4 = 4, - HTT_DXE_TX_BTQM_QID5 = 5, - HTT_DXE_TX_BTQM_QID6 = 6, - HTT_DXE_TX_BTQM_QID7 = 7, - HTT_DXE_TX_BTQM_QID8 = 8, - HTT_DXE_TX_BTQM_QID9 = 9, - HTT_DXE_TX_BTQM_QID10 = 10, - - HTT_DXE_TX_BTQM_QUEUE_SELF_STA_BCAST_MGMT = HTT_DXE_TX_BTQM_QID10, - HTT_DXE_TX_BTQM_QUEUE_SELF_STA_UCAST_MGMT = HTT_DXE_TX_BTQM_QID9, - HTT_DXE_TX_BTQM_QUEUE_SELF_STA_UCAST_DATA = HTT_DXE_TX_BTQM_QID9, - HTT_DXE_TX_BTQM_QUEUE_TX_NON_QOS = HTT_DXE_TX_BTQM_QID8, - -}; - -enum { - HTT_DXE_TX_BMUWQ_BTQM_TX_MGMT = 25, -}; - -/*--- utility functions -----------------------------------------------------*/ - -static inline u_int16_t * -htt_dxe_tx_msdu_id_storage(adf_nbuf_t msdu) -{ - adf_os_assert(adf_nbuf_headroom(msdu) >= (sizeof(u_int16_t) * 2 - 1)); - return (u_int16_t *) (((adf_os_size_t) (adf_nbuf_head(msdu) + 1)) & ~0x1); -} - -/* - * The Tx BD is supposed to be in big-endian format. - * On a little endian host, the Tx BD is produced in the expected format by - * 1. using the conditionally-compiled Tx BD bitfield defs from - * isoc_hw_desc.h to make sure the bitfields are at the correct positions - * within a 32-bit word. - * 2. Using the HTT_DXE_TX_BD_BYTESWAP function to swap the bytes within each - * 32-bit word of the Tx BD, so when the Tx BD is stored in little-endian - * order, the shuffled bytes will end up in big-endian order. - * (The byte-shuffling will cancel out the little-endian byte ordering - * that occurs as the 32-bit words are stored into bytes of memory.) - */ -#ifndef BIG_ENDIAN_HOST -/* little-endian - swap the bytes */ -static inline void -HTT_DXE_TX_BD_BYTESWAP(isoc_tx_bd_t *tx_bd) -{ - isoc_hw_bd_swap_bytes32((char *) tx_bd, sizeof(*tx_bd)); -} -#else -/* big-endian - bytes are naturally in the correct order, no swap needed */ -#define HTT_DXE_TX_BD_BYTESWAP(tx_bd) /* no-op */ -#endif /* BIG_ENDIAN_HOST */ - -/*--- debug functions -------------------------------------------------------*/ - -#ifdef HTT_DBG -#define htt_dxe_tx_desc_display htt_tx_desc_display -void -htt_tx_desc_display(void *tx_desc) -{ - struct htt_dxe_tx_desc_t *sw_tx_desc = (struct htt_dxe_tx_desc_t *) desc; - isoc_tx_bd_dump((isoc_tx_bd_t *) sw_tx_desc->tx_bd_buf); -} -#endif - -#ifndef HTT_DXE_TX_DEBUG_LEVEL -#define HTT_DXE_TX_DEBUG_LEVEL 1 /* default */ -#endif - -#if defined(HTT_DBG) || HTT_DXE_TX_DEBUG_LEVEL > 1 - -void HTT_DXE_TX_BD_DUMP(isoc_tx_bd_t *tx_bd) -{ - isoc_tx_bd_t tmp_tx_bd; - - /* - * Make our own copy of the Tx BD. - * This is mainly so we can convert the Tx BD back to little-endian - * format for a printout, if the host is little-endian. - * A secondary purpose is to do a single block-copy from the - * real Tx BD in non-cacheable memory into a cacheable location, - * before reading and printing fields of the struct. - */ - tmp_tx_bd = *tx_bd; - /* undo the endianness fix */ - HTT_DXE_TX_BD_BYTESWAP(&tmp_tx_bd); - isoc_tx_bd_dump(&tmp_tx_bd); -} -#else -#define HTT_DXE_TX_BD_DUMP(tx_bd) /* no-op */ -#endif - -/*--- setup / tear-down functions -------------------------------------------*/ - -A_STATUS -htt_dxe_tx_attach(struct htt_dxe_pdev_t *pdev, int desc_pool_elems) -{ - int i, pool_size; - adf_os_dma_addr_t pool_paddr; - struct htt_dxe_tx_desc_t *sw_desc; - char *tx_bd_buf; - - pdev->tx_descs.sw_descs_pool = NULL; - pdev->tx_descs.tx_bds.pool_vaddr = NULL; - - /*--- allocate the pool of SW tx descs ---*/ - pool_size = sizeof(struct htt_dxe_tx_desc_t) * desc_pool_elems; - pdev->tx_descs.sw_descs_pool = adf_os_mem_alloc(pdev->osdev, pool_size); - if (!pdev->tx_descs.sw_descs_pool) { - goto fail; - } - - /*--- allocate the pool of HW tx descs ---*/ - pdev->tx_descs.size = - ol_cfg_sw_encap_hdr_max_size(pdev->ctrl_pdev) + - sizeof(isoc_tx_bd_t); - if (pdev->tx_descs.size < sizeof(u_int32_t *)) { - pdev->tx_descs.size = sizeof(u_int32_t *); - } - /* - * Make sure tx_descs.size is a multiple of 4-bytes. - * It should be, but round up just to be sure. - */ - pdev->tx_descs.size = (pdev->tx_descs.size + 3) & (~0x3); - - pdev->tx_descs.pool_elems = desc_pool_elems; - pdev->tx_descs.alloc_cnt = 0; - - pool_size = pdev->tx_descs.pool_elems * pdev->tx_descs.size; - -/* allocate extra, for alignment padding? */ - pdev->tx_descs.tx_bds.pool_vaddr = adf_os_mem_alloc_consistent( - pdev->osdev, pool_size, &pool_paddr, - adf_os_get_dma_mem_context((&pdev->tx_descs), memctx)); - pdev->tx_descs.tx_bds.pool_paddr = pool_paddr; - - if (!pdev->tx_descs.tx_bds.pool_vaddr) { - goto fail; - } - - /*-- link HW descs with SW descs, and link SW descs into a freelist ---*/ - pdev->tx_descs.freelist = NULL; - tx_bd_buf = pdev->tx_descs.tx_bds.pool_vaddr; - sw_desc = pdev->tx_descs.sw_descs_pool; - for (i = 0; i < desc_pool_elems; i++) { - sw_desc->tx_bd_buf = tx_bd_buf; - htt_dxe_tx_desc_free(pdev, sw_desc); - - sw_desc++; - tx_bd_buf += pdev->tx_descs.size; - } - - /* program the constant fields within the template Tx BD */ - /* currently, nearly all constant fields need to be set to zero */ - adf_os_mem_zero(&pdev->template_tx_bd, sizeof(pdev->template_tx_bd)); - pdev->template_tx_bd.mpdu_header_offset = sizeof(isoc_tx_bd_t); - - /* initialize the Tx BD serial number */ - pdev->tx_bd_sig_serial_num = 0; - - return A_OK; /* success */ - -fail: - /* clean up any partial inits */ - htt_dxe_tx_detach(pdev); - return A_ERROR; -} - -void -htt_dxe_tx_detach(struct htt_dxe_pdev_t *pdev) -{ - if (pdev->tx_descs.sw_descs_pool) { - adf_os_mem_free(pdev->tx_descs.sw_descs_pool); - } - if (pdev->tx_descs.tx_bds.pool_vaddr) { - adf_os_mem_free_consistent( - pdev->osdev, - pdev->tx_descs.pool_elems * pdev->tx_descs.size, /* pool_size */ - pdev->tx_descs.tx_bds.pool_vaddr, - pdev->tx_descs.tx_bds.pool_paddr, - adf_os_get_dma_mem_context((&pdev->tx_descs), memctx)); - } -} - -/*--- descriptor allocation functions ---------------------------------------*/ - -void * -htt_dxe_tx_desc_alloc(struct htt_dxe_pdev_t *pdev, u_int32_t *paddr_lo) -{ - struct htt_dxe_tx_desc_t *sw_desc; - u_int32_t offset; - - sw_desc = pdev->tx_descs.freelist; - if (! sw_desc) { - return NULL; /* pool is exhausted */ - } - - pdev->tx_descs.freelist = sw_desc->u.next; - pdev->tx_descs.alloc_cnt++; - - offset = (u_int32_t) - (((char *) sw_desc->tx_bd_buf) - - ((char *) pdev->tx_descs.tx_bds.pool_vaddr)); - *paddr_lo = ((u_int32_t) pdev->tx_descs.tx_bds.pool_paddr) + offset; - return (void *) sw_desc; -} - -void -htt_dxe_tx_desc_free(struct htt_dxe_pdev_t *pdev, void *abstract_desc) -{ - struct htt_dxe_tx_desc_t *sw_desc; - - sw_desc = (struct htt_dxe_tx_desc_t *) abstract_desc; - sw_desc->u.next = pdev->tx_descs.freelist; - pdev->tx_descs.freelist = sw_desc; - pdev->tx_descs.alloc_cnt--; -} - -#define htt_dxe_tx_desc_mpdu_header htt_tx_desc_mpdu_header -volatile char * -htt_dxe_tx_desc_mpdu_header(void *abstract_desc, u_int8_t new_l2_hdr_size) -{ - struct htt_dxe_tx_desc_t *sw_desc; - - sw_desc = (struct htt_dxe_tx_desc_t *) abstract_desc; - sw_desc->u.info.l2_hdr_size = new_l2_hdr_size; - return sw_desc->tx_bd_buf + sizeof(isoc_tx_bd_t); -} - - -#ifdef HTT_DBG -void -htt_dxe_tx_desc_display(void *tx_desc) -{ -} -#endif - -/*--- tx descriptor programming functions -----------------------------------*/ - -static u_int16_t -htt_dxe_tx_select_peer( - struct htt_dxe_pdev_t *pdev, - struct htt_msdu_info_t *msdu_info, - int is_robust_mgmt) -{ - struct htt_dxe_vdev_t *vdev; - - vdev = &pdev->vdevs[msdu_info->info.vdev_id]; - if (vdev->op_mode == htt_op_mode_sta) { - if (msdu_info->info.frame_type == htt_frm_type_data) { - /* use the real peer object */ - return msdu_info->info.peer_id; - } else if (is_robust_mgmt) { - /* for robust management, use the real peer object */ - return msdu_info->info.peer_id; - } else { - /* regular management - use self-peer */ - return vdev->self_peer_id; - } - } else { - /* AP */ - if (msdu_info->info.is_unicast) { - if (msdu_info->info.frame_type == htt_frm_type_data) { - /* use the real peer object */ - return msdu_info->info.peer_id; - } else { - /* - * unicast management - - * Is there a valid peer? If so, use it. - * If not (probe-resp or assoc-resp), use the self-peer. - */ - return msdu_info->info.peer_id == HTT_INVALID_PEER_ID ? - vdev->self_peer_id : msdu_info->info.peer_id; - } - } else { - /* use broadcast self-STA */ - return vdev->bcast_peer_id; - } - } -} - -static u_int8_t -htt_dxe_tx_tid_translate(u_int8_t ext_tid, int is_mgmt) -{ - if (is_mgmt) return 7; - if (ext_tid > 7) return 0; - return ext_tid; -} - -static inline u_int8_t -htt_dxe_tx_qos_queue_id(u_int8_t tid) -{ - static u_int8_t tid_queue_ids[] = { - HTT_DXE_TX_BTQM_QID0, HTT_DXE_TX_BTQM_QID1, - HTT_DXE_TX_BTQM_QID2, HTT_DXE_TX_BTQM_QID3, - HTT_DXE_TX_BTQM_QID4, HTT_DXE_TX_BTQM_QID5, - HTT_DXE_TX_BTQM_QID6, HTT_DXE_TX_BTQM_QID7 }; - /* - * Confirm this is a UP TID (0-7), not a regular TID (0-15) - * or extended TID (0-17). - */ - adf_os_assert(tid < ARRAY_LEN(tid_queue_ids)); - - return tid_queue_ids[tid]; -} - -enum { - HTT_DXE_TXBD_SIG_SERIAL_NUM_SHIFT = 0, - HTT_DXE_TXBD_SIG_TID_SHIFT = 8, - HTT_DXE_TXBD_SIG_UCAST_SHIFT = 9, - HTT_DXE_TXBD_SIG_DEST_MAC_ADDR_SHIFT = 16, -}; -#define HTT_DXE_TXBD_SIG_MGMT_MAGIC 0xbdbdbdbd - -/* - * NOTE: this Tx BD signature computation function is currently not used. - * Its purpose is to show whether the prior contents of a Tx BD can be - * reused for a new frame. - * This optimization is not currently utilized, nor are there plans to - * utilize it. - * However, this function is being left in place just in case this - * optimization is utilized in the future. - */ -static inline u_int32_t -htt_dxe_tx_bd_signature( - struct htt_dxe_pdev_t *pdev, - u_int8_t *dest_mac_addr, - u_int8_t tid, - u_int8_t is_unicast, - int is_data) -{ - u_int16_t *dest_mac_addr16 = (u_int16_t *) dest_mac_addr; - u_int16_t dest_mac_addr_hash16; - - if ((!is_data) || (!pdev->cfg.flags.do_frame_translate)) { - return HTT_DXE_TXBD_SIG_MGMT_MAGIC; - } - - /* confirm dest addr has 2-byte alignment, so the above typecast is safe */ - adf_os_assert(((unsigned) dest_mac_addr & 0x1) == 0); - - dest_mac_addr_hash16 = - dest_mac_addr16[0] ^ dest_mac_addr16[1] ^ dest_mac_addr[2]; - return - (dest_mac_addr_hash16 << HTT_DXE_TXBD_SIG_DEST_MAC_ADDR_SHIFT) | - // FIX THIS: update tx_bd_sig_serial_num - (pdev->tx_bd_sig_serial_num << HTT_DXE_TXBD_SIG_SERIAL_NUM_SHIFT) | - (tid << HTT_DXE_TXBD_SIG_TID_SHIFT) | - (is_unicast << HTT_DXE_TXBD_SIG_UCAST_SHIFT); -} - -static void -htt_dxe_tx_bd_fill( - struct htt_dxe_pdev_t *pdev, - struct htt_dxe_tx_desc_t *sw_tx_desc, - int msdu_len, - struct htt_msdu_info_t *msdu_info) -{ - struct htt_dxe_peer_t *peer; - isoc_tx_bd_t shadow_tx_bd = pdev->template_tx_bd; - int tid; - int peer_id; - int which_key; - int l2_hdr_size; - int is_data; - int is_robust_mgmt; - - /* - * The following Tx BD fields are only used internally within the - * target. The host does not need to program these fields. - * adu_feedback - * dpu_feedback - * head_pdu_idx - * tail_pdu_idx - * pdu_count - * dxe_h2b_start_timestamp - * dxe_h2b_end_timestamp - * - * The following Tx BD fields are constant, and are copied from the - * template: - * fw_tx_complete_intr (value = 0) - * bd_type (value = 0) - * mpdu_header_offset (value = sizeof(isoc_tx_bd_t)) - * reserved fields (some of these need to be 0) - * tx_bd_signature (value = 0) - * The tx_bd_signature is a reserved field that can be used - * by the host SW to determine whether the new tx frame is - * similar enough to the prior tx frame described by this - * Tx BD to avoid reprogramming the Tx BD from scratch. - * The htt_dxe module doesn't attempt this optimization. - */ - - is_data = msdu_info->info.frame_type == htt_frm_type_data; - sw_tx_desc->u.info.is_mgmt = !is_data; - tid = htt_dxe_tx_tid_translate(msdu_info->info.ext_tid, !is_data); - is_robust_mgmt = - (!is_data) && - /* - * The peer ID will be HTT_INVALID_PEER_ID if either this is a - * multicast / broadcast frame, or if this is a unicast frame - * to an unassociated peer (probe req/resp, assoc req/resp). - * Thus, it's not necessary to separately check is_unicast. - */ - (msdu_info->info.peer_id != HTT_INVALID_PEER_ID) && - (pdev->peers[msdu_info->info.peer_id].robust_mgmt) && - (msdu_info->info.frame_subtype == htt_frm_subtype_mgmt_action || - msdu_info->info.frame_subtype == htt_frm_subtype_mgmt_deauth || - msdu_info->info.frame_subtype == htt_frm_subtype_mgmt_disassoc); - - /* - * Decide whether to use the peer ID provided by txrx, - * or use the self or BSS peer. - */ - peer_id = htt_dxe_tx_select_peer(pdev, msdu_info, is_robust_mgmt); - peer = &pdev->peers[peer_id]; - /* - * There should never be a transmission that uses an uninitialized - * real-peer or self-peer object. Do a sanity check that the peer - * object has been initialized via a PEER_INFO message. - */ - HTT_DXE_ASSERT2(peer->valid); - /* - * The msdu_info's l3_hdr_offset is always valid, and thus can be used - * as the l2_hdr_size. - * For data frames without SW encap, the l3_hdr_offset is the offset - * within the tx MSDU's netbuf from the start of the L2 header. - * For data frames with SW encap, the old L2 header has been removed - * from the netbuf (by pulling the data pointer past the old L2 header), - * but the l3_hdr_offset still accounts for the new L2 header, even though - * that new L2 header is stored in a buffer provided by HTT, rather than - * in the tx netbuf. - * For management frames, the 802.11 L2 header is present in the netbuf, - * and the msdu_info's l3_hdr_offset has been set to - * sizeof(ieee80211_frame). - */ - l2_hdr_size = msdu_info->info.l3_hdr_offset; - - if (adf_os_likely(msdu_info->info.is_unicast)) { - /*=== unicast data and mgmt ===*/ - // TBD: - //check consistency with frame hdr ack policy field, if SW tx encap? - shadow_tx_bd.ack_policy = HTT_DXE_ACK_POLICY_ACK; - which_key = HTT_DXE_PEER_KEY_UCAST; - - if (adf_os_likely(is_data)) { - shadow_tx_bd.queue_id = (peer->qos_capable) ? - htt_dxe_tx_qos_queue_id(tid) : HTT_DXE_TX_BTQM_QUEUE_TX_NON_QOS; - } else { - /*--- unicast mgmt ---*/ - int is_associated = msdu_info->info.peer_id == HTT_INVALID_PEER_ID; - shadow_tx_bd.queue_id = (is_associated) ? - /* regular unicast mgmt frames - expect ack */ - HTT_DXE_TX_BTQM_QUEUE_SELF_STA_UCAST_MGMT : - /* probe request/response, assoc request/response - no ack */ - HTT_DXE_TX_BTQM_QUEUE_SELF_STA_BCAST_MGMT; - } - } else { - /*=== multicast data and mgmt ===*/ - //TBD: - //check consistency with frame hdr ack policy field, if SW tx encap? - shadow_tx_bd.ack_policy = HTT_DXE_ACK_POLICY_NO_ACK; - if (is_data) { - /*--- multicast data ---*/ - which_key = HTT_DXE_PEER_KEY_MCAST; - shadow_tx_bd.queue_id = HTT_DXE_TX_BTQM_QID0; - } else { - /*--- multicast mgmt ---*/ - which_key = HTT_DXE_PEER_KEY_MGMT; - shadow_tx_bd.queue_id = HTT_DXE_TX_BTQM_QUEUE_SELF_STA_BCAST_MGMT; - } - } - - if (is_data) { - /*=== multicast and unicast data ===*/ - shadow_tx_bd.bd_seq_num_src = (peer->qos_capable) ? - HTT_DXE_TX_SSN_FILL_DPU_QOS : HTT_DXE_TX_SSN_FILL_DPU_NON_QOS; - shadow_tx_bd.bd_rate = HTT_DXE_TX_BDRATE_DEFAULT; - - /* - * riva: no frame translation (tx encap done by SW) - * pronto + northstar: - * depending on frame format, enable HW frm translate - */ - shadow_tx_bd.frame_translate = pdev->cfg.flags.do_frame_translate; - } else { - /*=== multicast and unicast mgmt ===*/ - if (is_robust_mgmt) { - shadow_tx_bd.robust_mgmt = 1; - /* make sure the "no_encrypt" flag gets turned off */ - msdu_info->action.do_encrypt = 1; - } else { - /* besides the robust mgmt case, mgmt frames are not encrypted */ - msdu_info->action.do_encrypt = 0; - } - shadow_tx_bd.bd_seq_num_src = HTT_DXE_TX_SSN_FILL_DPU_NON_QOS; - /* - * bd_rate: - * Check if the rate is forced to 6 Mbps (for mgmt frames in the - * 5 GHz band, or for mgmt frames sent by P2P devices). - * Otherwise, unicast mgmt frames will go at lower rate - * (multicast rate). Multicast mgmt frames will go at the - * STA rate as in AP mode. Buffering has an issue at HW - * if BD rate is used. - */ - if (msdu_info->action.use_6mbps) { - shadow_tx_bd.bd_rate = HTT_DXE_TX_BDRATE_CTRL_FRAME; - } else { - shadow_tx_bd.bd_rate = (msdu_info->info.is_unicast) ? - HTT_DXE_TX_BDRATE_BCMGMT_FRAME : HTT_DXE_TX_BDRATE_DEFAULT; - } - /* mgmt frames already have a 802.11 header - no frame translation */ - shadow_tx_bd.frame_translate = 0; - } - - shadow_tx_bd.dpu_no_encrypt = ! msdu_info->action.do_encrypt; - if(msdu_info->action.do_tx_complete) { - adf_os_print("*** WARNING: Pronto SW for OTA tx ack is incomplete!\n"); - } - shadow_tx_bd.tx_complete_intr = msdu_info->action.do_tx_complete; - shadow_tx_bd.not_unicast = ! msdu_info->info.is_unicast; - shadow_tx_bd.sta_index = peer_id; - shadow_tx_bd.tid = tid; - shadow_tx_bd.mpdu_header_length = l2_hdr_size; - shadow_tx_bd.mpdu_data_offset = sizeof(isoc_tx_bd_t) + l2_hdr_size; - shadow_tx_bd.mpdu_length = msdu_len + sw_tx_desc->u.info.l2_hdr_size; - shadow_tx_bd.dpu_signature = peer->security[which_key].signature; - shadow_tx_bd.dpu_desc_idx = peer->security[which_key].id; - - // FIX THIS - #if 0 - shadow_tx_bd.dpu_routing_flag = (trigger-enabled frame & U-APSD mode on) ? - BMUWQ_FW_DPU_TX : HTT_DXE_TX_BMUWQ_BTQM_TX_MGMT; - #else - // TEMPORARY: default to HTT_DXE_TX_BMUWQ_BTQM_TX_MGMT - shadow_tx_bd.dpu_routing_flag = HTT_DXE_TX_BMUWQ_BTQM_TX_MGMT; - #endif - - /* fix endianness */ - HTT_DXE_TX_BD_BYTESWAP(&shadow_tx_bd); - - /* signature uses native endianness */ - #if 0 /* using signature to avoid reprogramming Tx BD is not supported */ - shadow_tx_bd.tx_bd_signature = htt_dxe_tx_bd_signature( - pdev, msdu_info->info.dest_addr, tid, msdu_info->info.is_unicast, - is_data); - #endif - - adf_os_mem_copy( - (char *) sw_tx_desc->tx_bd_buf, &shadow_tx_bd, sizeof(shadow_tx_bd)); -} - -void htt_tx_desc_set_peer_id(u_int32_t *htt_tx_desc, u_int16_t peer_id) -{ - /* FILL IN HERE */ - return; -} - -void -htt_tx_desc_init( - htt_pdev_handle pdev, - void *desc, - u_int32_t htt_tx_desc_paddr_lo, - u_int16_t msdu_id, - adf_nbuf_t msdu, - struct htt_msdu_info_t *msdu_info) -{ - struct htt_dxe_tx_desc_t *sw_tx_desc = (struct htt_dxe_tx_desc_t *) desc; - int frag_size; - -#if defined(HTT_DBG) || HTT_DXE_TX_DEBUG_LEVEL > 1 - htt_msdu_info_dump(msdu_info); -#endif - htt_dxe_tx_bd_fill(pdev, sw_tx_desc, adf_nbuf_len(msdu), msdu_info); - - /* store the TID for later so we can determine which frames are mgmt */ - sw_tx_desc->u.info.ext_tid = msdu_info->info.ext_tid; - - /* add Tx BD as initial fragment to the netbuf */ - frag_size = sizeof(isoc_tx_bd_t); - /* account for the L2 encapsulation header, if any */ - frag_size += sw_tx_desc->u.info.l2_hdr_size; - adf_nbuf_frag_push_head( - msdu, - frag_size, - /* - * Pass in the address of the SW tx descriptor rather than the - * virtual address of the Tx BD itself. - * The underlying layers don't need to use the Tx BD virtual address; - * they only care about the physical address. - * If this layer needs need to find the Tx BD, it can use the - * sw_tx_desc->tx_bd_buf - * We retrieve this SW tx descriptor pointer later during the tx_send - * function, e.g. to check whether the frame is data or mgmt. - */ - (char *) sw_tx_desc, //sw_tx_desc->tx_bd_buf, /* virtual addr */ - htt_tx_desc_paddr_lo/*phy addr LSBs*/, 0 /* phys addr MSBs - n/a */); -} - -/*--- tx send function ------------------------------------------------------*/ - -#define htt_dxe_tx_send_std htt_tx_send_std -int -htt_dxe_tx_send_std( - struct htt_dxe_pdev_t *pdev, - adf_nbuf_t msdu, - u_int16_t msdu_id) -{ - struct htt_dxe_tx_desc_t *sw_tx_desc; - u_int16_t *msdu_id_storage; - int is_mgmt; - E_HIFDXE_CHANNELTYPE dxe_chan; - - /* - * The HTT tx descriptor was attached as the prefix fragment to the - * msdu netbuf during the call to htt_tx_desc_init. - * Retrieve it so we can check whether the frame is data or mgmt. - */ - sw_tx_desc = (struct htt_dxe_tx_desc_t *) adf_nbuf_get_frag_vaddr(msdu, 0); - - is_mgmt = sw_tx_desc->u.info.is_mgmt; - - /* for debugging, optionally show Tx BD contents */ - HTT_DXE_TX_BD_DUMP((isoc_tx_bd_t *) sw_tx_desc->tx_bd_buf); - - /* store MSDU ID */ - msdu_id_storage = htt_dxe_tx_msdu_id_storage(msdu); - *msdu_id_storage = msdu_id; - - /* send the frame to hif_dxe */ - dxe_chan = (is_mgmt) ? - HIFDXE_CHANNEL_TX_HIGH_PRI : HIFDXE_CHANNEL_TX_LOW_PRI; - - /* FOR NOW, send only one frame at a time */ - adf_nbuf_set_next(msdu, NULL); - - return hif_dxe_send(pdev->hif_dxe_pdev, dxe_chan, msdu) != A_OK; -} - -#define htt_dxe_tx_send_nonstd htt_tx_send_nonstd -int -htt_dxe_tx_send_nonstd( - struct htt_dxe_pdev_t *pdev, - adf_nbuf_t msdu, - u_int16_t msdu_id, - enum htt_pkt_type pkt_type) -{ - /* - * Since the whole frame gets downloaded, frames with a non-standard - * L2 header are handled the same as any other frame. - */ - return htt_dxe_tx_send_std(pdev, msdu, msdu_id); -} - -#define htt_dxe_tx_send_batch htt_tx_send_batch -adf_nbuf_t -htt_dxe_tx_send_batch( - struct htt_dxe_pdev_t *pdev, - adf_nbuf_t head_msdu,int num_msdus) -{ - /* FILL IN HERE */ - adf_os_assert(0); - return NULL; -} - -#define htt_dxe_tx_msdu_credit htt_tx_msdu_credit -u_int32_t htt_dxe_tx_msdu_credit(adf_nbuf_t msdu) -{ - /* - * Credits represent the number of spaces available in the DXE ring. - * Each frame consumes one DXE descriptor for each of its fragments. - * Hence, return the number of fragments in the frame. - */ - return adf_nbuf_get_num_frags(msdu); -} - -/*--- callback functions ----------------------------------------------------*/ - -A_STATUS -htt_dxe_tx_download_done( - void *context, - adf_nbuf_t msdus, - E_HIFDXE_CHANNELTYPE chan, - A_STATUS status) -{ - struct htt_dxe_pdev_t *pdev = (struct htt_dxe_pdev_t *) context; - u_int16_t *msdu_id_storage; - u_int16_t msdu_id; - - while (msdus) { - adf_nbuf_t msdu; - msdu = msdus; - msdus = adf_nbuf_next(msdus); - adf_nbuf_set_next(msdu, NULL); - - msdu_id_storage = htt_dxe_tx_msdu_id_storage(msdu); - msdu_id = *msdu_id_storage; - - ol_tx_download_done_hl_retain(pdev->txrx_pdev, A_OK, msdu, msdu_id); - /* - * For now, as soon as one frame is downloaded, allow another frame's - * download to begin, by immediately updating by the full credit. - */ - ol_tx_target_credit_update( - pdev->txrx_pdev, htt_dxe_tx_msdu_credit(msdu)); - /* - * TO DO: - * Don't give a completion callback here at download completion - * if this frame is tagged for OTA tx completion. - */ - ol_tx_completion_handler( - pdev->txrx_pdev, 1/*num_msdus*/, htt_tx_status_ok, &msdu_id); - } - - return A_OK; -} - -A_STATUS -htt_dxe_tx_low_rsrc( - void *context, - E_HIFDXE_CHANNELTYPE chan, - A_BOOL is_low_resource) -{ -/* FILL IN HERE */ - return A_OK; -} diff --git a/CORE/DXE/htt_dxe_types.h b/CORE/DXE/htt_dxe_types.h deleted file mode 100644 index e7e15949f33e..000000000000 --- a/CORE/DXE/htt_dxe_types.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -#ifndef _HTT_DXE_TYPES__H_ -#define _HTT_DXE_TYPES__H_ - -#include <osdep.h> /* u_int16_t, dma_addr_t */ -#include <adf_os_types.h> /* adf_os_device_t */ -#include <adf_os_lock.h> /* adf_os_spinlock_t */ -//#include <adf_os_timer.h> /* adf_os_timer_t */ -//#include <adf_os_atomic.h>/* adf_os_atomic_inc */ -#include <adf_nbuf.h> /* adf_nbuf_t */ - -#include <isoc_hw_desc.h> /* isoc_tx_bd_t */ -#include <htt_isoc.h> /* HTT_ISOC_T2H_PEER_TYPE_ENUM */ - -#include <ol_ctrl_api.h> /* ol_pdev_handle */ -#include <ol_txrx_api.h> /* ol_txrx_pdev_handle */ -#include <dmux_dxe_api.h> /* dmux_dxe_handle */ -#include <hif_dxe.h> /* hif_dxe_handle */ -#include <isoc_hw_desc.h> /* isoc_rx_bd_t */ -#include <ol_htt_api.h> /* enum htt_op_mode */ - -#define htt_dxe_pdev_t htt_pdev_t - - -struct htt_dxe_pdev_t; - -struct htt_dxe_tx_desc_t { - /* - * N.B. The union portion of this struct can get clobbered when - * the struct is stored in a freelist. - * Any elements that need to be maintained during the time that - * the struct is unallocated in the freelist must be placed - * after the union. - */ - union { - struct { - u_int8_t ext_tid; - u_int8_t l2_hdr_size; - u_int8_t is_mgmt; - } info; - struct htt_dxe_tx_desc_t *next; /* used for freelist */ - } u; - volatile char *tx_bd_buf; -}; - -enum { - HTT_DXE_PEER_KEY_UCAST, - HTT_DXE_PEER_KEY_MCAST, - HTT_DXE_PEER_KEY_MGMT, - - HTT_DXE_PEER_NUM_KEYS /* keep this last */ -}; - -struct htt_dxe_peer_t { - HTT_ISOC_T2H_PEER_TYPE_ENUM type; - u_int32_t rx_aggr_enabled_tids_bitmap; - struct { - u_int8_t id; - u_int8_t signature; - } security[HTT_DXE_PEER_NUM_KEYS]; - u_int8_t vdev_id; /* which vdev does this peer belong to */ - /* - * For now, store one flag per byte, to allow for fast access - * when checking these flags from the per-frame transmit functions. - * To minimize memory, these flags could be packed together, but - * that would be less CPU-efficient. - */ - u_int8_t qos_capable; - u_int8_t robust_mgmt; - u_int8_t valid; -}; - -struct htt_dxe_vdev_t { - enum htt_op_mode op_mode; - u_int16_t self_peer_id; - u_int16_t bcast_peer_id; - u_int8_t valid; -}; - -struct htt_dxe_msdu_list_t { - adf_nbuf_t head; - adf_nbuf_t tail; -}; - -struct htt_dxe_rx_log_elem_t { - u_int16_t peer_id; - int16_t seq_num; /* -1 for n/a */ - u_int8_t tid; - u_int8_t reorder_opcode; - int8_t slot_idx; /* -1 for n/a */ - int8_t fwd_idx; /* -1 for n/a */ -}; - -struct htt_dxe_pdev_t { - ol_pdev_handle ctrl_pdev; - ol_txrx_pdev_handle txrx_pdev; - dmux_dxe_handle dmux_dxe_pdev; - hif_dxe_handle hif_dxe_pdev; - adf_os_device_t osdev; - - struct htt_dxe_vdev_t *vdevs; - struct htt_dxe_peer_t *peers; - - struct { - struct { - u_int8_t sw_tx_encap; - u_int8_t do_frame_translate; - } flags; - } cfg; - - struct { - int size; /* of each HTT tx desc */ - int pool_elems; - int alloc_cnt; - struct htt_dxe_tx_desc_t *sw_descs_pool; - struct { - char *pool_vaddr; - u_int32_t pool_paddr; - } tx_bds; - struct htt_dxe_tx_desc_t *freelist; - adf_os_dma_mem_context(memctx); - } tx_descs; - isoc_tx_bd_t template_tx_bd; - u_int32_t tx_bd_sig_serial_num; - - adf_os_spinlock_t tx_mutex; - u_int8_t tx_mutex_valid; - - struct { - struct htt_dxe_msdu_list_t pending_amsdus[2/*low+high pri*/]; - struct htt_dxe_msdu_list_t delivery; - - /* cur - - * temporary context to remember which rx indication - * is being processed currently - */ - struct { - isoc_rx_bd_t *rx_bd; - u_int8_t peer_id; - u_int8_t tid; - u_int8_t rx_aggr_enabled; - } cur; - } rx; - - #ifdef HTT_DXE_RX_LOG - #define HTT_DXE_RX_LOG_LEN_LOG2 7 /* log length = 128 */ - #define HTT_DXE_RX_LOG_LEN (1 << HTT_DXE_RX_LOG_LEN_LOG2) - #define HTT_DXE_RX_LOG_LEN_MASK (HTT_DXE_RX_LOG_LEN - 1) - struct { - struct htt_dxe_rx_log_elem_t data[HTT_DXE_RX_LOG_LEN]; - int idx; - int enable; - int wrap; - int wrapped; - } reorder_log; - #endif /* HTT_DXE_RX_LOG */ - -}; - - - -#endif /* _HTT_DXE_TYPES__H_ */ diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h index c01b727167ed..61ee976e7ec3 100644 --- a/CORE/HDD/inc/qc_sap_ioctl.h +++ b/CORE/HDD/inc/qc_sap_ioctl.h @@ -284,6 +284,7 @@ enum { QCSAP_PARAM_HIDE_SSID = 8, QCSAP_PARAM_AUTO_CHANNEL = 9, QCSAP_PARAM_SET_MC_RATE = 10, + QCSAP_PARAM_SET_TXRX_FW_STATS=11, }; int iw_softap_get_channel_list(struct net_device *dev, diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index c2bdb8a8f3a9..ce509c10ca9f 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -50,7 +50,7 @@ #endif //Number of items that can be configured -#define MAX_CFG_INI_ITEMS 320 +#define MAX_CFG_INI_ITEMS 512 // Defines for all of the things we read from the configuration (registry). @@ -1411,6 +1411,11 @@ typedef enum #define CFG_HT_SMPS_CAP_FEATURE_MAX ( 3 ) #define CFG_HT_SMPS_CAP_FEATURE_DEFAULT ( 3 ) +#define CFG_DISABLE_DFS_CH_SWITCH "gDisableDFSChSwitch" +#define CFG_DISABLE_DFS_CH_SWITCH_MIN ( 0 ) +#define CFG_DISABLE_DFS_CH_SWITCH_MAX ( 1 ) +#define CFG_DISABLE_DFS_CH_SWITCH_DEFAULT ( 0 ) + #define CFG_REPORT_MAX_LINK_SPEED "gReportMaxLinkSpeed" #define CFG_REPORT_MAX_LINK_SPEED_MIN ( eHDD_LINK_SPEED_REPORT_ACTUAL ) #define CFG_REPORT_MAX_LINK_SPEED_MAX ( eHDD_LINK_SPEED_REPORT_MAX_SCALED ) @@ -2113,7 +2118,7 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_SAP_MAX_NO_PEERS "gSoftApMaxPeers" #define CFG_SAP_MAX_NO_PEERS_MIN (1) #define CFG_SAP_MAX_NO_PEERS_MAX (32) -#define CFG_SAP_MAX_NO_PEERS_DEFAULT (14) +#define CFG_SAP_MAX_NO_PEERS_DEFAULT (32) /*--------------------------------------------------------------------------- Type declarations @@ -2556,6 +2561,7 @@ typedef struct v_U8_t maxWoWFilters; v_U8_t wowEnable; v_U8_t maxNumberOfPeers; + v_U8_t disableDFSChSwitch; } hdd_config_t; /*--------------------------------------------------------------------------- Function declarations and documenation @@ -2670,6 +2676,7 @@ static __inline unsigned long utilMin( unsigned long a, unsigned long b ) #if defined (QCA_WIFI_2_0) && \ !defined (QCA_WIFI_ISOC) void hdd_update_tgt_cfg(void *context, void *param); +void hdd_dfs_indicate_radar(void *context, void *param); #endif /* QCA_WIFI_2_0 && !QCA_WIFI_ISOC */ #endif diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 245c104caf49..791ade2d26f7 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -162,7 +162,15 @@ #define WLAN_HDD_PUBLIC_ACTION_FRAME 4 #define WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET 24 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET 24 #define WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET 30 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET 0 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET 1 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET 2 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET 5 +#define WLAN_HDD_VENDOR_SPECIFIC_ACTION 0x09 +#define WLAN_HDD_WFA_OUI 0x506F9A +#define WLAN_HDD_WFA_P2P_OUI_TYPE 0x09 #define WLAN_HDD_P2P_SOCIAL_CHANNELS 3 #define WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN 1 @@ -206,7 +214,6 @@ #endif #define HDD_MAC_ADDR_LEN 6 -#define HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME 3 #define HDD_SESSION_ID_ANY 50 //This should be same as CSR_SESSION_ID_ANY typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN]; @@ -430,6 +437,7 @@ typedef struct WLAN_WAPI_KEY WLAN_WAPI_KEY; typedef struct WLAN_WAPI_KEY *pWLAN_WAPI_KEY; #define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) +#define WPA_GET_BE24(a) ((u32) ( (a[0] << 16) | (a[1] <<8) | a[2])) #define WLAN_EID_WAPI 68 #define WAPI_PSK_AKM_SUITE 0x02721400 #define WAPI_CERT_AKM_SUITE 0x01721400 @@ -525,6 +533,7 @@ typedef struct hdd_remain_on_chan_ctx unsigned int duration; u64 cookie; rem_on_channel_request_type_t rem_on_chan_request; + v_U32_t p2pRemOnChanTimeStamp; }hdd_remain_on_chan_ctx_t; typedef enum{ @@ -1220,12 +1229,17 @@ struct hdd_context_s #ifdef QCA_WIFI_2_0 v_U32_t target_type; v_U32_t target_fw_version; + v_U32_t dfs_radar_found; #endif struct regulatory reg; #ifdef FEATURE_WLAN_CH_AVOID v_U16_t unsafe_channel_count; v_U16_t unsafe_channel_list[NUM_20MHZ_RF_CHANNELS]; #endif /* FEATURE_WLAN_CH_AVOID */ + + v_U8_t max_intf_count; + v_U8_t current_intf_count; + }; diff --git a/CORE/HDD/inc/wlan_hdd_p2p.h b/CORE/HDD/inc/wlan_hdd_p2p.h index 49fec6b78cbb..a26f086ec28f 100644 --- a/CORE/HDD/inc/wlan_hdd_p2p.h +++ b/CORE/HDD/inc/wlan_hdd_p2p.h @@ -37,6 +37,7 @@ #define WAIT_CANCEL_REM_CHAN 1000 #define WAIT_REM_CHAN_READY 1000 #define WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX 3000 +#define READY_EVENT_PROPOGATE_TIME 2 #define ACTION_FRAME_DEFAULT_WAIT 200 diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h index 2fa866eda447..254dc3786c10 100644 --- a/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/CORE/HDD/inc/wlan_hdd_tdls.h @@ -32,9 +32,6 @@ \brief Linux HDD TDLS include file -Copyright (c) 2012-2013 Qualcomm Atheros, Inc. -All Rights Reserved. -Qualcomm Atheros Confidential and Proprietary. ==========================================================================*/ #define MAX_NUM_TDLS_PEER 3 diff --git a/CORE/HDD/inc/wlan_hdd_tgt_cfg.h b/CORE/HDD/inc/wlan_hdd_tgt_cfg.h index cc15d790d93e..120905a36547 100644 --- a/CORE/HDD/inc/wlan_hdd_tgt_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_tgt_cfg.h @@ -91,6 +91,13 @@ struct hdd_tgt_cfg { #ifdef WLAN_FEATURE_11AC struct hdd_tgt_vht_cap vht_cap; #endif + v_U8_t max_intf_count; +}; + +struct hdd_dfs_radar_ind { + u_int8_t ieee_chan_number; + u_int32_t chan_freq; + u_int32_t dfs_radar_status; }; #endif /* HDD_TGT_CFG_H */ diff --git a/CORE/HDD/src/test.c b/CORE/HDD/src/test.c deleted file mode 100644 index 9f895d2a6c61..000000000000 --- a/CORE/HDD/src/test.c +++ /dev/null @@ -1,10032 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/** ------------------------------------------------------------------------ * - ------------------------------------------------------------------------ * - - - \file wlan_hdd_wext.c - - \brief Airgo Linux Wireless Extensions Common Control Plane Types and - interfaces. - - $Id: wlan_hdd_wext.c,v 1.34 2007/04/14 01:49:23 jimz Exp jimz $ - - Copyright (C) 2007 Airgo Networks, Incorporated - - This file defines all of the types that are utilized by the CCP module - of the "Portable" HDD. This file also includes the underlying Linux - Wireless Extensions Data types referred to by CCP. - - ======================================================================== */ - -#include <linux/version.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/wireless.h> -#include <macTrace.h> -#include <wlan_hdd_includes.h> -#include <wlan_btc_svc.h> -#include <wlan_nlink_common.h> -#ifdef WLAN_BTAMP_FEATURE -#include <bap_hdd_main.h> -#endif -#include <vos_api.h> -#include <net/arp.h> -#include "ccmApi.h" -#include "sirParams.h" -#include "csrApi.h" -#include "csrInsideApi.h" -#if defined WLAN_FEATURE_VOWIFI -#include "smeRrmInternal.h" -#endif -#include <aniGlobal.h> -#include "dot11f.h" -#include <wlan_hdd_wowl.h> -#include <wlan_hdd_cfg.h> -#include <wlan_hdd_wmm.h> -#include "utilsApi.h" -#include "wlan_hdd_p2p.h" -#ifdef FEATURE_WLAN_TDLS -#include "wlan_hdd_tdls.h" -#endif - -#ifdef QCA_WIFI_2_0 -#include "ieee80211_common.h" -#include "ol_if_athvar.h" -#include "dbglog_host.h" -#include "wma.h" -#endif - -#ifdef CONFIG_HAS_EARLYSUSPEND -#include <linux/earlysuspend.h> -#endif -#include "wlan_hdd_power.h" -#include "qwlan_version.h" -#include <vos_power.h> -#include "wlan_hdd_host_offload.h" -#include "wlan_hdd_keep_alive.h" -#ifdef WLAN_FEATURE_PACKET_FILTERING -#include "wlan_hdd_packet_filtering.h" -#endif - -#include <linux/wireless.h> -#include <net/cfg80211.h> -#include "wlan_qct_pal_trace.h" -#include "wlan_qct_tl.h" - -#include "wlan_hdd_misc.h" -#include "bap_hdd_misc.h" - -#include "wlan_hdd_dev_pwr.h" -#include "qc_sap_ioctl.h" -#include "sme_Api.h" -#include "wlan_qct_wda.h" -#ifdef CONFIG_HAS_EARLYSUSPEND -extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend); -extern void hdd_resume_wlan(struct early_suspend *wlan_suspend); -#endif - -#ifdef FEATURE_OEM_DATA_SUPPORT -#define MAX_OEM_DATA_RSP_LEN 2047 -#endif - -#define HDD_FINISH_ULA_TIME_OUT 800 - -extern int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand); -int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr); - -static int ioctl_debug; -module_param(ioctl_debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - -#define STATS_CONTEXT_MAGIC 0x53544154 //STAT -#define RSSI_CONTEXT_MAGIC 0x52535349 //RSSI -#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR -#define SNR_CONTEXT_MAGIC 0x534E5200 //SNR - -/* To Validate Channel against the Frequency and Vice-Versa */ -static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, - {2422, 3}, {2427, 4}, {2432, 5}, {2437, 6}, {2442, 7}, {2447, 8}, - {2452, 9}, {2457, 10}, {2462, 11}, {2467 ,12}, {2472, 13}, - {2484, 14}, {4920, 240}, {4940, 244}, {4960, 248}, {4980, 252}, - {5040, 208}, {5060, 212}, {5080, 216}, {5180, 36}, {5200, 40}, {5220, 44}, - {5240, 48}, {5260, 52}, {5280, 56}, {5300, 60}, {5320, 64}, {5500, 100}, - {5520, 104}, {5540, 108}, {5560, 112}, {5580, 116}, {5600, 120}, - {5620, 124}, {5640, 128}, {5660, 132}, {5680, 136}, {5700, 140}, - {5745, 149}, {5765, 153}, {5785, 157}, {5805, 161}, {5825, 165} }; - -#define FREQ_CHAN_MAP_TABLE_SIZE (sizeof(freq_chan_map)/sizeof(freq_chan_map[0])) - -#define RC_2_RATE_IDX(_rc) ((_rc) & 0x7) -#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) - -#define RC_2_RATE_IDX_11AC(_rc) ((_rc) & 0xf) -#define HT_RC_2_STREAMS_11AC(_rc) ((((_rc) & 0x30) >> 4) + 1) - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_INT_GET_NONE (SIOCIWFIRSTPRIV + 0) -#define WE_SET_11D_STATE 1 -#define WE_WOWL 2 -#define WE_SET_POWER 3 -#define WE_SET_MAX_ASSOC 4 -#define WE_SET_SAP_AUTO_CHANNEL_SELECTION 5 -#define WE_SET_DATA_INACTIVITY_TO 6 -#define WE_SET_MAX_TX_POWER 7 -#define WE_SET_HIGHER_DTIM_TRANSITION 8 -#define WE_SET_TM_LEVEL 9 -#define WE_SET_PHYMODE 10 -#define WE_SET_NSS 11 -#define WE_SET_LDPC 12 -#define WE_SET_TX_STBC 13 -#define WE_SET_RX_STBC 14 -#define WE_SET_SHORT_GI 15 -#define WE_SET_RTSCTS 16 -#define WE_SET_CHWIDTH 17 -#define WE_SET_ANI_EN_DIS 18 -#define WE_SET_ANI_POLL_PERIOD 19 -#define WE_SET_ANI_LISTEN_PERIOD 20 -#define WE_SET_ANI_OFDM_LEVEL 21 -#define WE_SET_ANI_CCK_LEVEL 22 -#define WE_SET_DYNAMIC_BW 23 -#define WE_SET_TX_CHAINMASK 24 -#define WE_SET_RX_CHAINMASK 25 -#define WE_SET_11N_RATE 26 -#define WE_SET_AMPDU 27 -#define WE_SET_AMSDU 28 -#define WE_SET_TXPOW_2G 29 -#define WE_SET_TXPOW_5G 30 -/* Private ioctl for firmware debug log */ -#define WE_DBGLOG_LOG_LEVEL 31 -#define WE_DBGLOG_VAP_ENABLE 32 -#define WE_DBGLOG_VAP_DISABLE 33 -#define WE_DBGLOG_MODULE_ENABLE 34 -#define WE_DBGLOG_MODULE_DISABLE 35 -#define WE_DBGLOG_MOD_LOG_LEVEL 36 -#define WE_DBGLOG_TYPE 37 -#define WE_SET_TXRX_FWSTATS 38 -#define WE_SET_VHT_RATE 39 -#define WE_DBGLOG_REPORT_ENABLE 40 -#define WE_TXRX_FWSTATS_RESET 41 -#define WE_SET_MAX_TX_POWER_2_4 42 -#define WE_SET_MAX_TX_POWER_5_0 43 -#define WE_SET_POWER_GATING 44 -/* Private ioctl for packet powe save */ -#define WE_PPS_PAID_MATCH 45 -#define WE_PPS_GID_MATCH 46 -#define WE_PPS_EARLY_TIM_CLEAR 47 -#define WE_PPS_EARLY_DTIM_CLEAR 48 -#define WE_PPS_EOF_PAD_DELIM 49 -#define WE_PPS_MACADDR_MISMATCH 50 -#define WE_PPS_DELIM_CRC_FAIL 51 -#define WE_PPS_GID_NSTS_ZERO 52 -#define WE_PPS_RSSI_CHECK 53 -#define WE_ENABLE_STRICT_FCC_REG 54 - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) -#define WE_GET_11D_STATE 1 -#define WE_IBSS_STATUS 2 -#define WE_PMC_STATE 3 -#define WE_GET_WLAN_DBG 4 -#define WE_MODULE_DOWN_IND 5 -#define WE_GET_MAX_ASSOC 6 -#define WE_GET_WDI_DBG 7 -#define WE_GET_SAP_AUTO_CHANNEL_SELECTION 8 -#define WE_GET_CONCURRENCY_MODE 9 -#ifdef QCA_WIFI_2_0 -#define WE_GET_NSS 11 -#define WE_GET_LDPC 12 -#define WE_GET_TX_STBC 13 -#define WE_GET_RX_STBC 14 -#define WE_GET_SHORT_GI 15 -#define WE_GET_RTSCTS 16 -#define WE_GET_CHWIDTH 17 -#define WE_GET_ANI_EN_DIS 18 -#define WE_GET_ANI_POLL_PERIOD 19 -#define WE_GET_ANI_LISTEN_PERIOD 20 -#define WE_GET_ANI_OFDM_LEVEL 21 -#define WE_GET_ANI_CCK_LEVEL 22 -#define WE_GET_DYNAMIC_BW 23 -#define WE_GET_TX_CHAINMASK 24 -#define WE_GET_RX_CHAINMASK 25 -#define WE_GET_11N_RATE 26 -#define WE_GET_AMPDU 27 -#define WE_GET_AMSDU 28 -#define WE_GET_TXPOW_2G 29 -#define WE_GET_TXPOW_5G 30 -#define WE_GET_POWER_GATING 31 -#define WE_GET_PPS_PAID_MATCH 32 -#define WE_GET_PPS_GID_MATCH 33 -#define WE_GET_PPS_EARLY_TIM_CLEAR 34 -#define WE_GET_PPS_EARLY_DTIM_CLEAR 35 -#define WE_GET_PPS_EOF_PAD_DELIM 36 -#define WE_GET_PPS_MACADDR_MISMATCH 37 -#define WE_GET_PPS_DELIM_CRC_FAIL 38 -#define WE_GET_PPS_GID_NSTS_ZERO 39 -#define WE_GET_PPS_RSSI_CHECK 40 -#endif - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2) - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_CHAR_GET_NONE (SIOCIWFIRSTPRIV + 3) -#define WE_WOWL_ADD_PTRN 1 -#define WE_WOWL_DEL_PTRN 2 -#if defined WLAN_FEATURE_VOWIFI -#define WE_NEIGHBOR_REPORT_REQUEST 3 -#endif -#define WE_SET_AP_WPS_IE 4 //This is called in station mode to set probe rsp ie. -#define WE_SET_CONFIG 5 - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 4) -#define WE_SET_WLAN_DBG 1 -#define WE_SET_WDI_DBG 2 -#define WE_SET_SAP_CHANNELS 3 - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 5) -#define WE_WLAN_VERSION 1 -#define WE_GET_STATS 2 -#define WE_GET_CFG 3 -#define WE_GET_WMM_STATUS 4 -#define WE_GET_CHANNEL_LIST 5 -#ifdef WLAN_FEATURE_11AC -#define WE_GET_RSSI 6 -#endif -#define WE_GET_ROAM_RSSI 7 -#ifdef FEATURE_WLAN_TDLS -#define WE_GET_TDLS_PEERS 8 -#endif -#ifdef WLAN_FEATURE_11W -#define WE_GET_11W_INFO 9 -#endif -#define WE_GET_STATES 10 -#ifdef FEATURE_CESIUM_PROPRIETARY -#define WE_GET_IBSS_STA_INFO 11 -#endif -#ifdef QCA_WIFI_2_0 -#define WE_GET_PHYMODE 12 -#endif - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) -#define WE_CLEAR_STATS 1 -#define WE_INIT_AP 2 -#define WE_STOP_AP 3 -#define WE_ENABLE_AMP 4 -#define WE_DISABLE_AMP 5 -#define WE_ENABLE_DXE_STALL_DETECT 6 -#define WE_DISPLAY_DXE_SNAP_SHOT 7 -#define WE_SET_REASSOC_TRIGGER 8 -#define WE_DISPLAY_DATAPATH_SNAP_SHOT 9 -#ifdef FEATURE_CESIUM_PROPRIETARY -#define WE_IBSS_GET_PEER_INFO_ALL 10 -#endif -#ifdef QCA_WIFI_2_0 -#define WE_DUMP_AGC_START 11 -#define WE_DUMP_AGC 12 -#define WE_DUMP_CHANINFO_START 13 -#define WE_DUMP_CHANINFO 14 -#define WE_DUMP_WATCHDOG 15 -#ifdef DEBUG -#define WE_SET_FW_CRASH_INJECT 16 -#endif -#endif - -/* Private ioctls and their sub-ioctls */ -#define WLAN_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 7) -#define WE_LOG_DUMP_CMD 1 - -#define WE_P2P_NOA_CMD 2 -//IOCTL to configure MCC params -#define WE_MCC_CONFIG_CREDENTIAL 3 -#define WE_MCC_CONFIG_PARAMS 4 - -#ifdef FEATURE_WLAN_TDLS -#define WE_TDLS_CONFIG_PARAMS 5 -#endif -#ifdef FEATURE_CESIUM_PROPRIETARY -#define WE_IBSS_GET_PEER_INFO 6 -#endif -#ifdef FEATURE_WLAN_TDLS -#undef MAX_VAR_ARGS -#define MAX_VAR_ARGS 10 -#else -#define MAX_VAR_ARGS 7 -#endif - - -/* Private ioctls (with no sub-ioctls) */ -/* note that they must be odd so that they have "get" semantics */ -#define WLAN_PRIV_ADD_TSPEC (SIOCIWFIRSTPRIV + 9) -#define WLAN_PRIV_DEL_TSPEC (SIOCIWFIRSTPRIV + 11) -#define WLAN_PRIV_GET_TSPEC (SIOCIWFIRSTPRIV + 13) - -#ifdef FEATURE_WLAN_WAPI -/* Private ioctls EVEN NO: SET, ODD NO:GET */ -#define WLAN_PRIV_SET_WAPI_MODE (SIOCIWFIRSTPRIV + 8) -#define WLAN_PRIV_GET_WAPI_MODE (SIOCIWFIRSTPRIV + 16) -#define WLAN_PRIV_SET_WAPI_ASSOC_INFO (SIOCIWFIRSTPRIV + 10) -#define WLAN_PRIV_SET_WAPI_KEY (SIOCIWFIRSTPRIV + 12) -#define WLAN_PRIV_SET_WAPI_BKID (SIOCIWFIRSTPRIV + 14) -#define WLAN_PRIV_GET_WAPI_BKID (SIOCIWFIRSTPRIV + 15) -#define WAPI_PSK_AKM_SUITE 0x02721400 -#define WAPI_CERT_AKM_SUITE 0x01721400 -#endif - -#ifdef FEATURE_OEM_DATA_SUPPORT -/* Private ioctls for setting the measurement configuration */ -#define WLAN_PRIV_SET_OEM_DATA_REQ (SIOCIWFIRSTPRIV + 17) -#define WLAN_PRIV_GET_OEM_DATA_RSP (SIOCIWFIRSTPRIV + 19) -#endif - -#ifdef WLAN_FEATURE_VOWIFI_11R -#define WLAN_PRIV_SET_FTIES (SIOCIWFIRSTPRIV + 20) -#endif - -/* Private ioctl for setting the host offload feature */ -#define WLAN_PRIV_SET_HOST_OFFLOAD (SIOCIWFIRSTPRIV + 18) - -/* Private ioctl to get the statistics */ -#define WLAN_GET_WLAN_STATISTICS (SIOCIWFIRSTPRIV + 21) - -/* Private ioctl to set the Keep Alive Params */ -#define WLAN_SET_KEEPALIVE_PARAMS (SIOCIWFIRSTPRIV + 22) -#ifdef WLAN_FEATURE_PACKET_FILTERING -/* Private ioctl to set the Packet Filtering Params */ -#define WLAN_SET_PACKET_FILTER_PARAMS (SIOCIWFIRSTPRIV + 23) -#endif - -#ifdef FEATURE_WLAN_SCAN_PNO -/* Private ioctl to get the statistics */ -#define WLAN_SET_PNO (SIOCIWFIRSTPRIV + 24) -#endif - -#define WLAN_SET_BAND_CONFIG (SIOCIWFIRSTPRIV + 25) /*Don't change this number*/ - -#define WLAN_PRIV_SET_MCBC_FILTER (SIOCIWFIRSTPRIV + 26) -#define WLAN_PRIV_CLEAR_MCBC_FILTER (SIOCIWFIRSTPRIV + 27) -/* Private ioctl to trigger reassociation */ - -#define WLAN_SET_POWER_PARAMS (SIOCIWFIRSTPRIV + 29) -#ifdef FEATURE_OEM_DATA_SUPPORT -#ifdef QCA_WIFI_2_0 -/* Private ioctl to get capability information for OEM Data Request/Response */ -#define WLAN_PRIV_GET_OEM_DATA_CAP (SIOCIWFIRSTPRIV + 30) -#endif -#endif -#define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31) - -#define WLAN_STATS_INVALID 0 -#define WLAN_STATS_RETRY_CNT 1 -#define WLAN_STATS_MUL_RETRY_CNT 2 -#define WLAN_STATS_TX_FRM_CNT 3 -#define WLAN_STATS_RX_FRM_CNT 4 -#define WLAN_STATS_FRM_DUP_CNT 5 -#define WLAN_STATS_FAIL_CNT 6 -#define WLAN_STATS_RTS_FAIL_CNT 7 -#define WLAN_STATS_ACK_FAIL_CNT 8 -#define WLAN_STATS_RTS_SUC_CNT 9 -#define WLAN_STATS_RX_DISCARD_CNT 10 -#define WLAN_STATS_RX_ERROR_CNT 11 -#define WLAN_STATS_TX_BYTE_CNT 12 - -#define WLAN_STATS_RX_BYTE_CNT 13 -#define WLAN_STATS_RX_RATE 14 -#define WLAN_STATS_TX_RATE 15 - -#define WLAN_STATS_RX_UC_BYTE_CNT 16 -#define WLAN_STATS_RX_MC_BYTE_CNT 17 -#define WLAN_STATS_RX_BC_BYTE_CNT 18 -#define WLAN_STATS_TX_UC_BYTE_CNT 19 -#define WLAN_STATS_TX_MC_BYTE_CNT 20 -#define WLAN_STATS_TX_BC_BYTE_CNT 21 - -#define FILL_TLV(__p, __type, __size, __val, __tlen) do { \ - if ((__tlen + __size + 2) < WE_MAX_STR_LEN) \ - { \ - *__p++ = __type; \ - *__p++ = __size; \ - memcpy(__p, __val, __size); \ - __p += __size; \ - __tlen += __size + 2; \ - } \ - else \ - { \ - hddLog(VOS_TRACE_LEVEL_ERROR, "FILL_TLV Failed!!!\n"); \ - } \ - } while(0); - -#define VERSION_VALUE_MAX_LEN 32 - -#define TX_PER_TRACKING_DEFAULT_RATIO 5 -#define TX_PER_TRACKING_MAX_RATIO 10 -#define TX_PER_TRACKING_DEFAULT_WATERMARK 5 - -#define WLAN_ADAPTER 0 -#define P2P_ADAPTER 1 - -/*MCC Configuration parameters */ -enum { - MCC_SCHEDULE_TIME_SLICE_CFG_PARAM = 1, - MCC_MAX_NULL_SEND_TIME_CFG_PARAM, - MCC_TX_EARLY_STOP_TIME_CFG_PARAM, - MCC_RX_DRAIN_TIME_CFG_PARAM, - MCC_CHANNEL_SWITCH_TIME_CFG_PARAM, - MCC_MIN_CHANNEL_TIME_CFG_PARAM, - MCC_PARK_BEFORE_TBTT_CFG_PARAM, - MCC_MIN_AFTER_DTIM_CFG_PARAM, - MCC_TOO_CLOSE_MARGIN_CFG_PARAM, -}; - -int hdd_validate_mcc_config(hdd_adapter_t *pAdapter, v_UINT_t staId, - v_UINT_t arg1, v_UINT_t arg2, v_UINT_t arg3); - -#ifdef WLAN_FEATURE_PACKET_FILTERING -int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, - v_U8_t sessionId); -#endif - -/**--------------------------------------------------------------------------- - - \brief hdd_wlan_get_version() - - - This function use to get Wlan Driver, Firmware, & Hardware Version. - - \param - pAdapter Pointer to the adapter. - wrqu - Pointer to IOCTL REQUEST Data. - extra - Pointer to char - - \return - none - - --------------------------------------------------------------------------*/ -void hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu, - char *extra) -{ - VOS_STATUS status; - tSirVersionString wcnss_SW_version; - tSirVersionString wcnss_HW_version; - char *pSWversion; - char *pHWversion; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - - status = sme_GetWcnssSoftwareVersion(hHal, wcnss_SW_version, - sizeof(wcnss_SW_version)); - if (VOS_IS_STATUS_SUCCESS(status)) - { - pSWversion = wcnss_SW_version; - } - else - { - pSWversion = "Unknown"; - } - - status = sme_GetWcnssHardwareVersion(hHal, wcnss_HW_version, - sizeof(wcnss_HW_version)); - if (VOS_IS_STATUS_SUCCESS(status)) - { - pHWversion = wcnss_HW_version; - } - else - { - pHWversion = "Unknown"; - } - - wrqu->data.length = scnprintf(extra, WE_MAX_STR_LEN, - "Host SW:%s, FW:%s, HW:%s", - QWLAN_VERSIONSTR, - pSWversion, - pHWversion); - - return; -} - -#ifdef FEATURE_CESIUM_PROPRIETARY -void hdd_get_ibss_peer_info_cb(v_VOID_t *pUserData, v_VOID_t *pPeerInfoRsp) -{ - hdd_adapter_t *pAdapter = (hdd_adapter_t *)pUserData; - hdd_ibss_peer_info_t *pPeerInfo = (hdd_ibss_peer_info_t *)pPeerInfoRsp; - hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - v_U8_t i; - - if (NULL != pPeerInfo && eHAL_STATUS_SUCCESS == pPeerInfo->status) - { - pStaCtx->ibss_peer_info.status = pPeerInfo->status; - pStaCtx->ibss_peer_info.numIBSSPeers = pPeerInfo->numIBSSPeers; - for (i = 0; i < pPeerInfo->numIBSSPeers; i++) - { - memcpy(&pStaCtx->ibss_peer_info.ibssPeerList[i], - &pPeerInfo->ibssPeerList[i], sizeof(hdd_ibss_peer_info_params_t)); - } - } - else - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s] PEER_INFO_CMD_STATUS is not SUCCESS\n", __func__); - } - - complete(&pAdapter->ibss_peer_info_comp); -} - -v_MACADDR_t* hdd_wlan_get_ibss_mac_addr_from_staid(hdd_adapter_t *pAdapter, v_U8_t staIdx) -{ - v_U8_t idx; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) - { - if ( 0 != pHddStaCtx->conn_info.staId[ idx ] && - staIdx == pHddStaCtx->conn_info.staId[ idx ]) - { - return (&pHddStaCtx->conn_info.peerMacAddress[ idx ]); - } - } - return NULL; -} - -eHalStatus hdd_wlan_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx) -{ - eHalStatus status = eHAL_STATUS_FAILURE; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - hdd_ibss_peer_info_t *pPeerInfo = &pStaCtx->ibss_peer_info; - - status = sme_RequestIBSSPeerInfo(hHal, pAdapter, hdd_get_ibss_peer_info_cb, - VOS_FALSE, staIdx); - - INIT_COMPLETION(pAdapter->ibss_peer_info_comp); - - if (eHAL_STATUS_SUCCESS == status) - { - status = wait_for_completion_interruptible_timeout - (&pAdapter->ibss_peer_info_comp, - msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); - if(!status) - { - hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT", - __func__); - return status; - } - - /** Print the peer info */ - pr_info("pPeerInfo->numIBSSPeers = %d ", pPeerInfo->numIBSSPeers); - pr_info("============================================================"); - { - v_MACADDR_t *macAddr = hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter, - staIdx); - v_U32_t txRateMbps = ((pPeerInfo->ibssPeerList[0].txRate)*500*1000)/1000000; - - if (NULL != macAddr) - { - pr_info("PEER ADDR :" MAC_ADDRESS_STR " TxRate: %d Mbps RSSI: %d", - MAC_ADDR_ARRAY(macAddr->bytes), - (int)txRateMbps, (int)pPeerInfo->ibssPeerList[0].rssi); - } - else - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - " ERROR: PEER MAC ADDRESS NOT FOUND "); - } - } - } - else - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); - } - - return status; -} - -eHalStatus hdd_wlan_get_ibss_peer_info_all(hdd_adapter_t *pAdapter) -{ - eHalStatus status = eHAL_STATUS_FAILURE; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - hdd_ibss_peer_info_t *pPeerInfo = &pStaCtx->ibss_peer_info; - int i; - - status = sme_RequestIBSSPeerInfo(hHal, pAdapter, hdd_get_ibss_peer_info_cb, - VOS_TRUE, 0xFF); - INIT_COMPLETION(pAdapter->ibss_peer_info_comp); - - if (eHAL_STATUS_SUCCESS == status) - { - status = wait_for_completion_interruptible_timeout - (&pAdapter->ibss_peer_info_comp, - msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); - if(!status) - { - hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT", - __func__); - return status; - } - - /** Print the peer info */ - pr_info("pPeerInfo->numIBSSPeers = %d ", (int)pPeerInfo->numIBSSPeers); - pr_info("============================================================"); - for (i = 0; i < pPeerInfo->numIBSSPeers; i++) - { - v_U8_t staIdx = pPeerInfo->ibssPeerList[i].staIdx; - v_MACADDR_t *macAddr = hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter, - staIdx); - v_U32_t txRateMbps = ((pPeerInfo->ibssPeerList[0].txRate)*500*1000)/1000000; - - pr_info("STAIDX:%d ", (int)pPeerInfo->ibssPeerList[i].staIdx); - if (NULL != macAddr) - { - pr_info(" PEER ADDR :" MAC_ADDRESS_STR " TxRate: %d Mbps RSSI: %d", - MAC_ADDR_ARRAY(macAddr->bytes), - (int)txRateMbps, (int)pPeerInfo->ibssPeerList[i].rssi); - } - else - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - " ERROR: PEER MAC ADDRESS NOT FOUND "); - } - } - } - else - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); - } - - return status; -} -#endif /* FEATURE_CESIUM_PROPRIETARY */ - -int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) -{ - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - v_U32_t threshold = 0,status = 0; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s:LOGP in Progress. Ignore!!!",__func__); - return status; - } - - if ( eHAL_STATUS_SUCCESS != - ccmCfgGetInt(hHal, WNI_CFG_RTS_THRESHOLD, &threshold) ) - { - return -EIO; - } - wrqu->rts.value = threshold; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("Rts-Threshold=%ld!!\n"), wrqu->rts.value); - - EXIT(); - - return 0; -} - -int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) -{ - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - v_U32_t threshold = 0,status = 0; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s:LOGP in Progress. Ignore!!!",__func__); - return status; - } - - if ( ccmCfgGetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, &threshold) - != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - wrqu->frag.value = threshold; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("Frag-Threshold=%ld!!\n"), wrqu->frag.value); - - EXIT(); - - return 0; -} - -int hdd_wlan_get_freq(v_U32_t channel, v_U32_t *pfreq) -{ - int i; - if (channel > 0) - { - for (i=0; i < FREQ_CHAN_MAP_TABLE_SIZE; i++) - { - if (channel == freq_chan_map[i].chan) - { - *pfreq = freq_chan_map[i].freq; - return 1; - } - } - } - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("Invalid channel no=%d!!\n"), channel); - return -EINVAL; -} - -static v_BOOL_t -hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType) -{ - v_BOOL_t rsnType = VOS_FALSE; - // is the authType supported? - switch (authType) - { - case eCSR_AUTH_TYPE_NONE: //never used - rsnType = eANI_BOOLEAN_FALSE; - break; - // MAC layer authentication types - case eCSR_AUTH_TYPE_OPEN_SYSTEM: - rsnType = eANI_BOOLEAN_FALSE; - break; - case eCSR_AUTH_TYPE_SHARED_KEY: - rsnType = eANI_BOOLEAN_FALSE; - break; - case eCSR_AUTH_TYPE_AUTOSWITCH: - rsnType = eANI_BOOLEAN_FALSE; - break; - - // Upper layer authentication types - case eCSR_AUTH_TYPE_WPA: - rsnType = eANI_BOOLEAN_TRUE; - break; - case eCSR_AUTH_TYPE_WPA_PSK: - rsnType = eANI_BOOLEAN_TRUE; - break; - case eCSR_AUTH_TYPE_WPA_NONE: - rsnType = eANI_BOOLEAN_TRUE; - break; -#ifdef WLAN_FEATURE_VOWIFI_11R - case eCSR_AUTH_TYPE_FT_RSN: -#endif - case eCSR_AUTH_TYPE_RSN: - rsnType = eANI_BOOLEAN_TRUE; - break; -#ifdef WLAN_FEATURE_VOWIFI_11R - case eCSR_AUTH_TYPE_FT_RSN_PSK: -#endif - case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif - rsnType = eANI_BOOLEAN_TRUE; - break; - //case eCSR_AUTH_TYPE_FAILED: - case eCSR_AUTH_TYPE_UNKNOWN: - rsnType = eANI_BOOLEAN_FALSE; - break; - default: - hddLog(LOGE, FL("%s called with unknown authType - default to Open, None\n"), - __func__); - rsnType = eANI_BOOLEAN_FALSE; - break; - } - hddLog(LOGE, FL("%s called with authType: %d, returned: %d\n"), - __func__, authType, rsnType); - return rsnType; -} - -static void hdd_GetRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: rssi [%d] STA [%d] pContext [%p]\n", - __func__, (int)rssi, (int)staId, pContext); - } - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%p]", - __func__, pContext); - return; - } - - /* there is a race condition that exists between this callback function - and the caller since the caller could time out either before or - while this code is executing. we'll assume the timeout hasn't - occurred, but we'll verify that right before we save our work */ - - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (RSSI_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%p] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* the race is on. caller could have timed out immediately after - we verified the magic, but if so, caller will wait a short time - for us to copy over the rssi */ - pAdapter->rssi = rssi; - - /* and notify the caller */ - complete(&pStatsContext->completion); -} - -static void hdd_GetSnrCB(tANI_S8 snr, tANI_U32 staId, void *pContext) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: snr [%d] STA [%d] pContext [%p]\n", - __func__, (int)snr, (int)staId, pContext); - } - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%p]", - __func__, pContext); - return; - } - - /* there is a race condition that exists between this callback function - * and the caller since the caller could time out either before or - * while this code is executing. we'll assume the timeout hasn't - * occurred, but we'll verify that right before we save our work - */ - - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (SNR_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%p] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* the race is on. caller could have timed out immediately after - * we verified the magic, but if so, caller will wait a short time - * for us to copy over the snr - */ - pAdapter->snr = snr; - - /* and notify the caller */ - complete(&pStatsContext->completion); -} - -VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) -{ - struct statsContext context; - hdd_context_t *pHddCtx; - hdd_station_ctx_t *pHddStaCtx; - eHalStatus hstatus; - long lrc; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter", __func__); - return VOS_STATUS_E_FAULT; - } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__); - /* return a cached value */ - *rssi_value = pAdapter->rssi; - return VOS_STATUS_SUCCESS; - } - - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = RSSI_CONTEXT_MAGIC; - - hstatus = sme_GetRssi(pHddCtx->hHal, hdd_GetRssiCB, - pHddStaCtx->conn_info.staId[ 0 ], - pHddStaCtx->conn_info.bssId, - &context, pHddCtx->pvosContext); - if (eHAL_STATUS_SUCCESS != hstatus) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", - __func__); - /* we'll returned a cached value below */ - } - else - { - /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - /* either we have a response or we timed out - either way, first invalidate our magic */ - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while retrieving RSSI ", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - *rssi_value = pAdapter->rssi; - - return VOS_STATUS_SUCCESS; -} - -VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) -{ - struct statsContext context; - hdd_context_t *pHddCtx; - hdd_station_ctx_t *pHddStaCtx; - eHalStatus hstatus; - long lrc; - int valid; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Invalid context, pAdapter", __func__); - return VOS_STATUS_E_FAULT; - } - - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - - valid = wlan_hdd_validate_context(pHddCtx); - if (0 != valid) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); - return VOS_STATUS_E_FAULT; - } - - pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - if (NULL == pHddStaCtx) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD STA context is not valid")); - return VOS_STATUS_E_FAULT; - } - - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = SNR_CONTEXT_MAGIC; - - hstatus = sme_GetSnr(pHddCtx->hHal, hdd_GetSnrCB, - pHddStaCtx->conn_info.staId[ 0 ], - pHddStaCtx->conn_info.bssId, - &context); - if (eHAL_STATUS_SUCCESS != hstatus) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", - __func__); - /* we'll returned a cached value below */ - } - else - { - /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - /* either we have a response or we timed out - * either way, first invalidate our magic - */ - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while retrieving SNR ", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - * function could be executing at the same time we are. Of - * primary concern is if the callback function had already - * verified the "magic" but hasn't yet set the completion - * variable. Since the completion variable is on our - * stack, we'll delay just a bit to make sure the data is - * still valid if that is the case - */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - *snr = pAdapter->snr; - - return VOS_STATUS_SUCCESS; -} -#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) - -static void hdd_GetRoamRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - if (ioctl_debug) - { - pr_info("%s: rssi [%d] STA [%d] pContext [%p]\n", - __func__, (int)rssi, (int)staId, pContext); - } - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%p]", - __func__, pContext); - return; - } - - /* there is a race condition that exists between this callback function - and the caller since the caller could time out either before or - while this code is executing. we'll assume the timeout hasn't - occurred, but we'll verify that right before we save our work */ - - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (RSSI_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%p] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* the race is on. caller could have timed out immediately after - we verified the magic, but if so, caller will wait a short time - for us to copy over the rssi */ - pAdapter->rssi = rssi; - - /* and notify the caller */ - complete(&pStatsContext->completion); -} - - - -VOS_STATUS wlan_hdd_get_roam_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) -{ - struct statsContext context; - hdd_context_t *pHddCtx = NULL; - hdd_station_ctx_t *pHddStaCtx = NULL; - eHalStatus hstatus; - long lrc; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter", __func__); - return VOS_STATUS_E_FAULT; - } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__); - /* return a cached value */ - *rssi_value = pAdapter->rssi; - return VOS_STATUS_SUCCESS; - } - - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__); - /* return a cached value */ - *rssi_value = 0; - return VOS_STATUS_SUCCESS; - } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = RSSI_CONTEXT_MAGIC; - - hstatus = sme_GetRoamRssi(pHddCtx->hHal, hdd_GetRoamRssiCB, - pHddStaCtx->conn_info.staId[ 0 ], - pHddStaCtx->conn_info.bssId, - &context, pHddCtx->pvosContext); - if (eHAL_STATUS_SUCCESS != hstatus) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", - __func__); - /* we'll returned a cached value below */ - } - else - { - /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - /* either we have a response or we timed out - either way, first invalidate our magic */ - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while retrieving RSSI ", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - *rssi_value = pAdapter->rssi; - - return VOS_STATUS_SUCCESS; -} -#endif - - -void hdd_StatisticsCB( void *pStats, void *pContext ) -{ - hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext; - hdd_stats_t *pStatsCache = NULL; - hdd_wext_state_t *pWextState; - VOS_STATUS vos_status = VOS_STATUS_SUCCESS; - - tCsrSummaryStatsInfo *pSummaryStats = NULL; - tCsrGlobalClassAStatsInfo *pClassAStats = NULL; - tCsrGlobalClassBStatsInfo *pClassBStats = NULL; - tCsrGlobalClassCStatsInfo *pClassCStats = NULL; - tCsrGlobalClassDStatsInfo *pClassDStats = NULL; - tCsrPerStaStatsInfo *pPerStaStats = NULL; - - if (pAdapter!= NULL) - pStatsCache = &pAdapter->hdd_stats; - - - pSummaryStats = (tCsrSummaryStatsInfo *)pStats; - pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 ); - pClassBStats = (tCsrGlobalClassBStatsInfo *)( pClassAStats + 1 ); - pClassCStats = (tCsrGlobalClassCStatsInfo *)( pClassBStats + 1 ); - pClassDStats = (tCsrGlobalClassDStatsInfo *)( pClassCStats + 1 ); - pPerStaStats = (tCsrPerStaStatsInfo *)( pClassDStats + 1 ); - - if (pStatsCache!=NULL) - { - // and copy the stats into the cache we keep in the adapter instance structure - vos_mem_copy( &pStatsCache->summary_stat, pSummaryStats, sizeof( pStatsCache->summary_stat ) ); - vos_mem_copy( &pStatsCache->ClassA_stat, pClassAStats, sizeof( pStatsCache->ClassA_stat ) ); - vos_mem_copy( &pStatsCache->ClassB_stat, pClassBStats, sizeof( pStatsCache->ClassB_stat ) ); - vos_mem_copy( &pStatsCache->ClassC_stat, pClassCStats, sizeof( pStatsCache->ClassC_stat ) ); - vos_mem_copy( &pStatsCache->ClassD_stat, pClassDStats, sizeof( pStatsCache->ClassD_stat ) ); - vos_mem_copy( &pStatsCache->perStaStats, pPerStaStats, sizeof( pStatsCache->perStaStats ) ); - } - - if(pAdapter) - { - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - if(pWextState) - { - vos_status = vos_event_set(&pWextState->vosevent); - if (!VOS_IS_STATUS_SUCCESS(vos_status)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: vos_event_set failed", __func__); - return; - } - } - } -} - -void ccmCfgSetCallback(tHalHandle halHandle, tANI_S32 result) -{ - v_CONTEXT_t pVosContext; - hdd_context_t *pHddCtx; - VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx ); -#if 0 - hdd_wext_state_t *pWextState; - v_U32_t roamId; -#endif - - ENTER(); - - pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS,NULL); - - pHddCtx = (hdd_context_t*) vos_get_context(VOS_MODULE_ID_HDD,pVosContext); - if (NULL == pHddCtx) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid pHddCtx", __func__); - return; - } -#if 0 - pWextState = pAdapter->pWextState; -#endif - - if (WNI_CFG_NEED_RESTART == result || WNI_CFG_NEED_RELOAD == result) - { - //TODO Verify is this is really used. If yes need to fix it. - hdd_reconnect_all_adapters( pHddCtx ); -#if 0 - pAdapter->conn_info.connState = eConnectionState_NotConnected; - INIT_COMPLETION(pAdapter->disconnect_comp_var); - vosStatus = sme_RoamDisconnect(halHandle, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); - - if(VOS_STATUS_SUCCESS == vosStatus) - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - - sme_RoamConnect(halHandle, - pAdapter->sessionId, &(pWextState->roamProfile), - &roamId); -#endif - } - - EXIT(); - -} - -void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) -{ - int i = 0; - hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - /* clear WPA/RSN/WSC IE information in the profile */ - pWextState->roamProfile.nWPAReqIELength = 0; - pWextState->roamProfile.pWPAReqIE = (tANI_U8 *)NULL; - pWextState->roamProfile.nRSNReqIELength = 0; - pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL; - -#ifdef FEATURE_WLAN_WAPI - pWextState->roamProfile.nWAPIReqIELength = 0; - pWextState->roamProfile.pWAPIReqIE = (tANI_U8 *)NULL; -#endif - - pWextState->roamProfile.bWPSAssociation = VOS_FALSE; - pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL; - pWextState->roamProfile.nAddIEScanLength = 0; - pWextState->roamProfile.pAddIEAssoc = (tANI_U8 *)NULL; - pWextState->roamProfile.nAddIEAssocLength = 0; - - pWextState->roamProfile.EncryptionType.numEntries = 1; - pWextState->roamProfile.EncryptionType.encryptionType[0] - = eCSR_ENCRYPT_TYPE_NONE; - - pWextState->roamProfile.mcEncryptionType.numEntries = 1; - pWextState->roamProfile.mcEncryptionType.encryptionType[0] - = eCSR_ENCRYPT_TYPE_NONE; - - pWextState->roamProfile.AuthType.numEntries = 1; - pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; - -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE; - pWextState->roamProfile.MFPRequired = 0; - pWextState->roamProfile.MFPCapable = 0; -#endif - - pWextState->authKeyMgmt = 0; - - for (i=0; i < CSR_MAX_NUM_KEY; i++) - { - if (pWextState->roamProfile.Keys.KeyMaterial[i]) - { - pWextState->roamProfile.Keys.KeyLength[i] = 0; - } - } -#ifdef FEATURE_WLAN_WAPI - pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_OPEN; - pAdapter->wapi_info.nWapiMode = 0; -#endif - - vos_mem_zero((void *)(pWextState->req_bssId), WNI_CFG_BSSID_LEN); - -} - -void wlan_hdd_ula_done_cb(v_VOID_t *callbackContext) -{ - hdd_adapter_t *pAdapter = (hdd_adapter_t*)callbackContext; - - if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Invalid pAdapter magic", __func__); - } - else - { - complete(&pAdapter->ula_complete); - } -} - -VOS_STATUS wlan_hdd_check_ula_done(hdd_adapter_t *pAdapter) -{ - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - VOS_STATUS vos_status; - unsigned long rc; - - if (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated) - { - INIT_COMPLETION(pAdapter->ula_complete); - - /*To avoid race condition between the set key and the last EAPOL - packet, notify TL to finish upper layer authentication incase if the - last EAPOL packet pending in the TL queue.*/ - vos_status = WLANTL_Finish_ULA(wlan_hdd_ula_done_cb, pAdapter); - - if ( vos_status != VOS_STATUS_SUCCESS ) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "[%4d] WLANTL_Finish_ULA returned ERROR status= %d", - __LINE__, vos_status ); - return vos_status; - - } - - rc = wait_for_completion_timeout(&pAdapter->ula_complete, - msecs_to_jiffies(HDD_FINISH_ULA_TIME_OUT)); - if (0 == rc) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Timeout waiting for ULA to complete", __func__); - /* we'll still fall through and return success since the - * connection may still get established but is just taking - * too long for us to wait */ - } - } - return VOS_STATUS_SUCCESS; -} - -v_U8_t* wlan_hdd_get_vendor_oui_ie_ptr(v_U8_t *oui, v_U8_t oui_size, v_U8_t *ie, int ie_len) -{ - - int left = ie_len; - v_U8_t *ptr = ie; - v_U8_t elem_id,elem_len; - v_U8_t eid = 0xDD; - - if ( NULL == ie || 0 == ie_len ) - return NULL; - - while(left >= 2) - { - elem_id = ptr[0]; - elem_len = ptr[1]; - left -= 2; - if(elem_len > left) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), - eid,elem_len,left); - return NULL; - } - if (elem_id == eid) - { - if(memcmp( &ptr[2], oui, oui_size)==0) - return ptr; - } - - left -= elem_len; - ptr += (elem_len + 2); - } - return NULL; -} - -static int iw_set_commit(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hddLog( LOG1, "In %s\n", __func__); - /* Do nothing for now */ - return 0; -} - -static int iw_get_name(struct net_device *dev, - struct iw_request_info *info, - char *wrqu, char *extra) -{ - - ENTER(); - strlcpy(wrqu, "Qcom:802.11n", IFNAMSIZ); - EXIT(); - return 0; -} - -static int iw_set_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tCsrRoamProfile *pRoamProfile; - eCsrRoamBssType LastBSSType; - eMib_dot11DesiredBssType connectedBssType; - hdd_config_t *pConfig; - struct wireless_dev *wdev; - - ENTER(); - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter", __func__); - return 0; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return 0; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - if (pWextState == NULL) - { - hddLog(LOGE, "%s ERROR: Data Storage Corruption", __func__); - return -EINVAL; - } - - wdev = dev->ieee80211_ptr; - pRoamProfile = &pWextState->roamProfile; - LastBSSType = pRoamProfile->BSSType; - - hddLog(LOG1, "%s Old Bss type = %d", __func__, LastBSSType); - - switch (wrqu->mode) - { - case IW_MODE_ADHOC: - hddLog(LOG1, "%s Setting AP Mode as IW_MODE_ADHOC", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; - // Set the phymode correctly for IBSS. - pConfig = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; - pWextState->roamProfile.phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); - pAdapter->device_mode = WLAN_HDD_IBSS; - wdev->iftype = NL80211_IFTYPE_ADHOC; - break; - case IW_MODE_INFRA: - hddLog(LOG1, "%s Setting AP Mode as IW_MODE_INFRA", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; - wdev->iftype = NL80211_IFTYPE_STATION; - break; - case IW_MODE_AUTO: - hddLog(LOG1, "%s Setting AP Mode as IW_MODE_AUTO", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_ANY; - break; - default: - hddLog(LOG1, "%s Unknown AP Mode value", __func__); - return -EOPNOTSUPP; - } - - if ( LastBSSType != pRoamProfile->BSSType ) - { - //the BSS mode changed - // We need to issue disconnect if connected or in IBSS disconnect state - if ( hdd_connGetConnectedBssType( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) || - ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) ) - { - VOS_STATUS vosStatus; - // need to issue a disconnect to CSR. - INIT_COMPLETION(pAdapter->disconnect_comp_var); - vosStatus = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, - eCSR_DISCONNECT_REASON_IBSS_LEAVE ); - if(VOS_STATUS_SUCCESS == vosStatus) - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - } - } - - EXIT(); - return 0; -} - - -static int iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - - hddLog(LOG1, "In %s", __func__); - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter", __func__); - return 0; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return 0; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - if (pWextState == NULL) - { - hddLog(LOGE, "%s ERROR: Data Storage Corruption", __func__); - return -EINVAL; - } - - switch (pWextState->roamProfile.BSSType) - { - case eCSR_BSS_TYPE_INFRASTRUCTURE: - hddLog(LOG1, "%s returns IW_MODE_INFRA\n", __func__); - wrqu->mode = IW_MODE_INFRA; - break; - case eCSR_BSS_TYPE_IBSS: - case eCSR_BSS_TYPE_START_IBSS: - hddLog(LOG1, "%s returns IW_MODE_ADHOC\n", __func__); - wrqu->mode = IW_MODE_ADHOC; - break; - case eCSR_BSS_TYPE_ANY: - hddLog(LOG1, "%s returns IW_MODE_AUTO\n", __func__); - wrqu->mode = IW_MODE_AUTO; - break; - default: - hddLog(LOG1, "%s returns APMODE_UNKNOWN\n", __func__); - break; - } - - return 0; -} - -static int iw_set_freq(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - v_U32_t numChans = 0; - v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; - v_U32_t indx = 0; - v_U32_t status = 0; - - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - tCsrRoamProfile * pRoamProfile; - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return status; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - pRoamProfile = &pWextState->roamProfile; - - hddLog(LOG1,"setCHANNEL ioctl\n"); - - /* Link is up then return cant set channel*/ - if(eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState || - eConnectionState_Associated == pHddStaCtx->conn_info.connState) - { - hddLog( LOGE, "IBSS Associated\n"); - return -EOPNOTSUPP; - } - - /* Settings by Frequency as input */ - if((wrqu->freq.e == 1) && (wrqu->freq.m >= (tANI_U32)2.412e8) && - (wrqu->freq.m <= (tANI_U32)5.825e8)) - { - tANI_U32 freq = wrqu->freq.m / 100000; - - while ((indx < FREQ_CHAN_MAP_TABLE_SIZE) && (freq != freq_chan_map[indx].freq)) - indx++; - if (indx >= FREQ_CHAN_MAP_TABLE_SIZE) - { - return -EINVAL; - } - wrqu->freq.e = 0; - wrqu->freq.m = freq_chan_map[indx].chan; - - } - - if (wrqu->freq.e == 0) - { - if((wrqu->freq.m < WNI_CFG_CURRENT_CHANNEL_STAMIN) || - (wrqu->freq.m > WNI_CFG_CURRENT_CHANNEL_STAMAX)) - { - hddLog(LOG1,"%s: Channel [%d] is outside valid range from %d to %d\n", - __func__, wrqu->freq.m, WNI_CFG_CURRENT_CHANNEL_STAMIN, - WNI_CFG_CURRENT_CHANNEL_STAMAX); - return -EINVAL; - } - - numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; - - if (ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, - validChan, &numChans) != eHAL_STATUS_SUCCESS){ - return -EIO; - } - - for (indx = 0; indx < numChans; indx++) { - if (wrqu->freq.m == validChan[indx]){ - break; - } - } - } - else{ - - return -EINVAL; - } - - if(indx >= numChans) - { - return -EINVAL; - } - - /* Set the Operational Channel */ - numChans = pRoamProfile->ChannelInfo.numOfChannels = 1; - pHddStaCtx->conn_info.operationChannel = wrqu->freq.m; - pRoamProfile->ChannelInfo.ChannelList = &pHddStaCtx->conn_info.operationChannel; - - hddLog(LOG1,"pRoamProfile->operationChannel = %d\n", wrqu->freq.m); - - EXIT(); - - return status; -} - -static int iw_get_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - v_U32_t status = FALSE, channel = 0, freq = 0; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal; - hdd_wext_state_t *pWextState; - tCsrRoamProfile * pRoamProfile; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return status; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - - pRoamProfile = &pWextState->roamProfile; - - if( pHddStaCtx->conn_info.connState== eConnectionState_Associated ) - { - if (sme_GetOperationChannel(hHal, &channel, pAdapter->sessionId) != eHAL_STATUS_SUCCESS) - { - return -EIO; - } - else - { - status = hdd_wlan_get_freq(channel, &freq); - if( TRUE == status ) - { - /* Set Exponent parameter as 6 (MHZ) in struct iw_freq - * iwlist & iwconfig command shows frequency into proper - * format (2.412 GHz instead of 246.2 MHz)*/ - fwrq->m = freq; - fwrq->e = MHZ; - } - } - } - else - { - /* Set Exponent parameter as 6 (MHZ) in struct iw_freq - * iwlist & iwconfig command shows frequency into proper - * format (2.412 GHz instead of 246.2 MHz)*/ - fwrq->m = 0; - fwrq->e = MHZ; - } - return 0; -} - -static int iw_get_tx_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!",__func__); - return -EBUSY; - } - - if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) - { - wrqu->txpower.value = 0; - return 0; - } - wlan_hdd_get_classAstats(pAdapter); - wrqu->txpower.value = pAdapter->hdd_stats.ClassA_stat.max_pwr; - - return 0; -} - -static int iw_set_tx_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - ENTER(); - - if ( ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, wrqu->txpower.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - - EXIT(); - - return 0; -} - -static int iw_get_bitrate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - VOS_STATUS vos_status = VOS_STATUS_SUCCESS; - eHalStatus status = eHAL_STATUS_SUCCESS; - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return status; - } - - if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) { - wrqu->bitrate.value = 0; - } - else { - status = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD, - SME_SUMMARY_STATS | - SME_GLOBAL_CLASSA_STATS | - SME_GLOBAL_CLASSB_STATS | - SME_GLOBAL_CLASSC_STATS | - SME_GLOBAL_CLASSD_STATS | - SME_PER_STA_STATS, - hdd_StatisticsCB, 0, FALSE, - pHddStaCtx->conn_info.staId[0], pAdapter ); - - if(eHAL_STATUS_SUCCESS != status) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to retrieve statistics", - __func__); - return status; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS); - - if (!VOS_IS_STATUS_SUCCESS(vos_status)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME timeout while retrieving statistics", - __func__); - return VOS_STATUS_E_FAILURE; - } - - wrqu->bitrate.value = pAdapter->hdd_stats.ClassA_stat.tx_rate*500*1000; - } - - EXIT(); - - return vos_status; -} -/* ccm call back function */ - -static int iw_set_bitrate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_wext_state_t *pWextState; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; - v_U32_t a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; - v_U32_t b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; - v_U32_t i, rate; - v_U32_t valid_rate = FALSE, active_phy_mode = 0; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) - { - return -ENXIO ; - } - - rate = wrqu->bitrate.value; - - if (rate == -1) - { - rate = WNI_CFG_FIXED_RATE_AUTO; - valid_rate = TRUE; - } - else if (ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), - WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS) - { - if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G - || active_phy_mode == WNI_CFG_DOT11_MODE_11B) - { - if ((ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), - WNI_CFG_SUPPORTED_RATES_11A, - supp_rates, &a_len) == eHAL_STATUS_SUCCESS) && - (ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), - WNI_CFG_SUPPORTED_RATES_11B, - supp_rates, &b_len) == eHAL_STATUS_SUCCESS)) - { - for (i = 0; i < (b_len + a_len); ++i) - { - /* supported rates returned is double the actual rate so we divide it by 2 */ - if ((supp_rates[i]&0x7F)/2 == rate) - { - valid_rate = TRUE; - rate = i + WNI_CFG_FIXED_RATE_1MBPS; - break; - } - } - } - } - } - if (valid_rate != TRUE) - { - return -EINVAL; - } - if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), - WNI_CFG_FIXED_RATE, rate, - ccmCfgSetCallback,eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS) - { - return -EIO; - } - return 0; -} - - -static int iw_set_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - u_int8_t *genie = (u_int8_t *)extra; - v_U16_t remLen; - - ENTER(); - if(!wrqu->data.length) { - hdd_clearRoamProfileIe(pAdapter); - EXIT(); - return 0; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - remLen = wrqu->data.length; - - hddLog(LOG1,"iw_set_genie ioctl IE[0x%X], LEN[%d]\n", genie[0], genie[1]); - - /* clear any previous genIE before this call */ - memset( &pWextState->genIE, 0, sizeof(pWextState->genIE) ); - - while (remLen >= 2) - { - v_U16_t eLen = 0; - v_U8_t elementId; - elementId = *genie++; - eLen = *genie++; - remLen -= 2; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n", - __func__, elementId, eLen); - - switch ( elementId ) - { - case IE_EID_VENDOR: - if ((IE_LEN_SIZE+IE_EID_SIZE+IE_VENDOR_OUI_SIZE) > eLen) /* should have at least OUI */ - return -EINVAL; - - if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) - { - v_U16_t curGenIELen = pWextState->genIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS OUI(%02x %02x %02x %02x) IE(len %d)", - __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2); - - if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) ) - { - hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " - "Need bigger buffer space\n"); - VOS_ASSERT(0); - return -ENOMEM; - } - // save to Additional IE ; it should be accumulated to handle WPS IE + other IE - memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2); - pWextState->genIE.length += eLen + 2; - } - else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) - { - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2); - memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); - memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)); - pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE; - pWextState->roamProfile.nWPAReqIELength = eLen + 2; - } - else /* any vendorId except WPA IE should be accumulated to genIE */ - { - v_U16_t curGenIELen = pWextState->genIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OUI(%02x %02x %02x %02x) IE(len %d)", - __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2); - - if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) ) - { - hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " - "Need bigger buffer space\n"); - VOS_ASSERT(0); - return -ENOMEM; - } - // save to Additional IE ; it should be accumulated to handle WPS IE + other IE - memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2); - pWextState->genIE.length += eLen + 2; - } - break; - case DOT11F_EID_RSN: - hddLog (LOG1, "%s Set RSN IE (len %d)",__func__, eLen+2); - memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); - memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)); - pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE; - pWextState->roamProfile.nRSNReqIELength = eLen + 2; - break; - - default: - hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, elementId); - return 0; - } - genie += eLen; - remLen -= eLen; - } - EXIT(); - return 0; -} - -static int iw_get_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - eHalStatus status; - v_U32_t length = DOT11F_IE_RSN_MAX_LEN; - v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN]; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - - hddLog(LOG1,"getGEN_IE ioctl\n"); - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - if( pHddStaCtx->conn_info.connState == eConnectionState_NotConnected) - { - return -ENXIO; - } - - // Return something ONLY if we are associated with an RSN or WPA network - if ( VOS_TRUE != hdd_IsAuthTypeRSN(WLAN_HDD_GET_HAL_CTX(pAdapter), - pWextState->roamProfile.negotiatedAuthType)) - { - return -ENXIO; - } - - // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.) - status = csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, - &length, - genIeBytes); - length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN); - if (wrqu->data.length < length) - { - hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); - return -EFAULT; - } - vos_mem_copy( extra, (v_VOID_t*)genIeBytes, wrqu->data.length); - wrqu->data.length = length; - - hddLog(LOG1,"%s: RSN IE of %d bytes returned\n", __func__, wrqu->data.length ); - - EXIT(); - - return 0; -} - -static int iw_get_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); - int keyId; - eCsrAuthType authType = eCSR_AUTH_TYPE_NONE; - int i; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - keyId = pRoamProfile->Keys.defaultIndex; - - if(keyId < 0 || keyId >= MAX_WEP_KEYS) - { - hddLog(LOG1,"%s: Invalid keyId : %d\n",__func__,keyId); - return -EINVAL; - } - - if(pRoamProfile->Keys.KeyLength[keyId] > 0) - { - dwrq->flags |= IW_ENCODE_ENABLED; - dwrq->length = pRoamProfile->Keys.KeyLength[keyId]; - vos_mem_copy(extra,&(pRoamProfile->Keys.KeyMaterial[keyId][0]),pRoamProfile->Keys.KeyLength[keyId]); - - dwrq->flags |= (keyId + 1); - - } - else - { - dwrq->flags |= IW_ENCODE_DISABLED; - } - - for(i=0; i < MAX_WEP_KEYS; i++) - { - if(pRoamProfile->Keys.KeyMaterial[i] == NULL) - { - continue; - } - else - { - break; - } - } - - if(MAX_WEP_KEYS == i) - { - dwrq->flags |= IW_ENCODE_NOKEY; - } - - authType = ((hdd_station_ctx_t*)WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; - - if(eCSR_AUTH_TYPE_OPEN_SYSTEM == authType) - { - dwrq->flags |= IW_ENCODE_OPEN; - } - else - { - dwrq->flags |= IW_ENCODE_RESTRICTED; - } - EXIT(); - return 0; -} - -#define PAE_ROLE_AUTHENTICATOR 1 // =1 for authenticator, -#define PAE_ROLE_SUPPLICANT 0 // =0 for supplicant - - -/* - * This function sends a single 'key' to LIM at all time. - */ - -static int iw_get_rts_threshold(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - v_U32_t status = 0; - - status = hdd_wlan_get_rts_threshold(pAdapter,wrqu); - - return status; -} - -static int iw_set_rts_threshold(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } - if ( wrqu->rts.value < WNI_CFG_RTS_THRESHOLD_STAMIN || wrqu->rts.value > WNI_CFG_RTS_THRESHOLD_STAMAX ) - { - return -EINVAL; - } - - if ( ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, wrqu->rts.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - - EXIT(); - - return 0; -} - -static int iw_get_frag_threshold(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - v_U32_t status = 0; - - status = hdd_wlan_get_frag_threshold(pAdapter,wrqu); - - return status; -} - -static int iw_set_frag_threshold(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - if ( wrqu->frag.value < WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN || wrqu->frag.value > WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX ) - { - return -EINVAL; - } - - if ( ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, wrqu->frag.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - - EXIT(); - - return 0; -} - -static int iw_get_power_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - ENTER(); - return -EOPNOTSUPP; -} - -static int iw_set_power_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - ENTER(); - return -EOPNOTSUPP; -} - -static int iw_get_range(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - struct iw_range *range = (struct iw_range *) extra; - - v_U8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN]; - - v_U32_t num_channels = sizeof(channels); - v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; - v_U32_t a_len; - v_U32_t b_len; - v_U32_t active_phy_mode = 0; - v_U8_t index = 0, i; - - ENTER(); - - wrqu->data.length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - /*Get the phy mode*/ - if (ccmCfgGetInt(hHal, - WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "active_phy_mode = %ld", active_phy_mode); - - if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G) - { - /*Get the supported rates for 11G band*/ - a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; - if (ccmCfgGetStr(hHal, - WNI_CFG_SUPPORTED_RATES_11A, - supp_rates, &a_len) == eHAL_STATUS_SUCCESS) - { - if (a_len > WNI_CFG_SUPPORTED_RATES_11A_LEN) - { - a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; - } - for (i = 0; i < a_len; i++) - { - range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000; - } - range->num_bitrates = a_len; - } - else - { - return -EIO; - } - } - else if (active_phy_mode == WNI_CFG_DOT11_MODE_11B) - { - /*Get the supported rates for 11B band*/ - b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; - if (ccmCfgGetStr(hHal, - WNI_CFG_SUPPORTED_RATES_11B, - supp_rates, &b_len) == eHAL_STATUS_SUCCESS) - { - if (b_len > WNI_CFG_SUPPORTED_RATES_11B_LEN) - { - b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; - } - for (i = 0; i < b_len; i++) - { - range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000; - } - range->num_bitrates = b_len; - } - else - { - return -EIO; - } - } - } - - range->max_rts = WNI_CFG_RTS_THRESHOLD_STAMAX; - range->min_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN; - range->max_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = MAX_WEP_KEYS; - - // we support through Wireless Extensions 22 - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 22; - - /*Supported Channels and Frequencies*/ - if (ccmCfgGetStr((hHal), WNI_CFG_VALID_CHANNEL_LIST, channels, &num_channels) != eHAL_STATUS_SUCCESS) - { - return -EIO; - } - if (num_channels > IW_MAX_FREQUENCIES) - { - num_channels = IW_MAX_FREQUENCIES; - } - - range->num_channels = num_channels; - range->num_frequency = num_channels; - - for (index=0; index < num_channels; index++) - { - v_U32_t frq_indx = 0; - - range->freq[index].i = channels[index]; - while (frq_indx < FREQ_CHAN_MAP_TABLE_SIZE) - { - if(channels[index] == freq_chan_map[frq_indx].chan) - { - range->freq[index].m = freq_chan_map[frq_indx].freq * 100000; - range->freq[index].e = 1; - break; - } - frq_indx++; - } - } - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - - /*Encryption capability*/ - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - /* Txpower capability */ - range->txpower_capa = IW_TXPOW_MWATT; - - /*Scanning capability*/ - #if WIRELESS_EXT >= 22 - range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_CHANNEL; - #endif - - EXIT(); - return 0; -} - -/* Callback function registered with PMC to know status of PMC request */ -static void iw_power_callback_fn (void *pContext, eHalStatus status) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%p]", - __func__, pContext); - return; - } - - /* there is a race condition that exists between this callback function - and the caller since the caller could time out either before or - while this code is executing. we'll assume the timeout hasn't - occurred, but we'll verify that right before we save our work */ - - pStatsContext = (struct statsContext *)pContext; - pAdapter = pStatsContext->pAdapter; - - if ((NULL == pAdapter) || (POWER_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%p] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* and notify the caller */ - complete(&pStatsContext->completion); -} - -/* Callback function for tx per hit */ -void hdd_tx_per_hit_cb (void *pCallbackContext) -{ - hdd_adapter_t *pAdapter = (hdd_adapter_t *)pCallbackContext; - unsigned char tx_fail[16]; - union iwreq_data wrqu; - - if (NULL == pAdapter) - { - hddLog(LOGE, "hdd_tx_per_hit_cb: pAdapter is NULL\n"); - return; - } - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlcpy(tx_fail, "TX_FAIL", sizeof(tx_fail)); - wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, tx_fail); -} - -void hdd_GetClassA_statisticsCB(void *pStats, void *pContext) -{ - struct statsContext *pStatsContext; - tCsrGlobalClassAStatsInfo *pClassAStats; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: pStats [%p] pContext [%p]\n", - __func__, pStats, pContext); - } - - if ((NULL == pStats) || (NULL == pContext)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pStats [%p] pContext [%p]", - __func__, pStats, pContext); - return; - } - - /* there is a race condition that exists between this callback function - and the caller since the caller could time out either before or - while this code is executing. we'll assume the timeout hasn't - occurred, but we'll verify that right before we save our work */ - - pClassAStats = pStats; - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%p] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* the race is on. caller could have timed out immediately after - we verified the magic, but if so, caller will wait a short time - for us to copy over the stats. do so as a struct copy */ - pAdapter->hdd_stats.ClassA_stat = *pClassAStats; - - /* and notify the caller */ - complete(&pStatsContext->completion); -} - -VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) -{ - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - eHalStatus hstatus; - long lrc; - struct statsContext context; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Padapter is NULL", __func__); - return VOS_STATUS_E_FAULT; - } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__); - return VOS_STATUS_SUCCESS; - } - - /* we are connected - prepare our callback context */ - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; - /* query only for Class A statistics (which include link speed) */ - hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), - eCSR_HDD, - SME_GLOBAL_CLASSA_STATS, - hdd_GetClassA_statisticsCB, - 0, // not periodic - FALSE, //non-cached results - pHddStaCtx->conn_info.staId[0], - &context); - if (eHAL_STATUS_SUCCESS != hstatus) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to retrieve Class A statistics ", - __func__); - /* we'll returned a cached value below */ - } - else - { - /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - /* either we have a response or we timed out - either way, first invalidate our magic */ - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while retrieving Class A statistics", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - } - } - return VOS_STATUS_SUCCESS; -} - -static void hdd_get_station_statisticsCB(void *pStats, void *pContext) -{ - struct statsContext *pStatsContext; - tCsrSummaryStatsInfo *pSummaryStats; - tCsrGlobalClassAStatsInfo *pClassAStats; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: pStats [%p] pContext [%p]\n", - __func__, pStats, pContext); - } - - if ((NULL == pStats) || (NULL == pContext)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pStats [%p] pContext [%p]", - __func__, pStats, pContext); - return; - } - - /* there is a race condition that exists between this callback function - and the caller since the caller could time out either before or - while this code is executing. we'll assume the timeout hasn't - occurred, but we'll verify that right before we save our work */ - - pSummaryStats = (tCsrSummaryStatsInfo *)pStats; - pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 ); - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%p] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* the race is on. caller could have timed out immediately after - we verified the magic, but if so, caller will wait a short time - for us to copy over the stats. do so as a struct copy */ - pAdapter->hdd_stats.summary_stat = *pSummaryStats; - pAdapter->hdd_stats.ClassA_stat = *pClassAStats; - - /* and notify the caller */ - complete(&pStatsContext->completion); -} - -VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) -{ - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - eHalStatus hstatus; - long lrc; - struct statsContext context; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Padapter is NULL", __func__); - return VOS_STATUS_SUCCESS; - } - - /* we are connected - prepare our callback context */ - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; - - /* query only for Summary & Class A statistics */ - hstatus = sme_GetStatistics(WLAN_HDD_GET_HAL_CTX(pAdapter), - eCSR_HDD, - SME_SUMMARY_STATS | - SME_GLOBAL_CLASSA_STATS, - hdd_get_station_statisticsCB, - 0, // not periodic - FALSE, //non-cached results - pHddStaCtx->conn_info.staId[0], - &context); - if (eHAL_STATUS_SUCCESS != hstatus) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to retrieve statistics", - __func__); - /* we'll return with cached values */ - } - else - { - /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - /* either we have a response or we timed out - either way, first invalidate our magic */ - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while retrieving statistics", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - } - } - return VOS_STATUS_SUCCESS; -} - - -/* - * Support for the LINKSPEED private command - * Per the WiFi framework the response must be of the form - * "LinkSpeed xx" - */ -static int iw_get_linkspeed(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_context_t *pHddCtx; - char *pLinkSpeed = (char*)extra; - int len = sizeof(v_U32_t) + 1; - v_U32_t link_speed = 0; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - VOS_STATUS status; - int rc, valid; - - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - - valid = wlan_hdd_validate_context(pHddCtx); - - if (0 != valid) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); - return valid; - } - - if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) - { - /* we are not connected so we don't have a classAstats */ - link_speed = 0; - } - else - { - status = wlan_hdd_get_classAstats(pAdapter); - - if (!VOS_IS_STATUS_SUCCESS(status )) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics")); - return -EINVAL; - } - - /* Unit of link capacity is obtained from the TL API is MbpsX10 */ - WLANTL_GetSTALinkCapacity(WLAN_HDD_GET_CTX(pAdapter)->pvosContext, - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], - &link_speed); - - link_speed = link_speed / 10; - - if (0 == link_speed) - { - /* The linkspeed returned by HAL is in units of 500kbps. - * converting it to mbps. - * This is required to support legacy firmware which does - * not return link capacity. - */ - link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2; - } - - } - - wrqu->data.length = len; - // return the linkspeed in the format required by the WiFi Framework - rc = snprintf(pLinkSpeed, len, "%u", link_speed); - if ((rc < 0) || (rc >= len)) - { - // encoding or length error? - hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed")); - return -EIO; - } - - /* a value is being successfully returned */ - return 0; -} - - -/* - * Support for the RSSI & RSSI-APPROX private commands - * Per the WiFi framework the response must be of the form - * "<ssid> rssi <xx>" - * unless we are not associated, in which case the response is - * "OK" - */ -static int iw_get_rssi(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - char *cmd = extra; - int len = wrqu->data.length; - v_S7_t s7Rssi = 0; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length; - VOS_STATUS vosStatus; - int rc; - - if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || - (0 == ssidlen) || (ssidlen >= len)) - { - /* we are not connected or our SSID is too long - so we cannot report an rssi */ - rc = scnprintf(cmd, len, "OK"); - } - else - { - /* we are connected with a valid SSID - so we can write the SSID into the return buffer - (note that it is not NUL-terminated) */ - memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen ); - - vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi); - - if (VOS_STATUS_SUCCESS == vosStatus) - { - /* append the rssi to the ssid in the format required by - the WiFI Framework */ - rc = scnprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi); - } - else - { - rc = -1; - } - } - - /* verify that we wrote a valid response */ - if ((rc < 0) || (rc >= len)) - { - // encoding or length error? - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to encode RSSI, got [%s]", - __func__, cmd); - return -EIO; - } - - /* a value is being successfully returned */ - return 0; -} - -/* - * Support for SoftAP channel range private command - */ -static int iw_softap_set_channel_range( struct net_device *dev, - int startChannel, - int endChannel, - int band) -{ - VOS_STATUS status; - int ret = 0; - hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); - - - status = WLANSAP_SetChannelRange(hHal, startChannel, endChannel, band); - if (VOS_STATUS_SUCCESS != status) - { - ret = -EINVAL; - } - pHddCtx->is_dynamic_channel_range_set = 1; - return ret; -} - -VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) -{ - struct statsContext context; - eHalStatus status; - hdd_context_t *pHddCtx; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_FATAL, "Adapter NULL"); - return VOS_STATUS_E_FAULT; - } - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "power mode=%d", mode); - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - init_completion(&context.completion); - - context.pAdapter = pAdapter; - context.magic = POWER_CONTEXT_MAGIC; - - if (DRIVER_POWER_MODE_ACTIVE == mode) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering " - "Full Power", __func__); - status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context, - eSME_FULL_PWR_NEEDED_BY_HDD); - // Enter Full power command received from GUI this means we are disconnected - // Set PMC remainInPowerActiveTillDHCP flag to disable auto BMPS entry by PMC - sme_SetDHCPTillPowerActiveFlag(pHddCtx->hHal, TRUE); - if (eHAL_STATUS_PMC_PENDING == status) - { - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while requesting fullpower ", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - } - else if (DRIVER_POWER_MODE_AUTO == mode) - { - if (pHddCtx->cfg_ini->fIsBmpsEnabled) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering Bmps ", - __func__); - // Enter BMPS command received from GUI this means DHCP is completed - // Clear PMC remainInPowerActiveTillDHCP flag to enable auto BMPS entry - sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter), - FALSE); - status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context); - if (eHAL_STATUS_PMC_PENDING == status) - { - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while requesting BMPS ", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - } - else - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "BMPS is not " - "enabled in the cfg"); - } - } - return VOS_STATUS_SUCCESS; -} - -VOS_STATUS wlan_hdd_set_powersave(hdd_adapter_t *pAdapter, int mode) -{ - hdd_context_t *pHddCtx; - - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_FATAL, "Adapter NULL"); - return VOS_STATUS_E_FAULT; - } - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "power mode=%d", mode); - - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - - if (DRIVER_POWER_MODE_ACTIVE == mode) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering " - "Full Power", __func__); - - /* - * Enter Full power command received from GUI - * this means we are disconnected - */ - sme_PsOffloadDisablePowerSave(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId); - } - else if (DRIVER_POWER_MODE_AUTO == mode) - { - if (pHddCtx->cfg_ini->fIsBmpsEnabled) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering Bmps ", - __func__); - - /* - * Enter BMPS command received from GUI - * this means DHCP is completed - */ - sme_PsOffloadEnablePowerSave(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId); - } - else - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "BMPS is not " - "enabled in the cfg"); - } - } - return VOS_STATUS_SUCCESS; -} - -VOS_STATUS wlan_hdd_exit_lowpower(hdd_context_t *pHddCtx, - hdd_adapter_t *pAdapter) -{ - VOS_STATUS vos_Status; - - if ((NULL == pAdapter) || (NULL == pHddCtx)) - { - hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid pointer"); - return VOS_STATUS_E_FAULT; - } - - /**Exit from Deep sleep or standby if we get the driver - START cmd from android GUI - */ - if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit " - "from Stand by",__func__); - vos_Status = hdd_exit_standby(pHddCtx); - } - else if (eHDD_SUSPEND_DEEP_SLEEP == pHddCtx->hdd_ps_state) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit " - "from deep sleep",__func__); - vos_Status = hdd_exit_deep_sleep(pHddCtx, pAdapter); - } - else - { - hddLog(VOS_TRACE_LEVEL_WARN, "%s: Not in standby or deep sleep. " - "Ignore start cmd %d", __func__, pHddCtx->hdd_ps_state); - vos_Status = VOS_STATUS_SUCCESS; - } - - return vos_Status; -} - -VOS_STATUS wlan_hdd_enter_lowpower(hdd_context_t *pHddCtx) -{ - VOS_STATUS vos_Status = VOS_STATUS_E_FAILURE; - - if (NULL == pHddCtx) - { - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "HDD context NULL"); - return VOS_STATUS_E_FAULT; - } - - if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop) - { - //Execute standby procedure. - //Executing standby procedure will cause the STA to - //disassociate first and then the chip will be put into standby. - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering Stand by mode"); - vos_Status = hdd_enter_standby(pHddCtx); - } - else if (WLAN_MAP_DRIVER_STOP_TO_DEEP_SLEEP == - pHddCtx->cfg_ini->nEnableDriverStop) - { - //Execute deep sleep procedure - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering " - "deep sleep mode\n"); - //Deep sleep not supported - vos_Status = hdd_enter_standby(pHddCtx); - } - else - { - hddLog(VOS_TRACE_LEVEL_INFO_LOW, "%s: Driver stop is not enabled %d", - __func__, pHddCtx->cfg_ini->nEnableDriverStop); - vos_Status = VOS_STATUS_SUCCESS; - } - - return vos_Status; -} - - -void* wlan_hdd_change_country_code_callback(void *pAdapter) -{ - - hdd_adapter_t *call_back_pAdapter = pAdapter; - complete(&call_back_pAdapter->change_country_code); - - return NULL; -} - -static int iw_set_priv(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - char *cmd = extra; - int cmd_len = wrqu->data.length; - int ret = 0; - int status = 0; - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - - ENTER(); - - if (ioctl_debug) - { - pr_info("%s: req [%s] len [%d]\n", __func__, cmd, cmd_len); - } - - hddLog(VOS_TRACE_LEVEL_INFO_MED, - "%s: ***Received %s cmd from Wi-Fi GUI***", __func__, cmd); - - if (pHddCtx->isLogpInProgress) { - if (ioctl_debug) - { - pr_info("%s: RESTART in progress\n", __func__); - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!",__func__); - return status; - } - - if(strncmp(cmd, "CSCAN",5) == 0 ) - { - status = iw_set_cscan(dev, info, wrqu, extra); - } - else if( strcasecmp(cmd, "start") == 0 ) { - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Start command\n"); - /*Exit from Deep sleep or standby if we get the driver START cmd from android GUI*/ - status = wlan_hdd_exit_lowpower(pHddCtx, pAdapter); - - if(status == VOS_STATUS_SUCCESS) - { - union iwreq_data wrqu; - char buf[10]; - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlcpy(buf, "START", sizeof(buf)); - wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); - } - else - { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: START CMD Status %d", __func__, status); - } - goto done; - } - else if( strcasecmp(cmd, "stop") == 0 ) - { - union iwreq_data wrqu; - char buf[10]; - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Stop command\n"); - - wlan_hdd_enter_lowpower(pHddCtx); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlcpy(buf, "STOP", sizeof(buf)); - wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); - status = VOS_STATUS_SUCCESS; - goto done; - } - else if (strcasecmp(cmd, "macaddr") == 0) - { - ret = snprintf(cmd, cmd_len, "Macaddr = " MAC_ADDRESS_STR, - MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes)); - } - else if (strcasecmp(cmd, "scan-active") == 0) - { - pAdapter->scan_info.scan_mode = eSIR_ACTIVE_SCAN; - ret = snprintf(cmd, cmd_len, "OK"); - } - else if (strcasecmp(cmd, "scan-passive") == 0) - { - pAdapter->scan_info.scan_mode = eSIR_PASSIVE_SCAN; - ret = snprintf(cmd, cmd_len, "OK"); - } - else if( strcasecmp(cmd, "scan-mode") == 0 ) - { - ret = snprintf(cmd, cmd_len, "ScanMode = %u", pAdapter->scan_info.scan_mode); - } - else if( strcasecmp(cmd, "linkspeed") == 0 ) - { - status = iw_get_linkspeed(dev, info, wrqu, extra); - } - else if( strncasecmp(cmd, "COUNTRY", 7) == 0 ) { - char *country_code; - long lrc; - - country_code = cmd + 8; - - init_completion(&pAdapter->change_country_code); - - status = (int)sme_ChangeCountryCode(pHddCtx->hHal, - (void *)(tSmeChangeCountryCallback)wlan_hdd_change_country_code_callback, - country_code, - pAdapter, - pHddCtx->pvosContext, - eSIR_TRUE, - eSIR_TRUE); - - /* Wait for completion */ - lrc = wait_for_completion_interruptible_timeout(&pAdapter->change_country_code, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while setting country code ", - __func__, "Timed out"); - } - - if( 0 != status ) - { - VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: SME Change Country code fail \n",__func__); - return VOS_STATUS_E_FAILURE; - } - } - else if( strncasecmp(cmd, "rssi", 4) == 0 ) - { - status = iw_get_rssi(dev, info, wrqu, extra); - } - else if( strncasecmp(cmd, "powermode", 9) == 0 ) { - int mode; - char *ptr; - - if (9 < cmd_len) - { - ptr = (char*)(cmd + 9); - - }else{ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "CMD LENGTH %d is not correct",cmd_len); - return VOS_STATUS_E_FAILURE; - } - - if (1 != sscanf(ptr,"%d",&mode)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "powermode input %s is not correct",ptr); - return VOS_STATUS_E_FAILURE; - } - - if(!pHddCtx->cfg_ini->enablePowersaveOffload) - wlan_hdd_enter_bmps(pAdapter, mode); - else - wlan_hdd_set_powersave(pAdapter, mode); - } - else if (strncasecmp(cmd, "getpower", 8) == 0 ) { - v_U32_t pmc_state; - v_U16_t value; - - pmc_state = pmcGetPmcState(WLAN_HDD_GET_HAL_CTX(pAdapter)); - if(pmc_state == BMPS) { - value = DRIVER_POWER_MODE_AUTO; - } - else { - value = DRIVER_POWER_MODE_ACTIVE; - } - ret = snprintf(cmd, cmd_len, "powermode = %u", value); - } - else if( strncasecmp(cmd, "btcoexmode", 10) == 0 ) { - hddLog( VOS_TRACE_LEVEL_INFO, "btcoexmode\n"); - /*TODO: set the btcoexmode*/ - } - else if( strcasecmp(cmd, "btcoexstat") == 0 ) { - - hddLog(VOS_TRACE_LEVEL_INFO, "BtCoex Status\n"); - /*TODO: Return the btcoex status*/ - } - else if( strcasecmp(cmd, "rxfilter-start") == 0 ) { - - hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Start command\n"); - - /*TODO: Enable Rx data Filter*/ - } - else if( strcasecmp(cmd, "rxfilter-stop") == 0 ) { - - hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Stop command\n"); - - /*TODO: Disable Rx data Filter*/ - } - else if( strcasecmp(cmd, "rxfilter-statistics") == 0 ) { - - hddLog( VOS_TRACE_LEVEL_INFO, "Rx Data Filter Statistics command\n"); - /*TODO: rxfilter-statistics*/ - } - else if( strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { - - hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-add\n"); - /*TODO: rxfilter-add*/ - } - else if( strncasecmp(cmd, "rxfilter-remove",15) == 0 ) { - - hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-remove\n"); - /*TODO: rxfilter-remove*/ - } -#ifdef FEATURE_WLAN_SCAN_PNO - else if( strncasecmp(cmd, "pnosetup", 8) == 0 ) { - hddLog( VOS_TRACE_LEVEL_INFO, "pnosetup"); - /*TODO: support pnosetup*/ - } - else if( strncasecmp(cmd, "pnoforce", 8) == 0 ) { - hddLog( VOS_TRACE_LEVEL_INFO, "pnoforce"); - /*TODO: support pnoforce*/ - } - else if( strncasecmp(cmd, "pno",3) == 0 ) { - - hddLog( VOS_TRACE_LEVEL_INFO, "pno\n"); - status = iw_set_pno(dev, info, wrqu, extra, 3); - return status; - } - else if( strncasecmp(cmd, "rssifilter",10) == 0 ) { - - hddLog( VOS_TRACE_LEVEL_INFO, "rssifilter\n"); - status = iw_set_rssi_filter(dev, info, wrqu, extra, 10); - return status; - } -#endif /*FEATURE_WLAN_SCAN_PNO*/ - else if( strncasecmp(cmd, "powerparams",11) == 0 ) { - hddLog( VOS_TRACE_LEVEL_INFO, "powerparams\n"); - status = iw_set_power_params(dev, info, wrqu, extra, 11); - return status; - } - else if( 0 == strncasecmp(cmd, "CONFIG-TX-TRACKING", 18) ) { - tSirTxPerTrackingParam tTxPerTrackingParam; - char *ptr; - - if (18 < cmd_len) - { - ptr = (char*)(cmd + 18); - }else{ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "CMD LENGTH %d is not correct",cmd_len); - return VOS_STATUS_E_FAILURE; - } - - if (4 != sscanf(ptr,"%hhu %hhu %hhu %u", - &(tTxPerTrackingParam.ucTxPerTrackingEnable), - &(tTxPerTrackingParam.ucTxPerTrackingPeriod), - &(tTxPerTrackingParam.ucTxPerTrackingRatio), - &(tTxPerTrackingParam.uTxPerTrackingWatermark))) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "CONFIG-TX-TRACKING %s input is not correct",ptr); - return VOS_STATUS_E_FAILURE; - } - - // parameters checking - // period has to be larger than 0 - if (0 == tTxPerTrackingParam.ucTxPerTrackingPeriod) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Period input is not correct"); - return VOS_STATUS_E_FAILURE; - } - - // use default value 5 is the input is not reasonable. in unit of 10% - if ((tTxPerTrackingParam.ucTxPerTrackingRatio > TX_PER_TRACKING_MAX_RATIO) || (0 == tTxPerTrackingParam.ucTxPerTrackingRatio)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Ratio input is not good. use default 5"); - tTxPerTrackingParam.ucTxPerTrackingRatio = TX_PER_TRACKING_DEFAULT_RATIO; - } - - // default is 5 - if (0 == tTxPerTrackingParam.uTxPerTrackingWatermark) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx Packet number input is not good. use default 5"); - tTxPerTrackingParam.uTxPerTrackingWatermark = TX_PER_TRACKING_DEFAULT_WATERMARK; - } - - status = sme_SetTxPerTracking(pHddCtx->hHal, hdd_tx_per_hit_cb, (void*)pAdapter, &tTxPerTrackingParam); - if(status != eHAL_STATUS_SUCCESS){ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Set Tx PER Tracking Failed!"); - } - } - else { - hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", - __func__, cmd); - } -done: - /* many of the commands write information back into the command - string using snprintf(). check the return value here in one - place */ - if ((ret < 0) || (ret >= cmd_len)) - { - /* there was an encoding error or overflow */ - status = -EIO; - } - else if (ret > 0) - { - if (copy_to_user(wrqu->data.pointer, cmd, ret)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: failed to copy data to user buffer", __func__); - return -EFAULT; - } - wrqu->data.length = ret; - } - - if (ioctl_debug) - { - pr_info("%s: rsp [%s] len [%d] status %d\n", - __func__, cmd, wrqu->data.length, status); - } - return status; -} - -static int iw_set_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - ENTER(); - return 0; -} - -static int iw_get_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - ENTER(); - return 0; -} - -static struct iw_statistics *get_wireless_stats(struct net_device *dev) -{ - ENTER(); - return NULL; -} - -static int iw_set_encode(struct net_device *dev,struct iw_request_info *info, - union iwreq_data *wrqu,char *extra) - -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - struct iw_point *encoderq = &(wrqu->encoding); - v_U32_t keyId; - v_U8_t key_length; - eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; - v_BOOL_t fKeyPresent = 0; - int i; - eHalStatus status = eHAL_STATUS_SUCCESS; - - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - - keyId = encoderq->flags & IW_ENCODE_INDEX; - - if(keyId) - { - if(keyId > MAX_WEP_KEYS) - { - return -EINVAL; - } - - fKeyPresent = 1; - keyId--; - } - else - { - fKeyPresent = 0; - } - - - if(wrqu->data.flags & IW_ENCODE_DISABLED) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****iwconfig wlan0 key off*****\n"); - if(!fKeyPresent) { - - for(i=0;i < CSR_MAX_NUM_KEY; i++) { - - if(pWextState->roamProfile.Keys.KeyMaterial[i]) - pWextState->roamProfile.Keys.KeyLength[i] = 0; - } - } - pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; - pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; - pWextState->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - pWextState->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - - pHddStaCtx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE; - pHddStaCtx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE; - - if(eConnectionState_Associated == pHddStaCtx->conn_info.connState) - { - INIT_COMPLETION(pAdapter->disconnect_comp_var); - status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED ); - if(eHAL_STATUS_SUCCESS == status) - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - } - - return status; - - } - - if (wrqu->data.flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) - { - hddLog(VOS_TRACE_LEVEL_INFO, "iwconfig wlan0 key on"); - - pHddStaCtx->conn_info.authType = (encoderq->flags & IW_ENCODE_RESTRICTED) ? eCSR_AUTH_TYPE_SHARED_KEY : eCSR_AUTH_TYPE_OPEN_SYSTEM; - - } - - - if(wrqu->data.length > 0) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s : wrqu->data.length : %d",__func__,wrqu->data.length); - - key_length = wrqu->data.length; - - /* IW_ENCODING_TOKEN_MAX is the value that is set for wrqu->data.length by iwconfig.c when 'iwconfig wlan0 key on' is issued.*/ - - if(5 == key_length) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Call with WEP40,key_len=%d",__func__,key_length); - - if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) - { - encryptionType = eCSR_ENCRYPT_TYPE_WEP40; - } - else - { - encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; - } - } - else if(13 == key_length) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s:Call with WEP104,key_len:%d",__func__,key_length); - - if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) - { - encryptionType = eCSR_ENCRYPT_TYPE_WEP104; - } - else - { - encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; - } - } - else - { - hddLog(VOS_TRACE_LEVEL_WARN, "%s: Invalid WEP key length :%d", - __func__, key_length); - return -EINVAL; - } - - pHddStaCtx->conn_info.ucEncryptionType = encryptionType; - pHddStaCtx->conn_info.mcEncryptionType = encryptionType; - pWextState->roamProfile.EncryptionType.numEntries = 1; - pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType; - pWextState->roamProfile.mcEncryptionType.numEntries = 1; - pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType; - - if((eConnectionState_NotConnected == pHddStaCtx->conn_info.connState) && - ((eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) || - (eCSR_AUTH_TYPE_SHARED_KEY == pHddStaCtx->conn_info.authType))) - { - - vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[keyId][0],extra,key_length); - - pWextState->roamProfile.Keys.KeyLength[keyId] = (v_U8_t)key_length; - pWextState->roamProfile.Keys.defaultIndex = (v_U8_t)keyId; - - return status; - } - } - - return 0; -} - -static int iw_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); - int keyId; - eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; - eCsrAuthType authType = eCSR_AUTH_TYPE_NONE; - int i; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - keyId = pRoamProfile->Keys.defaultIndex; - - if(keyId < 0 || keyId >= MAX_WEP_KEYS) - { - hddLog(LOG1,"%s: Invalid keyId : %d\n",__func__,keyId); - return -EINVAL; - } - - if(pRoamProfile->Keys.KeyLength[keyId] > 0) - { - dwrq->flags |= IW_ENCODE_ENABLED; - dwrq->length = pRoamProfile->Keys.KeyLength[keyId]; - vos_mem_copy(extra, &(pRoamProfile->Keys.KeyMaterial[keyId][0]), - pRoamProfile->Keys.KeyLength[keyId]); - } - else - { - dwrq->flags |= IW_ENCODE_DISABLED; - } - - for(i=0; i < MAX_WEP_KEYS; i++) - { - if(pRoamProfile->Keys.KeyMaterial[i] == NULL) - { - continue; - } - else - { - break; - } - } - - if(MAX_WEP_KEYS == i) - { - dwrq->flags |= IW_ENCODE_NOKEY; - } - else - { - dwrq->flags |= IW_ENCODE_ENABLED; - } - - encryptionType = pRoamProfile->EncryptionType.encryptionType[0]; - - if(eCSR_ENCRYPT_TYPE_NONE == encryptionType) - { - dwrq->flags |= IW_ENCODE_DISABLED; - } - - authType = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; - - if(IW_AUTH_ALG_OPEN_SYSTEM == authType) - { - dwrq->flags |= IW_ENCODE_OPEN; - } - else - { - dwrq->flags |= IW_ENCODE_RESTRICTED; - } - EXIT(); - return 0; - -} - -static int iw_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - eHalStatus halStatus= eHAL_STATUS_SUCCESS; - - tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; - v_U32_t status = 0; - - struct iw_encode_ext *ext = (struct iw_encode_ext*)extra; - - v_U8_t groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - - int key_index; - struct iw_point *encoding = &wrqu->encoding; - tCsrRoamSetKey setKey; - v_U32_t roamId= 0xFF; - VOS_STATUS vos_status; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - key_index = encoding->flags & IW_ENCODE_INDEX; - - if(key_index > 0) { - - /*Convert from 1-based to 0-based keying*/ - key_index--; - } - if(!ext->key_len) { - - /*Set the encrytion type to NONE*/ - pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - return status; - } - - if(eConnectionState_NotConnected == pHddStaCtx->conn_info.connState && - (IW_ENCODE_ALG_WEP == ext->alg)) - { - if(IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) { - - VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,("Invalid Configuration:%s \n"),__func__); - return -EINVAL; - } - else { - /*Static wep, update the roam profile with the keys */ - if(ext->key && (ext->key_len <= eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES) && - key_index < CSR_MAX_NUM_KEY) { - vos_mem_copy(&pRoamProfile->Keys.KeyMaterial[key_index][0],ext->key,ext->key_len); - pRoamProfile->Keys.KeyLength[key_index] = (v_U8_t)ext->key_len; - - if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - pRoamProfile->Keys.defaultIndex = (v_U8_t)key_index; - - } - } - return status; - } - - vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); - - setKey.keyId = key_index; - setKey.keyLength = ext->key_len; - - if(ext->key_len <= CSR_MAX_KEY_LEN) { - vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len); - } - - if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - /*Key direction for group is RX only*/ - setKey.keyDirection = eSIR_RX_ONLY; - vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN); - } - else { - - setKey.keyDirection = eSIR_TX_RX; - vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN); - } - - /*For supplicant pae role is zero*/ - setKey.paeRole = 0; - - switch(ext->alg) - { - case IW_ENCODE_ALG_NONE: - setKey.encType = eCSR_ENCRYPT_TYPE_NONE; - break; - - case IW_ENCODE_ALG_WEP: - setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104; - break; - - case IW_ENCODE_ALG_TKIP: - { - v_U8_t *pKey = &setKey.Key[0]; - - setKey.encType = eCSR_ENCRYPT_TYPE_TKIP; - - vos_mem_zero(pKey, CSR_MAX_KEY_LEN); - - /*Supplicant sends the 32bytes key in this order - - |--------------|----------|----------| - | Tk1 |TX-MIC | RX Mic | - |--------------|----------|----------| - <---16bytes---><--8bytes--><--8bytes--> - - */ - /*Sme expects the 32 bytes key to be in the below order - - |--------------|----------|----------| - | Tk1 |RX-MIC | TX Mic | - |--------------|----------|----------| - <---16bytes---><--8bytes--><--8bytes--> - */ - /* Copy the Temporal Key 1 (TK1) */ - vos_mem_copy(pKey,ext->key,16); - - /*Copy the rx mic first*/ - vos_mem_copy(&pKey[16],&ext->key[24],8); - - /*Copy the tx mic */ - vos_mem_copy(&pKey[24],&ext->key[16],8); - - } - break; - - case IW_ENCODE_ALG_CCMP: - setKey.encType = eCSR_ENCRYPT_TYPE_AES; - break; - -#ifdef FEATURE_WLAN_CCX -#define IW_ENCODE_ALG_KRK 6 - case IW_ENCODE_ALG_KRK: - setKey.encType = eCSR_ENCRYPT_TYPE_KRK; - break; -#endif /* FEATURE_WLAN_CCX */ - - default: - setKey.encType = eCSR_ENCRYPT_TYPE_NONE; - break; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d \n"),__func__,(int)ext->alg,(int)ext->key_len,setKey.encType); - -#ifdef WLAN_FEATURE_VOWIFI_11R - /* The supplicant may attempt to set the PTK once pre-authentication - is done. Save the key in the UMAC and include it in the ADD - BSS request */ - halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey); - if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) - { - hddLog(VOS_TRACE_LEVEL_INFO_MED, - "%s: Update PreAuth Key success", __func__); - return 0; - } - else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Update PreAuth Key failed", __func__); - return -EINVAL; - } -#endif /* WLAN_FEATURE_VOWIFI_11R */ - - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - - vos_status = wlan_hdd_check_ula_done(pAdapter); - if ( vos_status != VOS_STATUS_SUCCESS ) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d", - __LINE__, vos_status ); - - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; - } - - halStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),pAdapter->sessionId, &setKey, &roamId ); - - if ( halStatus != eHAL_STATUS_SUCCESS ) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "[%4d] sme_RoamSetKey returned ERROR status= %d", - __LINE__, halStatus ); - - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; - } - - return halStatus; -} - -static int iw_set_retry(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if(wrqu->retry.value < WNI_CFG_LONG_RETRY_LIMIT_STAMIN || - wrqu->retry.value > WNI_CFG_LONG_RETRY_LIMIT_STAMAX) { - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Invalid Retry-Limit=%ld!!\n"),wrqu->retry.value); - - return -EINVAL; - } - - if(wrqu->retry.flags & IW_RETRY_LIMIT) { - - if((wrqu->retry.flags & IW_RETRY_LONG)) - { - if ( ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, wrqu->retry.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - } - else if((wrqu->retry.flags & IW_RETRY_SHORT)) - { - if ( ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, wrqu->retry.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - } - } - else - { - return -EOPNOTSUPP; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Set Retry-Limit=%ld!!\n"),wrqu->retry.value); - - EXIT(); - - return 0; - -} - -static int iw_get_retry(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - v_U32_t retry = 0; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if((wrqu->retry.flags & IW_RETRY_LONG)) - { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - - if ( ccmCfgGetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - - wrqu->retry.value = retry; - } - else if ((wrqu->retry.flags & IW_RETRY_SHORT)) - { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; - - if ( ccmCfgGetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS ) - { - return -EIO; - } - - wrqu->retry.value = retry; - } - else { - return -EOPNOTSUPP; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Retry-Limit=%ld!!\n"),retry); - - EXIT(); - - return 0; -} - -static int iw_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - struct iw_mlme *mlme = (struct iw_mlme *)extra; - eHalStatus status = eHAL_STATUS_SUCCESS; - - ENTER(); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!",__func__); - return 0; - } - - //reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED - switch (mlme->cmd) { - case IW_MLME_DISASSOC: - case IW_MLME_DEAUTH: - - if( pHddStaCtx->conn_info.connState == eConnectionState_Associated ) - { - eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED; - - if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE ) - reason = eCSR_DISCONNECT_REASON_MIC_ERROR; - - INIT_COMPLETION(pAdapter->disconnect_comp_var); - status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,reason); - - if(eHAL_STATUS_SUCCESS == status) - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - else - hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d \n", - __func__, (int)mlme->cmd, (int)status ); - - /* Resetting authKeyMgmt */ - (WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->authKeyMgmt = 0; - - netif_tx_disable(dev); - netif_carrier_off(dev); - - } - else - { - hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state \n", __func__, (int)mlme->cmd ); - } - break; - default: - hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate \n", __func__, (int)mlme->cmd ); - return -EINVAL; - }//end of switch - - EXIT(); - - return status; - -} - -#ifdef QCA_WIFI_2_0 -int process_wma_set_command(int sessid, int paramid, - int sval, int vpdev) -{ - int ret = 0; - vos_msg_t msg = {0}; - - wda_cli_set_cmd_t *iwcmd = (wda_cli_set_cmd_t *)vos_mem_malloc( - sizeof(wda_cli_set_cmd_t)); - if (NULL == iwcmd) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_mem_alloc failed", __func__); - return -EINVAL; - } - vos_mem_zero((void *)iwcmd, sizeof(wda_cli_set_cmd_t)); - iwcmd->param_value = sval; - iwcmd->param_vdev_id = sessid; - iwcmd->param_id = paramid; - iwcmd->param_vp_dev = vpdev; - msg.type = WDA_CLI_SET_CMD; - msg.reserved = 0; - msg.bodyptr = (void *)iwcmd; - if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, - &msg)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " - "Not able to post wda_cli_set_cmd message to WDA", - __func__); - vos_mem_free(iwcmd); - ret = -EIO; - } - return ret; -} -#endif - -#ifdef QCA_WIFI_2_0 -static int wlan_hdd_update_phymode(struct net_device *net, tHalHandle hal, - int new_phymode, - hdd_context_t *phddctx) -{ - v_BOOL_t band_24 = VOS_FALSE, band_5g = VOS_FALSE; - v_BOOL_t ch_bond24 = VOS_FALSE, ch_bond5g = VOS_FALSE; - tSmeConfigParams smeconfig; - tANI_U32 vhtchanwidth, chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - eCsrPhyMode phymode = -EIO, old_phymode; - eCsrBand curr_band = eCSR_BAND_ALL; - - old_phymode = sme_GetPhyMode(hal); - - if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - sme_GetCBPhyStateFromCBIniValue( - phddctx->cfg_ini->nChannelBondingMode24GHz)) - ch_bond24 = VOS_TRUE; - - if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - sme_GetCBPhyStateFromCBIniValue( - phddctx->cfg_ini->nChannelBondingMode5GHz)) - ch_bond5g = VOS_TRUE; - - if (phddctx->cfg_ini->nBandCapability == eCSR_BAND_ALL) { - band_24 = band_5g = VOS_TRUE; - } else if (phddctx->cfg_ini->nBandCapability == eCSR_BAND_24) { - band_24 = VOS_TRUE; - } else if (phddctx->cfg_ini->nBandCapability == eCSR_BAND_5G) { - band_5g = VOS_TRUE; - } - - vhtchanwidth = phddctx->cfg_ini->vhtChannelWidth; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, ("ch_bond24=%d " - "ch_bond5g=%d band_24=%d band_5g=%d VHT_ch_width=%u"), ch_bond24, - ch_bond5g, band_24, band_5g, vhtchanwidth); - switch (new_phymode) { - case IEEE80211_MODE_11A: - if (band_5g) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11a); - if ((hdd_setBand_helper(net, "SETBAND 1") == 0)) - phymode = eCSR_DOT11_MODE_11a; - else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - case IEEE80211_MODE_11B: - if (band_24) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11b); - if ((hdd_setBand_helper(net, "SETBAND 2") == 0)) - phymode = eCSR_DOT11_MODE_11b; - else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - case IEEE80211_MODE_11G: - if (band_24) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11g); - if ((hdd_setBand_helper(net, "SETBAND 2") == 0)) - phymode = eCSR_DOT11_MODE_11g; - else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - /* UMAC doesnt have option to set MODE_11NA/MODE_11NG as phymode - * so setting phymode as eCSR_DOT11_MODE_11n and updating the band - * and channel bonding in configuration to reflect MODE_11NA/MODE_11NG - */ - case IEEE80211_MODE_11NA_HT20: - if (band_5g) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); - if ((hdd_setBand_helper(net, "SETBAND 1") == 0)) { - phymode = eCSR_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = eCSR_BAND_5G; - } else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - case IEEE80211_MODE_11NA_HT40: - if (band_5g && ch_bond5g) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); - if ((hdd_setBand_helper(net, "SETBAND 1") == 0)) { - phymode = eCSR_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = eCSR_BAND_5G; - } else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - case IEEE80211_MODE_11NG_HT20: - if (band_24) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); - if ((hdd_setBand_helper(net, "SETBAND 2") == 0)) { - phymode = eCSR_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = eCSR_BAND_24; - } else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - case IEEE80211_MODE_11NG_HT40: - if (band_24 && ch_bond24) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); - if ((hdd_setBand_helper(net, "SETBAND 2") == 0)) { - phymode = eCSR_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = eCSR_BAND_24; - } else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; -#ifdef WLAN_FEATURE_11AC - case IEEE80211_MODE_11AC_VHT20: - case IEEE80211_MODE_11AC_VHT40: - if ((vhtchanwidth == eHT_CHANNEL_WIDTH_20MHZ || - vhtchanwidth == eHT_CHANNEL_WIDTH_40MHZ) && - band_5g) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11ac); - if ((hdd_setBand_helper(net, "SETBAND 1") == 0)) { - phymode = eCSR_DOT11_MODE_11ac; - } else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; - case IEEE80211_MODE_11AC_VHT80: - if ((vhtchanwidth == eHT_CHANNEL_WIDTH_80MHZ) && - band_5g) { - sme_SetPhyMode(hal, eCSR_DOT11_MODE_11ac); - if ((hdd_setBand_helper(net, "SETBAND 1") == 0)) { - phymode = eCSR_DOT11_MODE_11ac; - } else { - sme_SetPhyMode(hal, old_phymode); - return -EIO; - } - } - break; -#endif - default: - return -EIO; - } - - if (phymode != -EIO) { - sme_GetConfigParam(hal, &smeconfig); - smeconfig.csrConfig.phyMode = phymode; - if (phymode == eCSR_DOT11_MODE_11n && - chwidth == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) { - if (curr_band == eCSR_BAND_24) - smeconfig.csrConfig.channelBondingMode24GHz = - WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - else - smeconfig.csrConfig.channelBondingMode5GHz = - WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - } else if (phymode == eCSR_DOT11_MODE_11n && - chwidth == WNI_CFG_CHANNEL_BONDING_MODE_ENABLE) { - if (curr_band == eCSR_BAND_24) - smeconfig.csrConfig.channelBondingMode24GHz = - phddctx->cfg_ini->nChannelBondingMode24GHz; - else - smeconfig.csrConfig.channelBondingMode5GHz = - phddctx->cfg_ini->nChannelBondingMode5GHz; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "SET PHY MODE=%d", - smeconfig.csrConfig.phyMode); - sme_UpdateConfig(hal, &smeconfig); - } - - return 0; -} -#endif -/* set param sub-ioctls */ -static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - tSmeConfigParams smeConfig; - int *value = (int *)extra; - int sub_cmd = value[0]; - int set_value = value[1]; - int ret = 0; /* success */ - int enable_pbm, enable_mp; - -#ifdef CONFIG_HAS_EARLYSUSPEND - v_U8_t nEnableSuspendOld; -#endif - INIT_COMPLETION(pWextState->completion_var); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - switch(sub_cmd) - { - case WE_SET_11D_STATE: - { - if((ENABLE_11D == set_value) || (DISABLE_11D == set_value)) { - - memset(&smeConfig, 0x00, sizeof(smeConfig)); - sme_GetConfigParam(hHal, &smeConfig); - smeConfig.csrConfig.Is11dSupportEnabled = (v_BOOL_t)set_value; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("11D state=%ld!!\n"), - smeConfig.csrConfig.Is11dSupportEnabled); - - sme_UpdateConfig(hHal, &smeConfig); - } - else { - return -EINVAL; - } - break; - } - - case WE_WOWL: - { - switch (set_value) - { - case 0x00: - hdd_exit_wowl(pAdapter); - break; - case 0x01: - case 0x02: - case 0x03: - enable_mp = (set_value & 0x01) ? 1 : 0; - enable_pbm = (set_value & 0x02) ? 1 : 0; - hddLog(LOGE, "magic packet ? = %s pattern byte matching ? = %s\n", - (enable_mp ? "YES":"NO"), (enable_pbm ? "YES":"NO")); - hdd_enter_wowl(pAdapter, enable_mp, enable_pbm); - break; - default: - hddLog(LOGE, "Invalid arg %d in WE_WOWL IOCTL\n", set_value); - ret = -EINVAL; - break; - } - - break; - } - case WE_SET_POWER: - { - switch (set_value) - { - case 0: //Full Power - { - struct statsContext context; - eHalStatus status; - - init_completion(&context.completion); - - context.pAdapter = pAdapter; - context.magic = POWER_CONTEXT_MAGIC; - - status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context, - eSME_FULL_PWR_NEEDED_BY_HDD); - if(eHAL_STATUS_PMC_PENDING == status) - { - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while " - "requesting fullpower ", - __func__, (0 == lrc) ? - "timeout" : "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - hddLog(LOGE, "iwpriv Full Power completed\n"); - break; - } - case 1: //Enable BMPS - sme_EnablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE); - break; - case 2: //Disable BMPS - sme_DisablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE); - break; - case 3: //Request Bmps - { - struct statsContext context; - eHalStatus status; - - init_completion(&context.completion); - - context.pAdapter = pAdapter; - context.magic = POWER_CONTEXT_MAGIC; - - status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context); - if(eHAL_STATUS_PMC_PENDING == status) - { - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - context.magic = 0; - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while " - "requesting BMPS", - __func__, (0 == lrc) ? "timeout" : - "interrupt"); - /* there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but hasn't yet set the completion - variable. Since the completion variable is on our - stack, we'll delay just a bit to make sure the data is - still valid if that is the case */ - msleep(50); - /* we'll now returned a cached value below */ - } - } - hddLog(LOGE, "iwpriv Request BMPS completed\n"); - break; - } - case 4: //Enable IMPS - sme_EnablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE); - break; - case 5: //Disable IMPS - sme_DisablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE); - break; - case 6: //Enable Standby - sme_EnablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE); - break; - case 7: //Disable Standby - sme_DisablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE); - break; - case 8: //Request Standby -#ifdef CONFIG_HAS_EARLYSUSPEND -#endif - break; - case 9: //Start Auto Bmps Timer - sme_StartAutoBmpsTimer(hHal); - break; - case 10://Stop Auto BMPS Timer - sme_StopAutoBmpsTimer(hHal); - break; -#ifdef CONFIG_HAS_EARLYSUSPEND - case 11://suspend to standby -#ifdef CONFIG_HAS_EARLYSUSPEND - nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend; - (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 1; - (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld; -#endif - break; - case 12://suspend to deep sleep -#ifdef CONFIG_HAS_EARLYSUSPEND - nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend; - (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 2; - (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld; -#endif - break; - case 13://resume from suspend -#ifdef CONFIG_HAS_EARLYSUSPEND -#endif - break; -#endif - case 14://reset wlan (power down/power up) - vos_chipReset(NULL, VOS_FALSE, NULL, NULL, VOS_CHIP_RESET_UNKNOWN_EXCEPTION); - break; - default: - hddLog(LOGE, "Invalid arg %d in WE_SET_POWER IOCTL\n", set_value); - ret = -EINVAL; - break; - } - break; - } - - case WE_SET_MAX_ASSOC: - { - if ((WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) || - (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value)) - { - ret = -EINVAL; - } - else if ( ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, - set_value, NULL, eANI_BOOLEAN_FALSE) - != eHAL_STATUS_SUCCESS ) - { - ret = -EIO; - } - break; - } - - case WE_SET_SAP_AUTO_CHANNEL_SELECTION: - { - if( 0 == set_value ) - { - (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection = 0; - } - else if ( 1 == set_value ) - { - (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection = 1; - } - else - { - hddLog(LOGE, "Invalid arg %d in WE_SET_SAP_AUTO_CHANNEL_SELECTION IOCTL\n", set_value); - ret = -EINVAL; - } - break; - } - - case WE_SET_DATA_INACTIVITY_TO: - { - if ((set_value < CFG_DATA_INACTIVITY_TIMEOUT_MIN) || - (set_value > CFG_DATA_INACTIVITY_TIMEOUT_MAX) || - (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal, - WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, - set_value, - NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)) - { - hddLog(LOGE,"Failure: Could not pass on " - "WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT configuration info " - "to CCM\n"); - ret = -EINVAL; - } - break; - } - case WE_SET_MAX_TX_POWER: - { - tSirMacAddr bssid; - tSirMacAddr selfMac; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm", - __func__, set_value); - vos_mem_copy(bssid, pAdapter->macAddressCurrent.bytes, - VOS_MAC_ADDR_SIZE); - vos_mem_copy(selfMac, pAdapter->macAddressCurrent.bytes, - VOS_MAC_ADDR_SIZE); - - if( sme_SetMaxTxPower(hHal, bssid, selfMac, set_value) != - eHAL_STATUS_SUCCESS ) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", - __func__); - return -EIO; - } - - break; - } - case WE_SET_MAX_TX_POWER_2_4: - { - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: Setting maximum tx power %d dBm for 2.4 GHz band", - __func__, set_value); - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, set_value) != - eHAL_STATUS_SUCCESS) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Setting maximum tx power failed for 2.4 GHz band", - __func__); - return -EIO; - } - - break; - } - case WE_SET_MAX_TX_POWER_5_0: - { - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: Setting maximum tx power %d dBm for 5.0 GHz band", - __func__, set_value); - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, set_value) != - eHAL_STATUS_SUCCESS) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Setting maximum tx power failed for 5.0 GHz band", - __func__); - return -EIO; - } - - break; - } - case WE_SET_HIGHER_DTIM_TRANSITION: - { - if(!((set_value == eANI_BOOLEAN_FALSE) || - (set_value == eANI_BOOLEAN_TRUE))) - { - hddLog(LOGE, "Dynamic DTIM Incorrect data:%d", set_value); - ret = -EINVAL; - } - else - { - if(pAdapter->higherDtimTransition != set_value) - { - pAdapter->higherDtimTransition = set_value; - hddLog(LOG1, "%s: higherDtimTransition set to :%d", __func__, pAdapter->higherDtimTransition); - } - } - - break; - } - - case WE_SET_TM_LEVEL: - { -#ifdef QCA_WIFI_ISOC - hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter); - hddLog(VOS_TRACE_LEVEL_INFO, "Set Thermal Mitigation Level %d", (int)set_value); - hddDevTmLevelChangedHandler(hddCtxt->parent_dev, set_value); -#else - hddLog(VOS_TRACE_LEVEL_INFO, "Thermal Mitigation Level %d not set for discrete", - (int)set_value); -#endif - break; - } - - case WE_ENABLE_STRICT_FCC_REG: - { - hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter); - struct wiphy *wiphy = NULL; - long lrc; - int status; - - wiphy = hddCtxt->wiphy; - if(wiphy == NULL) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy is NULL ", __func__); - break; - } - init_completion(&hddCtxt->wiphy_channel_update_event); - - hddCtxt->nEnableStrictRegulatoryForFCC = set_value; - - status = regulatory_hint(wiphy, "00"); - if(status < 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failure in setting regulatory rule ", __func__); - break; - } - - /* Wait for completion */ - lrc = wait_for_completion_interruptible_timeout(&hddCtxt->wiphy_channel_update_event, - msecs_to_jiffies(WLAN_WAIT_TIME_CHANNEL_UPDATE)); - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while setting strict FCC regulatory rule ", - __func__, (0 == lrc) ? "Timeout" : "Interrupt"); - return (0 == lrc) ? -ETIMEDOUT : -EINTR; - } - hddLog(VOS_TRACE_LEVEL_INFO,"%s: SUCCESS in setting strict FCC regulatory rule", __func__); - - break; - } -#ifdef QCA_WIFI_2_0 - case WE_SET_PHYMODE: - { - hdd_context_t *phddctx = WLAN_HDD_GET_CTX(pAdapter); - - ret = wlan_hdd_update_phymode(dev, hHal, set_value, phddctx); - break; - } - - case WE_SET_NSS: - { - hddLog(LOG1, "WMI_VDEV_PARAM_NSS val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_NSS, - set_value, VDEV_CMD); - break; - } - - case WE_SET_LDPC: - { - tANI_U32 value; - union { - tANI_U16 nCfgValue16; - tSirMacHTCapabilityInfo htCapInfo; - }uHTCapabilityInfo; - - hddLog(LOG1, "LDPC val %d", set_value); - /* get the HT capability info*/ - ret = ccmCfgGetInt(hHal, WNI_CFG_HT_CAP_INFO, &value); - if (eHAL_STATUS_SUCCESS != ret) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: could not get HT capability info", - __func__); - return -EIO; - } - - uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; - if ((set_value && (uHTCapabilityInfo.htCapInfo.advCodingCap)) || - (!set_value)) { - ret = sme_UpdateHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_ADVANCE_CODING, - set_value); - } - - if (ret) - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Failed to set LDPC value"); - - break; - } - - case WE_SET_TX_STBC: - { - tANI_U32 value; - union { - tANI_U16 nCfgValue16; - tSirMacHTCapabilityInfo htCapInfo; - }uHTCapabilityInfo; - - hddLog(LOG1, "TX_STBC val %d", set_value); - /* get the HT capability info*/ - ret = ccmCfgGetInt(hHal, WNI_CFG_HT_CAP_INFO, &value); - if (eHAL_STATUS_SUCCESS != ret) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: could not get HT capability info", - __func__); - return -EIO; - } - - uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; - if ((set_value && (uHTCapabilityInfo.htCapInfo.txSTBC)) || - (!set_value)) { - ret = sme_UpdateHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_TX_STBC, - set_value); - } - - if (ret) - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Failed to set TX STBC value"); - - break; - } - - case WE_SET_RX_STBC: - { - tANI_U32 value; - union { - tANI_U16 nCfgValue16; - tSirMacHTCapabilityInfo htCapInfo; - }uHTCapabilityInfo; - - hddLog(LOG1, "WMI_VDEV_PARAM_RX_STBC val %d", set_value); - /* get the HT capability info*/ - ret = ccmCfgGetInt(hHal, WNI_CFG_HT_CAP_INFO, &value); - if (eHAL_STATUS_SUCCESS != ret) { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: could not get HT capability info", - __func__); - return -EIO; - } - - uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; - if ((set_value && (uHTCapabilityInfo.htCapInfo.rxSTBC)) || - (!set_value)) { - ret = sme_UpdateHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_RX_STBC, - (!set_value)? set_value : - uHTCapabilityInfo.htCapInfo.rxSTBC); - } - - if (ret) - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Failed to set RX STBC value"); - break; - } - - case WE_SET_SHORT_GI: - { - hddLog(LOG1, "WMI_VDEV_PARAM_SGI val %d", set_value); - ret = sme_UpdateHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ, - set_value); - if (ret) - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Failed to set ShortGI value"); - break; - } - - case WE_SET_RTSCTS: - { - u_int32_t value; - - hddLog(LOG1, "WMI_VDEV_PARAM_ENABLE_RTSCTS val %d", set_value); - if (set_value == 1) - value = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->RTSThreshold; - else if (set_value == 0) - value = WNI_CFG_RTS_THRESHOLD_STAMAX; - else - return -EIO; - - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, - set_value, VDEV_CMD); - if (!ret) { - if (ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, value, - ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != - eHAL_STATUS_SUCCESS) { - hddLog(LOGE, "FAILED TO SET RTSCTS"); - return -EIO; - } - } - - break; - } - - case WE_SET_CHWIDTH: - { - bool chwidth; - hdd_context_t *phddctx = WLAN_HDD_GET_CTX(pAdapter); - /*updating channel bonding only on 5Ghz*/ - hddLog(LOG1, "WMI_VDEV_PARAM_CHWIDTH val %d", set_value); - if (set_value > eHT_CHANNEL_WIDTH_80MHZ) { - hddLog(LOGE, "Invalid channel width 0->20 1->40 2->80"); - return -EINVAL; - } - - if ((WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - csrConvertCBIniValueToPhyCBState( - phddctx->cfg_ini->nChannelBondingMode5GHz))) - chwidth = true; - - memset(&smeConfig, 0x00, sizeof(smeConfig)); - sme_GetConfigParam(hHal, &smeConfig); - switch (set_value) { - case eHT_CHANNEL_WIDTH_20MHZ: - smeConfig.csrConfig.channelBondingMode5GHz = - WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - break; - case eHT_CHANNEL_WIDTH_40MHZ: - if (chwidth) - smeConfig.csrConfig.channelBondingMode5GHz = - phddctx->cfg_ini->nChannelBondingMode5GHz; - else - return -EINVAL; - - break; -#ifdef WLAN_FEATURE_11AC - case eHT_CHANNEL_WIDTH_80MHZ: - if (chwidth) - smeConfig.csrConfig.channelBondingMode5GHz = - phddctx->cfg_ini->nChannelBondingMode5GHz; - else - return -EINVAL; - - break; -#endif - - default: - return -EINVAL; - } - - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_CHWIDTH, - set_value, VDEV_CMD); - if (!ret) - sme_UpdateConfig(hHal, &smeConfig); - - break; - } - - case WE_SET_ANI_EN_DIS: - { - hddLog(LOG1, "WMI_PDEV_PARAM_ANI_ENABLE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_ENABLE, - set_value, PDEV_CMD); - break; - } - - case WE_SET_ANI_POLL_PERIOD: - { - hddLog(LOG1, "WMI_PDEV_PARAM_ANI_POLL_PERIOD val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_POLL_PERIOD, - set_value, PDEV_CMD); - break; - } - - case WE_SET_ANI_LISTEN_PERIOD: - { - hddLog(LOG1, "WMI_PDEV_PARAM_ANI_LISTEN_PERIOD val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, - set_value, PDEV_CMD); - break; - } - - case WE_SET_ANI_OFDM_LEVEL: - { - hddLog(LOG1, "WMI_PDEV_PARAM_ANI_OFDM_LEVEL val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_OFDM_LEVEL, - set_value, PDEV_CMD); - break; - } - - case WE_SET_ANI_CCK_LEVEL: - { - hddLog(LOG1, "WMI_PDEV_PARAM_ANI_CCK_LEVEL val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_CCK_LEVEL, - set_value, PDEV_CMD); - break; - } - - case WE_SET_DYNAMIC_BW: - { - hddLog(LOG1, "WMI_PDEV_PARAM_DYNAMIC_BW val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_DYNAMIC_BW, - set_value, PDEV_CMD); - break; - } - - case WE_SET_11N_RATE: - { - u_int8_t preamble, nss, rix; - hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d", set_value); - - rix = RC_2_RATE_IDX(set_value); - if (set_value & 0x80) { - preamble = WMI_RATE_PREAMBLE_HT; - nss = HT_RC_2_STREAMS(set_value) -1; - } else { - nss = 0; - rix = RC_2_RATE_IDX(set_value); - if (set_value & 0x10) { - preamble = WMI_RATE_PREAMBLE_CCK; - rix |= 0x4; /* Enable Short preamble always for CCK */ - } else - preamble = WMI_RATE_PREAMBLE_OFDM; - } - - hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d rix %d preamble %x\ - nss %d", set_value, rix, preamble, nss); - - set_value = (preamble << 6) | (nss << 4) | rix; - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_FIXED_RATE, - set_value, VDEV_CMD); - break; - } - - case WE_SET_VHT_RATE: - { - u_int8_t preamble, nss, rix; - - rix = RC_2_RATE_IDX_11AC(set_value); - preamble = WMI_RATE_PREAMBLE_VHT; - nss = HT_RC_2_STREAMS_11AC(set_value) -1; - - hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d rix %d preamble %x\ - nss %d", set_value, rix, preamble, nss); - - set_value = (preamble << 6) | (nss << 4) | rix; - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_FIXED_RATE, - set_value, VDEV_CMD); - break; - } - - case WE_SET_AMPDU: - { - hddLog(LOG1, "SET AMPDU val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_VDEV_PARAM_AMPDU, - set_value, GEN_CMD); - break; - } - - case WE_SET_AMSDU: - { - hddLog(LOG1, "SET AMSDU val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_VDEV_PARAM_AMSDU, - set_value, GEN_CMD); - break; - } - - case WE_SET_TX_CHAINMASK: - { - hddLog(LOG1, "WMI_PDEV_PARAM_TX_CHAIN_MASK val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, - set_value, PDEV_CMD); - break; - } - - case WE_SET_RX_CHAINMASK: - { - hddLog(LOG1, "WMI_PDEV_PARAM_RX_CHAIN_MASK val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, - set_value, PDEV_CMD); - break; - } - - case WE_SET_TXPOW_2G: - { - hddLog(LOG1, "WMI_PDEV_PARAM_TXPOWER_LIMIT2G val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_TXPOWER_LIMIT2G, - set_value, PDEV_CMD); - break; - } - - case WE_SET_TXPOW_5G: - { - hddLog(LOG1, "WMI_PDEV_PARAM_TXPOWER_LIMIT5G val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_TXPOWER_LIMIT5G, - set_value, PDEV_CMD); - break; - } - - case WE_SET_POWER_GATING: - { - hddLog(LOG1, "WMI_PDEV_PARAM_POWER_GATING_SLEEP val %d", - set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_POWER_GATING_SLEEP, - (set_value)? true:false, PDEV_CMD); - break; - } - - /* Firmware debug log */ - case WE_DBGLOG_LOG_LEVEL: - { - hddLog(LOG1, "WE_DBGLOG_LOG_LEVEL val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_LOG_LEVEL, - set_value, DBG_CMD); - break; - } - - case WE_DBGLOG_VAP_ENABLE: - { - hddLog(LOG1, "WE_DBGLOG_VAP_ENABLE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_VAP_ENABLE, - set_value, DBG_CMD); - break; - } - - case WE_DBGLOG_VAP_DISABLE: - { - hddLog(LOG1, "WE_DBGLOG_VAP_DISABLE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_VAP_DISABLE, - set_value, DBG_CMD); - break; - } - - case WE_DBGLOG_MODULE_ENABLE: - { - hddLog(LOG1, "WE_DBGLOG_MODULE_ENABLE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_MODULE_ENABLE, - set_value, DBG_CMD); - break; - } - - case WE_DBGLOG_MODULE_DISABLE: - { - hddLog(LOG1, "WE_DBGLOG_MODULE_DISABLE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_MODULE_DISABLE, - set_value, DBG_CMD); - break; - } - - case WE_DBGLOG_MOD_LOG_LEVEL: - { - hddLog(LOG1, "WE_DBGLOG_MOD_LOG_LEVEL val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_MOD_LOG_LEVEL, - set_value, DBG_CMD); - break; - } - - case WE_DBGLOG_TYPE: - { - hddLog(LOG1, "WE_DBGLOG_TYPE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_TYPE, - set_value, DBG_CMD); - break; - } - case WE_DBGLOG_REPORT_ENABLE: - { - hddLog(LOG1, "WE_DBGLOG_REPORT_ENABLE val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_DBGLOG_REPORT_ENABLE, - set_value, DBG_CMD); - break; - } - - case WE_SET_TXRX_FWSTATS: - { - hddLog(LOG1, "WE_SET_TXRX_FWSTATS val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID, - set_value, VDEV_CMD); - break; - } - - case WE_TXRX_FWSTATS_RESET: - { - hddLog(LOG1, "WE_TXRX_FWSTATS_RESET val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMA_VDEV_TXRX_FWSTATS_RESET_CMDID, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_PAID_MATCH: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - - hddLog(LOG1, "WMI_VDEV_PPS_PAID_MATCH val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_PAID_MATCH, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_GID_MATCH: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_GID_MATCH val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_GID_MATCH, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_EARLY_TIM_CLEAR: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, " WMI_VDEV_PPS_EARLY_TIM_CLEAR val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_EARLY_DTIM_CLEAR: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_EARLY_DTIM_CLEAR val %d", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_EOF_PAD_DELIM: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_EOF_PAD_DELIM val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EOF_PAD_DELIM, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_MACADDR_MISMATCH: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_MACADDR_MISMATCH val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_MACADDR_MISMATCH, - set_value, VDEV_CMD); - break; - } - - case WE_PPS_DELIM_CRC_FAIL: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_DELIM_CRC_FAIL val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, - set_value, VDEV_CMD); - break; - } - - - case WE_PPS_GID_NSTS_ZERO: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_GID_NSTS_ZERO val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_GID_NSTS_ZERO, - set_value, VDEV_CMD); - break; - } - - - case WE_PPS_RSSI_CHECK: - { - if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) - return EINVAL; - hddLog(LOG1, "WMI_VDEV_PPS_RSSI_CHECK val %d ", set_value); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_RSSI_CHECK, - set_value, VDEV_CMD); - break; - } - -#endif - default: - { - hddLog(LOGE, "%s: Invalid sub command %d", __func__, sub_cmd); - ret = -EINVAL; - break; - } - } - return ret; -} - -/* set param sub-ioctls */ -static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - VOS_STATUS vstatus; - int sub_cmd = wrqu->data.flags; - int ret = 0; /* success */ - hdd_adapter_t *pAdapter = (netdev_priv(dev)); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); -#ifdef WLAN_FEATURE_VOWIFI - hdd_config_t *pConfig = pHddCtx->cfg_ini; -#endif /* WLAN_FEATURE_VOWIFI */ - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received length %d", __func__, wrqu->data.length); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received data %s", __func__, extra); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - switch(sub_cmd) - { - case WE_WOWL_ADD_PTRN: - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "ADD_PTRN\n"); - hdd_add_wowl_ptrn(pAdapter, extra); - break; - case WE_WOWL_DEL_PTRN: - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN\n"); - hdd_del_wowl_ptrn(pAdapter, extra); - break; -#if defined WLAN_FEATURE_VOWIFI - case WE_NEIGHBOR_REPORT_REQUEST: - { - tRrmNeighborReq neighborReq; - tRrmNeighborRspCallbackInfo callbackInfo; - - if (pConfig->fRrmEnable) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Neighbor Request\n"); - neighborReq.no_ssid = (wrqu->data.length - 1) ? false : true ; - if( !neighborReq.no_ssid ) - { - neighborReq.ssid.length = (wrqu->data.length - 1) > 32 ? 32 : (wrqu->data.length - 1) ; - vos_mem_copy( neighborReq.ssid.ssId, extra, neighborReq.ssid.length ); - } - - callbackInfo.neighborRspCallback = NULL; - callbackInfo.neighborRspCallbackContext = NULL; - callbackInfo.timeout = 5000; //5 seconds - sme_NeighborReportRequest( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &neighborReq, &callbackInfo ); - } - else - { - hddLog(LOGE, "%s: Ignoring neighbor request as RRM is not enabled\n", __func__); - ret = -EINVAL; - } - } - break; -#endif - case WE_SET_AP_WPS_IE: - hddLog( LOGE, "Received WE_SET_AP_WPS_IE" ); - sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), extra, wrqu->data.length ); - break; - case WE_SET_CONFIG: - vstatus = hdd_execute_config_command(pHddCtx, extra); - if (VOS_STATUS_SUCCESS != vstatus) - { - ret = -EINVAL; - } - break; - default: - { - hddLog(LOGE, "%s: Invalid sub command %d", __func__, sub_cmd); - ret = -EINVAL; - break; - } - } - return ret; -} - -/* get param sub-ioctls */ -static int iw_setnone_getint(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - int *value = (int *)extra; - int ret = 0; /* success */ -#ifdef QCA_WIFI_2_0 - hdd_context_t *wmahddCtxt = WLAN_HDD_GET_CTX(pAdapter); - void *wmapvosContext = wmahddCtxt->pvosContext; -#endif - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - switch (value[0]) - { - case WE_GET_11D_STATE: - { - tSmeConfigParams smeConfig; - sme_GetConfigParam(hHal,&smeConfig); - - *value = smeConfig.csrConfig.Is11dSupportEnabled; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("11D state=%ld!!\n"),*value); - - break; - } - - case WE_IBSS_STATUS: - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****Return IBSS Status*****\n"); - break; - - case WE_PMC_STATE: - { - *value = pmcGetPmcState(hHal); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("PMC state=%ld!!\n"),*value); - break; - } - case WE_GET_WLAN_DBG: - { - vos_trace_display(); - *value = 0; - break; - } - case WE_MODULE_DOWN_IND: - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: sending WLAN_MODULE_DOWN_IND", __func__); - send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); -#ifdef WLAN_BTAMP_FEATURE - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: Take down AMP PAL", __func__); - BSL_Deinit(vos_get_global_context(VOS_MODULE_ID_HDD, NULL)); -#endif - //WLANBAP_Close(vos_get_global_context(VOS_MODULE_ID_HDD, NULL)); - - *value = 0; - break; - } - case WE_GET_MAX_ASSOC: - { - if (ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value) != eHAL_STATUS_SUCCESS) - { - ret = -EIO; - } - break; - } - - case WE_GET_WDI_DBG: - { - wpalTraceDisplay(); - *value = 0; - break; - } - - case WE_GET_SAP_AUTO_CHANNEL_SELECTION: - { - *value = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection; - break; - } - case WE_GET_CONCURRENCY_MODE: - { - *value = hdd_get_concurrency_mode ( ); - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("concurrency mode=%d \n"),*value); - break; - } - -#ifdef QCA_WIFI_2_0 - case WE_GET_NSS: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_NSS"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_NSS, - VDEV_CMD); - break; - } - - case WE_GET_LDPC: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_LDPC"); - *value = sme_GetHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_ADVANCE_CODING); - break; - } - - case WE_GET_TX_STBC: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_TX_STBC"); - *value = sme_GetHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_TX_STBC); - break; - } - - case WE_GET_RX_STBC: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_RX_STBC"); - *value = sme_GetHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_RX_STBC); - break; - } - - case WE_GET_SHORT_GI: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_SGI"); - *value = sme_GetHTConfig(hHal, pAdapter->sessionId, - WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ); - break; - } - - case WE_GET_RTSCTS: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_ENABLE_RTSCTS"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, - VDEV_CMD); - break; - } - - case WE_GET_CHWIDTH: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_CHWIDTH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_CHWIDTH, - VDEV_CMD); - break; - } - - case WE_GET_ANI_EN_DIS: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_ENABLE"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_ENABLE, - PDEV_CMD); - break; - } - - case WE_GET_ANI_POLL_PERIOD: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_POLL_PERIOD"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_POLL_PERIOD, - PDEV_CMD); - break; - } - - case WE_GET_ANI_LISTEN_PERIOD: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_LISTEN_PERIOD"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, - PDEV_CMD); - break; - } - - case WE_GET_ANI_OFDM_LEVEL: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_OFDM_LEVEL"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_OFDM_LEVEL, - PDEV_CMD); - break; - } - - case WE_GET_ANI_CCK_LEVEL: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_CCK_LEVEL"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_ANI_CCK_LEVEL, - PDEV_CMD); - break; - } - - case WE_GET_DYNAMIC_BW: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_CCK_LEVEL"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_DYNAMIC_BW, - PDEV_CMD); - break; - } - - case WE_GET_11N_RATE: - { - hddLog(LOG1, "GET WMI_VDEV_PARAM_FIXED_RATE"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PARAM_FIXED_RATE, - VDEV_CMD); - break; - } - - case WE_GET_AMPDU: - { - hddLog(LOG1, "GET AMPDU"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)GEN_VDEV_PARAM_AMPDU, - GEN_CMD); - break; - } - - case WE_GET_AMSDU: - { - hddLog(LOG1, "GET AMSDU"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)GEN_VDEV_PARAM_AMSDU, - GEN_CMD); - break; - } - - case WE_GET_TX_CHAINMASK: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_TX_CHAIN_MASK"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, - PDEV_CMD); - break; - } - - case WE_GET_RX_CHAINMASK: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_RX_CHAIN_MASK"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, - PDEV_CMD); - break; - } - - case WE_GET_TXPOW_2G: - { - tANI_U32 txpow2g = 0; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hddLog(LOG1, "GET WMI_PDEV_PARAM_TXPOWER_LIMIT2G"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_TXPOWER_LIMIT2G, - PDEV_CMD); - if ( eHAL_STATUS_SUCCESS != ccmCfgGetInt(hHal, - WNI_CFG_CURRENT_TX_POWER_LEVEL, &txpow2g) ) - { - return -EIO; - } - hddLog(LOG1, "2G tx_power %d", txpow2g); - break; - } - - case WE_GET_TXPOW_5G: - { - tANI_U32 txpow5g = 0; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hddLog(LOG1, "GET WMI_PDEV_PARAM_TXPOWER_LIMIT5G"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_TXPOWER_LIMIT5G, - PDEV_CMD); - if ( eHAL_STATUS_SUCCESS != ccmCfgGetInt(hHal, - WNI_CFG_CURRENT_TX_POWER_LEVEL, &txpow5g) ) - { - return -EIO; - } - hddLog(LOG1, "5G tx_power %d", txpow5g); - break; - } - - case WE_GET_POWER_GATING: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_POWER_GATING_SLEEP"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_PDEV_PARAM_POWER_GATING_SLEEP, - PDEV_CMD); - break; - } - -#endif - - default: - { - hddLog(LOGE, "Invalid IOCTL get_value command %d", value[0]); - break; - } - } - - return ret; -} - -/* set param sub-ioctls */ -int iw_set_three_ints_getnone(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int *value = (int *)extra; - int sub_cmd = value[0]; - int ret = 0; - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - switch(sub_cmd) - { - case WE_SET_WLAN_DBG: - { - vos_trace_setValue( value[1], value[2], value[3]); - break; - } - case WE_SET_WDI_DBG: - { - wpalTraceSetLevel( value[1], value[2], value[3]); - break; - } - case WE_SET_SAP_CHANNELS: - { - ret = iw_softap_set_channel_range( dev, value[1], value[2], value[3]); - break; - } - - - default: - { - hddLog(LOGE, "Invalid IOCTL command %d", sub_cmd); - break; - } - } - return ret; -} - -static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int sub_cmd = wrqu->data.flags; -#ifdef WLAN_FEATURE_11W - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); -#endif - - if (NULL == WLAN_HDD_GET_CTX(pAdapter)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: HDD Context is NULL!", __func__); - - return -EINVAL; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - switch(sub_cmd) - { - case WE_WLAN_VERSION: - { - hdd_wlan_get_version(pAdapter, wrqu, extra); - break; - } - - case WE_GET_STATS: - { - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats; - hdd_chip_reset_stats_t *pResetStats = &pHddCtx->hddChipResetStats; - - snprintf(extra, WE_MAX_STR_LEN, - "\nTransmit" - "\ncalled %u, dropped %u, backpressured %u, queued %u" - "\n dropped BK %u, BE %u, VI %u, VO %u" - "\n classified BK %u, BE %u, VI %u, VO %u" - "\nbackpressured BK %u, BE %u, VI %u, VO %u" - "\n queued BK %u, BE %u, VI %u, VO %u" - "\nfetched %u, empty %u, lowres %u, deqerr %u" - "\ndequeued %u, depressured %u, completed %u, flushed %u" - "\n fetched BK %u, BE %u, VI %u, VO %u" - "\n dequeued BK %u, BE %u, VI %u, VO %u" - "\n depressured BK %u, BE %u, VI %u, VO %u" - "\n flushed BK %u, BE %u, VI %u, VO %u" - "\n\nReceive" - "\nchains %u, packets %u, dropped %u, delivered %u, refused %u" - "\n\nResetsStats" - "\n TotalLogp %u Cmd53 %u MutexRead %u MIF-Error %u FW-Heartbeat %u Others %u" - "\n", - pStats->txXmitCalled, - pStats->txXmitDropped, - pStats->txXmitBackPressured, - pStats->txXmitQueued, - - pStats->txXmitDroppedAC[WLANTL_AC_BK], - pStats->txXmitDroppedAC[WLANTL_AC_BE], - pStats->txXmitDroppedAC[WLANTL_AC_VI], - pStats->txXmitDroppedAC[WLANTL_AC_VO], - - pStats->txXmitClassifiedAC[WLANTL_AC_BK], - pStats->txXmitClassifiedAC[WLANTL_AC_BE], - pStats->txXmitClassifiedAC[WLANTL_AC_VI], - pStats->txXmitClassifiedAC[WLANTL_AC_VO], - - pStats->txXmitBackPressuredAC[WLANTL_AC_BK], - pStats->txXmitBackPressuredAC[WLANTL_AC_BE], - pStats->txXmitBackPressuredAC[WLANTL_AC_VI], - pStats->txXmitBackPressuredAC[WLANTL_AC_VO], - - pStats->txXmitQueuedAC[WLANTL_AC_BK], - pStats->txXmitQueuedAC[WLANTL_AC_BE], - pStats->txXmitQueuedAC[WLANTL_AC_VI], - pStats->txXmitQueuedAC[WLANTL_AC_VO], - - pStats->txFetched, - pStats->txFetchEmpty, - pStats->txFetchLowResources, - pStats->txFetchDequeueError, - - pStats->txFetchDequeued, - pStats->txFetchDePressured, - pStats->txCompleted, - pStats->txFlushed, - - pStats->txFetchedAC[WLANTL_AC_BK], - pStats->txFetchedAC[WLANTL_AC_BE], - pStats->txFetchedAC[WLANTL_AC_VI], - pStats->txFetchedAC[WLANTL_AC_VO], - - pStats->txFetchDequeuedAC[WLANTL_AC_BK], - pStats->txFetchDequeuedAC[WLANTL_AC_BE], - pStats->txFetchDequeuedAC[WLANTL_AC_VI], - pStats->txFetchDequeuedAC[WLANTL_AC_VO], - - pStats->txFetchDePressuredAC[WLANTL_AC_BK], - pStats->txFetchDePressuredAC[WLANTL_AC_BE], - pStats->txFetchDePressuredAC[WLANTL_AC_VI], - pStats->txFetchDePressuredAC[WLANTL_AC_VO], - - pStats->txFlushedAC[WLANTL_AC_BK], - pStats->txFlushedAC[WLANTL_AC_BE], - pStats->txFlushedAC[WLANTL_AC_VI], - pStats->txFlushedAC[WLANTL_AC_VO], - - pStats->rxChains, - pStats->rxPackets, - pStats->rxDropped, - pStats->rxDelivered, - pStats->rxRefused, - - pResetStats->totalLogpResets, - pResetStats->totalCMD53Failures, - pResetStats->totalMutexReadFailures, - pResetStats->totalMIFErrorFailures, - pResetStats->totalFWHearbeatFailures, - pResetStats->totalUnknownExceptions - ); - wrqu->data.length = strlen(extra)+1; - break; - } - -/* The case prints the current state of the HDD, SME, CSR, PE, TL - *it can be extended for WDI Global State as well. - *And currently it only checks P2P_CLIENT adapter. - *P2P_DEVICE and P2P_GO have not been added as of now. -*/ - case WE_GET_STATES: - { - int buf = 0, len = 0; - int adapter_num = 0; - int count = 0, check = 1; - - tANI_U16 tlState; - tHalHandle hHal; - tpAniSirGlobal pMac; - hdd_station_ctx_t *pHddStaCtx; - - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); - hdd_adapter_t *useAdapter = NULL; - - /* Print wlan0 or p2p0 states based on the adapter_num - *by using the correct adapter - */ - while ( adapter_num < 2 ) - { - if ( WLAN_ADAPTER == adapter_num ) - { - useAdapter = pAdapter; - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n\n wlan0 States:-"); - len += buf; - } - else if ( P2P_ADAPTER == adapter_num ) - { - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n\n p2p0 States:-"); - len += buf; - - if( !pHddCtx ) - { - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n pHddCtx is NULL"); - len += buf; - break; - } - - /*Printing p2p0 states only in the case when the device is - configured as a p2p_client*/ - useAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT); - if ( !useAdapter ) - { - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n Device not configured as P2P_CLIENT."); - len += buf; - break; - } - } - - hHal = WLAN_HDD_GET_HAL_CTX( useAdapter ); - pMac = PMAC_STRUCT( hHal ); - pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR( useAdapter ); - if( !pHddStaCtx ) - { - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n pHddStaCtx is NULL"); - len += buf; - break; - } - - tlState = smeGetTLSTAState(hHal, pHddStaCtx->conn_info.staId[0]); - - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n HDD Conn State - %s " - "\n \n SME State:" - "\n Neighbour Roam State - %s" - "\n CSR State - %s" - "\n CSR Substate - %s" - "\n \n TL STA %d State: %s", - macTraceGetHDDWlanConnState( - pHddStaCtx->conn_info.connState), - macTraceGetNeighbourRoamState( - pMac->roam.neighborRoamInfo.neighborRoamState), - macTraceGetcsrRoamState( - pMac->roam.curState[useAdapter->sessionId]), - macTraceGetcsrRoamSubState( - pMac->roam.curSubState[useAdapter->sessionId]), - pHddStaCtx->conn_info.staId[0], - macTraceGetTLState(tlState) - ); - len += buf; - adapter_num++; - } - - /* Printing Lim State starting with global lim states */ - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n \n LIM STATES:-" - "\n Global Sme State - %s "\ - "\n Global mlm State - %s "\ - "\n", - macTraceGetLimSmeState(pMac->lim.gLimSmeState), - macTraceGetLimMlmState(pMac->lim.gLimMlmState) - ); - len += buf; - - /*printing the PE Sme and Mlm states for valid lim sessions*/ - while ( check < 3 && count < 255) - { - if ( pMac->lim.gpSession[count].valid ) - { - buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, - "\n Lim Valid Session %d:-" - "\n PE Sme State - %s " - "\n PE Mlm State - %s " - "\n", - check, - macTraceGetLimSmeState(pMac->lim.gpSession[count].limSmeState), - macTraceGetLimMlmState(pMac->lim.gpSession[count].limMlmState) - ); - - len += buf; - check++; - } - count++; - } - - wrqu->data.length = strlen(extra)+1; - break; - } - - case WE_GET_CFG: - { - hdd_cfg_get_config(WLAN_HDD_GET_CTX(pAdapter), extra, WE_MAX_STR_LEN); - wrqu->data.length = strlen(extra)+1; - break; - } -#ifdef WLAN_FEATURE_11AC - case WE_GET_RSSI: - { - v_S7_t s7Rssi = 0; - wlan_hdd_get_rssi(pAdapter, &s7Rssi); - snprintf(extra, WE_MAX_STR_LEN, "rssi=%d",s7Rssi); - wrqu->data.length = strlen(extra)+1; - break; - } -#endif - -#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) - case WE_GET_ROAM_RSSI: - { - v_S7_t s7Rssi = 0; - wlan_hdd_get_roam_rssi(pAdapter, &s7Rssi); - snprintf(extra, WE_MAX_STR_LEN, "rssi=%d", s7Rssi); - wrqu->data.length = strlen(extra)+1; - break; - } -#endif - case WE_GET_WMM_STATUS: - { - snprintf(extra, WE_MAX_STR_LEN, - "\nDir: 0=up, 1=down, 3=both\n" - "|------------------------|\n" - "|AC | ACM |Admitted| Dir |\n" - "|------------------------|\n" - "|VO | %d | %3s | %d |\n" - "|VI | %d | %3s | %d |\n" - "|BE | %d | %3s | %d |\n" - "|BK | %d | %3s | %d |\n" - "|------------------------|\n", - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessRequired, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessAllowed?"YES":"NO", - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcTspecInfo.ts_info.direction, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessRequired, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessAllowed?"YES":"NO", - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcTspecInfo.ts_info.direction, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessRequired, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessAllowed?"YES":"NO", - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcTspecInfo.ts_info.direction, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessRequired, - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessAllowed?"YES":"NO", - pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcTspecInfo.ts_info.direction); - - - wrqu->data.length = strlen(extra)+1; - break; - } - case WE_GET_CHANNEL_LIST: - { - VOS_STATUS status; - v_U8_t i, len; - char* buf ; - - tChannelListInfo channel_list; - - status = iw_softap_get_channel_list(dev, info, wrqu, (char *)&channel_list); - if ( !VOS_IS_STATUS_SUCCESS( status ) ) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s GetChannelList Failed!!!\n",__func__); - return -EINVAL; - } - buf = extra; - - /** - * Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. Maximum buffer - * needed = 5 * number of channels. Check ifsufficient - * buffer is available and then proceed to fill the buffer. - */ - if(WE_MAX_STR_LEN < (5 * WNI_CFG_VALID_CHANNEL_LIST_LEN)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s Insufficient Buffer to populate channel list\n", - __func__); - return -EINVAL; - } - len = scnprintf(buf, WE_MAX_STR_LEN, "%u ", - channel_list.num_channels); - for(i = 0 ; i < channel_list.num_channels; i++) - { - len += scnprintf(buf + len, WE_MAX_STR_LEN - len, - "%u ", channel_list.channels[i]); - } - wrqu->data.length = strlen(extra)+1; - - break; - } -#ifdef FEATURE_WLAN_TDLS - case WE_GET_TDLS_PEERS: - { - wrqu->data.length = wlan_hdd_tdls_get_all_peers(pAdapter, extra, WE_MAX_STR_LEN)+1; - break; - } -#endif -#ifdef WLAN_FEATURE_11W - case WE_GET_11W_INFO: - { - hddLog(LOGE, "WE_GET_11W_ENABLED = %d", pWextState->roamProfile.MFPEnabled ); - - snprintf(extra, WE_MAX_STR_LEN, - "\n BSSID %02X:%02X:%02X:%02X:%02X:%02X, Is PMF Assoc? %d" - "\n Number of Unprotected Disassocs %d" - "\n Number of Unprotected Deauths %d", - (*pWextState->roamProfile.BSSIDs.bssid)[0], (*pWextState->roamProfile.BSSIDs.bssid)[1], - (*pWextState->roamProfile.BSSIDs.bssid)[2], (*pWextState->roamProfile.BSSIDs.bssid)[3], - (*pWextState->roamProfile.BSSIDs.bssid)[4], (*pWextState->roamProfile.BSSIDs.bssid)[5], - pWextState->roamProfile.MFPEnabled, pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx, - pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx); - - wrqu->data.length = strlen(extra)+1; - break; - } -#endif -#ifdef FEATURE_CESIUM_PROPRIETARY - case WE_GET_IBSS_STA_INFO: - { - hdd_station_ctx_t *pHddStaCtx = - WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - int idx = 0; - int length = 0, buf = 0; - - for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++) - { - if (0 != pHddStaCtx->conn_info.staId[ idx ]) - { - buf = snprintf - ( - (extra + length), WE_MAX_STR_LEN - length, - "\n%d .%02x:%02x:%02x:%02x:%02x:%02x\n", - pHddStaCtx->conn_info.staId[ idx ], - pHddStaCtx->conn_info.peerMacAddress[idx].bytes[0], - pHddStaCtx->conn_info.peerMacAddress[idx].bytes[1], - pHddStaCtx->conn_info.peerMacAddress[idx].bytes[2], - pHddStaCtx->conn_info.peerMacAddress[idx].bytes[3], - pHddStaCtx->conn_info.peerMacAddress[idx].bytes[4], - pHddStaCtx->conn_info.peerMacAddress[idx].bytes[5] - ); - length += buf; - } - } - wrqu->data.length = strlen(extra)+1; - break; - } -#endif -#ifdef QCA_WIFI_2_0 - case WE_GET_PHYMODE: - { - v_BOOL_t ch_bond24 = VOS_FALSE, ch_bond5g = VOS_FALSE; - hdd_context_t *hddctx = WLAN_HDD_GET_CTX(pAdapter); - tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter); - eCsrPhyMode phymode; - eCsrBand currBand; - tSmeConfigParams smeconfig; - - sme_GetConfigParam(hal, &smeconfig); - if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - smeconfig.csrConfig.channelBondingMode24GHz) - ch_bond24 = VOS_TRUE; - - if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - smeconfig.csrConfig.channelBondingMode5GHz) - ch_bond5g = VOS_TRUE; - - phymode = sme_GetPhyMode(hal); - if ((eHAL_STATUS_SUCCESS != sme_GetFreqBand(hal, &currBand))) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: Failed to get current band config", - __func__); - return -EIO; - } - - - switch (phymode) { - case eCSR_DOT11_MODE_AUTO: - snprintf(extra, WE_MAX_STR_LEN, "AUTO MODE"); - break; - case eCSR_DOT11_MODE_TAURUS: - case eCSR_DOT11_MODE_POLARIS: - case eCSR_DOT11_MODE_TAURUS_ONLY: - case eCSR_DOT11_MODE_TITAN: - case eCSR_DOT11_MODE_11n: - case eCSR_DOT11_MODE_11n_ONLY: - if (currBand == eCSR_BAND_24) { - if (ch_bond24) - snprintf(extra, WE_MAX_STR_LEN, "11NGHT40"); - else - snprintf(extra, WE_MAX_STR_LEN, "11NGHT20"); - } - else if(currBand == eCSR_BAND_5G) { - if (ch_bond5g) - snprintf(extra, WE_MAX_STR_LEN, "11NAHT40"); - else - snprintf(extra, WE_MAX_STR_LEN, "11NAHT20"); - } else { - snprintf(extra, WE_MAX_STR_LEN, "11N"); - } - break; - case eCSR_DOT11_MODE_abg: - snprintf(extra, WE_MAX_STR_LEN, "11ABG"); - break; - case eCSR_DOT11_MODE_11a: - case eCSR_DOT11_MODE_11a_ONLY: - snprintf(extra, WE_MAX_STR_LEN, "11A"); - break; - case eCSR_DOT11_MODE_11b: - case eCSR_DOT11_MODE_11b_ONLY: - snprintf(extra, WE_MAX_STR_LEN, "11B"); - break; - case eCSR_DOT11_MODE_11g: - case eCSR_DOT11_MODE_11g_ONLY: - snprintf(extra, WE_MAX_STR_LEN, "11G"); - break; -#ifdef WLAN_FEATURE_11AC - case eCSR_DOT11_MODE_11ac: - case eCSR_DOT11_MODE_11ac_ONLY: - if (hddctx->cfg_ini->vhtChannelWidth == - eHT_CHANNEL_WIDTH_20MHZ) - snprintf(extra, WE_MAX_STR_LEN, "11ACVHT20"); - else if (hddctx->cfg_ini->vhtChannelWidth == - eHT_CHANNEL_WIDTH_40MHZ) - snprintf(extra, WE_MAX_STR_LEN, "11ACVHT40"); - else if (hddctx->cfg_ini->vhtChannelWidth == - eHT_CHANNEL_WIDTH_80MHZ) - snprintf(extra, WE_MAX_STR_LEN, "11ACVHT80"); - else if (hddctx->cfg_ini->vhtChannelWidth == - eHT_CHANNEL_WIDTH_160MHZ) - snprintf(extra, WE_MAX_STR_LEN, "11ACVHT160"); - break; -#endif - } - - wrqu->data.length = strlen(extra)+1; - break; - } -#endif - default: - { - hddLog(LOGE, "Invalid IOCTL command %d", sub_cmd); - break; - } - } - - return 0; -} - -/* action sub-ioctls */ -static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int sub_cmd = wrqu->data.flags; - int ret = 0; /* success */ - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - switch (sub_cmd) - { - case WE_CLEAR_STATS: - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: clearing", __func__); - memset(&pAdapter->stats, 0, sizeof(pAdapter->stats)); - memset(&pAdapter->hdd_stats, 0, sizeof(pAdapter->hdd_stats)); - break; - } - case WE_INIT_AP: - { - pr_info("Init AP trigger\n"); - hdd_open_adapter( WLAN_HDD_GET_CTX(pAdapter), WLAN_HDD_SOFTAP, "softap.%d", - wlan_hdd_get_intf_addr( WLAN_HDD_GET_CTX(pAdapter) ),TRUE); - break; - } -#ifdef FEATURE_CESIUM_PROPRIETARY - case WE_IBSS_GET_PEER_INFO_ALL: - { - hdd_wlan_get_ibss_peer_info_all(pAdapter); - break; - } -#endif - case WE_STOP_AP: - { - /*FIX ME: Need to be revisited if multiple SAPs to be supported */ - /* As Soft AP mode has been changed to STA already with killing of Hostapd, - * this is a dead code and need to find the adpater by name rather than mode */ - hdd_adapter_t* pAdapter_to_stop = - hdd_get_adapter_by_name(WLAN_HDD_GET_CTX(pAdapter), "softap.0"); - if( pAdapter_to_stop ) - { - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - - pr_info("Stopping AP mode\n"); - - if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) - { - /* EXIT BMPS as fw cannot handle DEL_STA when its in BMPS */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); - } - - /*Make sure that pAdapter cleaned properly*/ - hdd_stop_adapter( pHddCtx, pAdapter_to_stop ); - hdd_deinit_adapter( pHddCtx, pAdapter_to_stop ); - memset(&pAdapter_to_stop->sessionCtx, 0, sizeof(pAdapter_to_stop->sessionCtx)); - - wlan_hdd_release_intf_addr(WLAN_HDD_GET_CTX(pAdapter), - pAdapter_to_stop->macAddressCurrent.bytes); - hdd_close_adapter(WLAN_HDD_GET_CTX(pAdapter), pAdapter_to_stop, - TRUE); - - if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) - { - /* put the device back into BMPS */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); - } - } - else - { - printk(KERN_ERR"SAP adapter not found to stop it!\n"); - } - - break; - } -#ifdef WLAN_BTAMP_FEATURE - case WE_ENABLE_AMP: - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: enabling AMP", __func__); - WLANBAP_RegisterWithHCI(pAdapter); - break; - } - case WE_DISABLE_AMP: - { - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); - VOS_STATUS status; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__); - - pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); - status = WLANBAP_StopAmp(); - if(VOS_STATUS_SUCCESS != status ) - { - pHddCtx->isAmpAllowed = VOS_TRUE; - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: Failed to stop AMP", __func__); - } - else - { - //a state m/c implementation in PAL is TBD to avoid this delay - msleep(500); - pHddCtx->isAmpAllowed = VOS_FALSE; - WLANBAP_DeregisterFromHCI(); - } - - break; - } - case WE_GET_PPS_PAID_MATCH: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_PAID_MATCH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_PAID_MATCH, - VDEV_CMD); - break; - } - case WE_GET_PPS_GID_MATCH: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_GID_MATCH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_GID_MATCH, - VDEV_CMD); - break; - } - case WE_GET_PPS_EARLY_TIM_CLEAR: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_TIM_CLEAR"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, - VDEV_CMD); - break; - } - case WE_GET_PPS_EARLY_DTIM_CLEAR: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_DTIM_CLEAR"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, - VDEV_CMD); - break; - } - case WE_GET_PPS_EOF_PAD_DELIM: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_EOF_PAD_DELIM"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EOF_PAD_DELIM, - VDEV_CMD); - break; - } - case WE_GET_PPS_MACADDR_MISMATCH: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_MACADDR_MISMATCH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_MACADDR_MISMATCH, - VDEV_CMD); - break; - } - case WE_GET_PPS_DELIM_CRC_FAIL: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_DELIM_CRC_FAIL"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, - VDEV_CMD); - break; - } - case WE_GET_PPS_GID_NSTS_ZERO: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_GID_NSTS_ZERO"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_GID_NSTS_ZERO, - VDEV_CMD); - break; - } - case WE_GET_PPS_RSSI_CHECK: - { - - hddLog(LOG1, "GET WMI_VDEV_PPS_RSSI_CHECK"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_RSSI_CHECK, - VDEV_CMD); - break; - } -#endif - - case WE_ENABLE_DXE_STALL_DETECT: - { - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - sme_transportDebug(hHal, VOS_FALSE, VOS_TRUE); - break; - } - case WE_DISPLAY_DXE_SNAP_SHOT: - { - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - sme_transportDebug(hHal, VOS_TRUE, VOS_FALSE); - break; - } - case WE_DISPLAY_DATAPATH_SNAP_SHOT: - { - hddLog(LOGE, "%s: called %d",__func__, sub_cmd); - hdd_wmm_tx_snapshot(pAdapter); - WLANTL_TLDebugMessage(VOS_TRUE); - break; - } - case WE_SET_REASSOC_TRIGGER: - { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tpAniSirGlobal pMac = WLAN_HDD_GET_HAL_CTX(pAdapter); - v_U32_t roamId = 0; - tCsrRoamModifyProfileFields modProfileFields; - sme_GetModifyProfileFields(pMac, pAdapter->sessionId, &modProfileFields); - sme_RoamReassoc(pMac, pAdapter->sessionId, NULL, modProfileFields, &roamId, 1); - return 0; - } - -#ifdef QCA_WIFI_2_0 - case WE_DUMP_AGC_START: - { - hddLog(LOG1, "WE_DUMP_AGC_START"); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_PARAM_DUMP_AGC_START, - 0, GEN_CMD); - break; - } - case WE_DUMP_AGC: - { - hddLog(LOG1, "WE_DUMP_AGC"); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_PARAM_DUMP_AGC, - 0, GEN_CMD); - break; - } - - case WE_DUMP_CHANINFO_START: - { - hddLog(LOG1, "WE_DUMP_CHANINFO_START"); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_PARAM_DUMP_CHANINFO_START, - 0, GEN_CMD); - break; - } - case WE_DUMP_CHANINFO: - { - hddLog(LOG1, "WE_DUMP_CHANINFO_START"); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_PARAM_DUMP_CHANINFO, - 0, GEN_CMD); - break; - } - case WE_DUMP_WATCHDOG: - { - hddLog(LOG1, "WE_DUMP_WATCHDOG"); - ret = process_wma_set_command((int)pAdapter->sessionId, - (int)GEN_PARAM_DUMP_WATCHDOG, - 0, GEN_CMD); - break; - } -#ifdef DEBUG - case WE_SET_FW_CRASH_INJECT: - { - hddLog(LOGE, "WE_FW_CRASH_INJECT"); - ret = process_wma_set_command((int) pAdapter->sessionId, - (int) GEN_PARAM_CRASH_INJECT, - 0, GEN_CMD); - break; - } -#endif -#endif - default: - { - hddLog(LOGE, "%s: unknown ioctl %d", __func__, sub_cmd); - break; - } - } - - return ret; -} - -void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter) -{ - /* - * Function to display HDD WMM information - * for Tx Queues. - * Prints globala as well as per client depending - * whether the clients are registered or not. - */ - int i = 0, j = 0; - for ( i=0; i< NUM_TX_QUEUES; i++) - { - spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock); - hddLog(LOGE, "HDD WMM TxQueue Info For AC: %d Count: %d PrevAdress:0x%x, NextAddress:0x%x", - i, pAdapter->wmm_tx_queue[i].count, - pAdapter->wmm_tx_queue[i].anchor.prev, pAdapter->wmm_tx_queue[i].anchor.next); - spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); - } - - for(i =0; i<WLAN_MAX_STA_COUNT; i++) - { - if(pAdapter->aStaInfo[i].isUsed) - { - hddLog(LOGE, "******STAIndex: %d*********", i); - for ( j=0; j< NUM_TX_QUEUES; j++) - { - spin_lock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); - hddLog(LOGE, "HDD TxQueue Info For AC: %d Count: %d PrevAdress:0x%x, NextAddress:0x%x", - j, pAdapter->aStaInfo[i].wmm_tx_queue[j].count, - pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.prev, - pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.next); - spin_unlock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); - } - } - } - -} -int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - int sub_cmd = wrqu->data.flags; - int *value = (int*)extra; - int apps_args[MAX_VAR_ARGS] = {0}; - int num_args = wrqu->data.length; - hdd_station_ctx_t *pStaCtx = NULL ; - hdd_ap_ctx_t *pAPCtx = NULL; - int cmd = 0; - int staId = 0; - - hddLog(LOG1, "%s: Received length %d", __func__, wrqu->data.length); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if (num_args > MAX_VAR_ARGS) - { - num_args = MAX_VAR_ARGS; - } - vos_mem_copy(apps_args, value, (sizeof(int)) * num_args); - - if(( sub_cmd == WE_MCC_CONFIG_CREDENTIAL ) || - (sub_cmd == WE_MCC_CONFIG_PARAMS )) - { - if(( pAdapter->device_mode == WLAN_HDD_INFRA_STATION )|| - ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT )) - { - pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - staId = pStaCtx->conn_info.staId[0]; - } - else if (( pAdapter->device_mode == WLAN_HDD_P2P_GO ) || - ( pAdapter->device_mode == WLAN_HDD_SOFTAP )) - { - pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); - staId = pAPCtx->uBCStaId; - } - else - { - hddLog(LOGE, "%s: Device mode %d not recognised", __FUNCTION__, pAdapter->device_mode); - return 0; - } - } - - switch (sub_cmd) - { - case WE_LOG_DUMP_CMD: - { - hddLog(LOG1, "%s: LOG_DUMP %d arg1 %d arg2 %d arg3 %d arg4 %d", - __func__, apps_args[0], apps_args[1], apps_args[2], - apps_args[3], apps_args[4]); - - logPrintf(hHal, apps_args[0], apps_args[1], apps_args[2], - apps_args[3], apps_args[4]); - - } - break; -#ifdef FEATURE_CESIUM_PROPRIETARY - case WE_IBSS_GET_PEER_INFO: - { - pr_info ( "Station ID = %d\n",apps_args[0]); - hdd_wlan_get_ibss_peer_info(pAdapter, apps_args[0]); - } - break; -#endif - - case WE_P2P_NOA_CMD: - { - p2p_app_setP2pPs_t p2pNoA; - - p2pNoA.opp_ps = apps_args[0]; - p2pNoA.ctWindow = apps_args[1]; - p2pNoA.duration = apps_args[2]; - p2pNoA.interval = apps_args[3]; - p2pNoA.count = apps_args[4]; - p2pNoA.single_noa_duration = apps_args[5]; - p2pNoA.psSelection = apps_args[6]; - - hddLog(LOG1, "%s: P2P_NOA_ATTR:oppPS %d ctWindow %d duration %d " - "interval %d count %d single noa duration %d PsSelection %x", - __func__, apps_args[0], apps_args[1], apps_args[2], - apps_args[3], apps_args[4], apps_args[5], apps_args[6]); - - hdd_setP2pPs(dev, &p2pNoA); - - } - break; - - case WE_MCC_CONFIG_CREDENTIAL : - { - cmd = 287; //Command should be updated if there is any change - // in the Riva dump command - if((apps_args[0] >= 40 ) && (apps_args[0] <= 160 )) - { - logPrintf(hHal, cmd, staId, apps_args[0], apps_args[1], apps_args[2]); - } - else - { - hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160\n", __func__); - return 0; - } - } - break; - - case WE_MCC_CONFIG_PARAMS : - { - cmd = 288; //command Should be updated if there is any change - // in the Riva dump command - hdd_validate_mcc_config(pAdapter, staId, apps_args[0], apps_args[1],apps_args[2]); - } - break; - -#ifdef FEATURE_WLAN_TDLS - case WE_TDLS_CONFIG_PARAMS : - { - tdls_config_params_t tdlsParams; - - tdlsParams.tdls = apps_args[0]; - tdlsParams.tx_period_t = apps_args[1]; - tdlsParams.tx_packet_n = apps_args[2]; - tdlsParams.discovery_period_t = apps_args[3]; - tdlsParams.discovery_tries_n = apps_args[4]; - tdlsParams.idle_timeout_t = apps_args[5]; - tdlsParams.idle_packet_n = apps_args[6]; - tdlsParams.rssi_hysteresis = apps_args[7]; - tdlsParams.rssi_trigger_threshold = apps_args[8]; - tdlsParams.rssi_teardown_threshold = apps_args[9]; - - wlan_hdd_tdls_set_params(dev, &tdlsParams); - } - break; -#endif - default: - { - hddLog(LOGE, "Invalid IOCTL command %d", sub_cmd ); - } - break; - } - - return 0; -} - - -static int iw_add_tspec(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra; - int params[HDD_WLAN_WMM_PARAM_COUNT]; - sme_QosWmmTspecInfo tSpec; - v_U32_t handle; - - // make sure the application is sufficiently priviledged - // note that the kernel will do this for "set" ioctls, but since - // this ioctl wants to return status to user space it must be - // defined as a "get" ioctl - if (!capable(CAP_NET_ADMIN)) - { - return -EPERM; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - // we must be associated in order to add a tspec - if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) - { - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - - // since we are defined to be a "get" ioctl, and since the number - // of params exceeds the number of params that wireless extensions - // will pass down in the iwreq_data, we must copy the "set" params - // from user space ourselves - if (copy_from_user(¶ms, wrqu->data.pointer, sizeof(params))) - { - // hmmm, can't get them - return -EIO; - } - - // clear the tspec - memset(&tSpec, 0, sizeof(tSpec)); - - // validate the handle - handle = params[HDD_WLAN_WMM_PARAM_HANDLE]; - if (HDD_WMM_HANDLE_IMPLICIT == handle) - { - // that one is reserved - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - - // validate the TID - if (params[HDD_WLAN_WMM_PARAM_TID] > 7) - { - // out of range - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - tSpec.ts_info.tid = params[HDD_WLAN_WMM_PARAM_TID]; - - // validate the direction - switch (params[HDD_WLAN_WMM_PARAM_DIRECTION]) - { - case HDD_WLAN_WMM_DIRECTION_UPSTREAM: - tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_UPLINK; - break; - - case HDD_WLAN_WMM_DIRECTION_DOWNSTREAM: - tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_DOWNLINK; - break; - - case HDD_WLAN_WMM_DIRECTION_BIDIRECTIONAL: - tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_BOTH; - break; - - default: - // unknown - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - - tSpec.ts_info.psb = params[HDD_WLAN_WMM_PARAM_APSD]; - - // validate the user priority - if (params[HDD_WLAN_WMM_PARAM_USER_PRIORITY] >= SME_QOS_WMM_UP_MAX) - { - // out of range - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - tSpec.ts_info.up = params[HDD_WLAN_WMM_PARAM_USER_PRIORITY]; - if(0 > tSpec.ts_info.up || SME_QOS_WMM_UP_MAX < tSpec.ts_info.up) - { - hddLog(VOS_TRACE_LEVEL_ERROR,"***ts_info.up out of bounds***"); - return 0; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, - "%s:TS_INFO PSB %d UP %d !!!", __func__, - tSpec.ts_info.psb, tSpec.ts_info.up); - - tSpec.nominal_msdu_size = params[HDD_WLAN_WMM_PARAM_NOMINAL_MSDU_SIZE]; - tSpec.maximum_msdu_size = params[HDD_WLAN_WMM_PARAM_MAXIMUM_MSDU_SIZE]; - tSpec.min_data_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_DATA_RATE]; - tSpec.mean_data_rate = params[HDD_WLAN_WMM_PARAM_MEAN_DATA_RATE]; - tSpec.peak_data_rate = params[HDD_WLAN_WMM_PARAM_PEAK_DATA_RATE]; - tSpec.max_burst_size = params[HDD_WLAN_WMM_PARAM_MAX_BURST_SIZE]; - tSpec.min_phy_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_PHY_RATE]; - tSpec.surplus_bw_allowance = params[HDD_WLAN_WMM_PARAM_SURPLUS_BANDWIDTH_ALLOWANCE]; - tSpec.min_service_interval = params[HDD_WLAN_WMM_PARAM_SERVICE_INTERVAL]; - tSpec.max_service_interval = params[HDD_WLAN_WMM_PARAM_MAX_SERVICE_INTERVAL]; - tSpec.suspension_interval = params[HDD_WLAN_WMM_PARAM_SUSPENSION_INTERVAL]; - tSpec.inactivity_interval = params[HDD_WLAN_WMM_PARAM_INACTIVITY_INTERVAL]; - - tSpec.ts_info.burst_size_defn = params[HDD_WLAN_WMM_PARAM_BURST_SIZE_DEFN]; - - // validate the ts info ack policy - switch (params[HDD_WLAN_WMM_PARAM_ACK_POLICY]) - { - case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK: - tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK; - break; - - case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK: - tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK; - break; - - default: - // unknown - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - - *pStatus = hdd_wmm_addts(pAdapter, handle, &tSpec); - return 0; -} - - -static int iw_del_tspec(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int *params = (int *)extra; - hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra; - v_U32_t handle; - - // make sure the application is sufficiently priviledged - // note that the kernel will do this for "set" ioctls, but since - // this ioctl wants to return status to user space it must be - // defined as a "get" ioctl - if (!capable(CAP_NET_ADMIN)) - { - return -EPERM; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - // although we are defined to be a "get" ioctl, the params we require - // will fit in the iwreq_data, therefore unlike iw_add_tspec() there - // is no need to copy the params from user space - - // validate the handle - handle = params[HDD_WLAN_WMM_PARAM_HANDLE]; - if (HDD_WMM_HANDLE_IMPLICIT == handle) - { - // that one is reserved - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - - *pStatus = hdd_wmm_delts(pAdapter, handle); - return 0; -} - - -static int iw_get_tspec(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int *params = (int *)extra; - hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra; - v_U32_t handle; - - // although we are defined to be a "get" ioctl, the params we require - // will fit in the iwreq_data, therefore unlike iw_add_tspec() there - // is no need to copy the params from user space - - // validate the handle - handle = params[HDD_WLAN_WMM_PARAM_HANDLE]; - if (HDD_WMM_HANDLE_IMPLICIT == handle) - { - // that one is reserved - *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; - return 0; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - *pStatus = hdd_wmm_checkts(pAdapter, handle); - return 0; -} - - -#ifdef FEATURE_WLAN_WAPI -static int iw_qcom_set_wapi_mode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; - - WAPI_FUNCTION_MODE *pWapiMode = (WAPI_FUNCTION_MODE *)extra; - - hddLog(LOG1, "The function iw_qcom_set_wapi_mode called"); - hddLog(LOG1, "%s: Received data %s", __func__, extra); - hddLog(LOG1, "%s: Received length %d", __func__, wrqu->data.length); - hddLog(LOG1, "%s: Input Data (wreq) WAPI Mode:%02d", __func__, pWapiMode->wapiMode); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if(WZC_ORIGINAL == pWapiMode->wapiMode) { - hddLog(LOG1, "%s: WAPI Mode Set to OFF", __func__); - /* Set Encryption mode to defualt , this allows next successfull non-WAPI Association */ - pRoamProfile->EncryptionType.numEntries = 1; - pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - pRoamProfile->mcEncryptionType.numEntries = 1; - pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - - pRoamProfile->AuthType.numEntries = 1; - pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; - pRoamProfile->AuthType.authType[0] = pHddStaCtx->conn_info.authType; - } - else if(WAPI_EXTENTION == pWapiMode->wapiMode) { - hddLog(LOG1, "%s: WAPI Mode Set to ON", __func__); - } - else - return -EINVAL; - - pAdapter->wapi_info.nWapiMode = pWapiMode->wapiMode; - - return 0; -} - -static int iw_qcom_get_wapi_mode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - WAPI_FUNCTION_MODE *pWapiMode = (WAPI_FUNCTION_MODE *)(extra); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - hddLog(LOG1, "The function iw_qcom_get_wapi_mode called"); - - pWapiMode->wapiMode = pAdapter->wapi_info.nWapiMode; - hddLog(LOG1, "%s: GET WAPI Mode Value:%02d", __func__, pWapiMode->wapiMode); - printk("\nGET WAPI MODE:%d",pWapiMode->wapiMode); - return 0; -} - -static int iw_qcom_set_wapi_assoc_info(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); -// WAPI_AssocInfo *pWapiAssocInfo = (WAPI_AssocInfo *)(wrqu->data.pointer); - WAPI_AssocInfo *pWapiAssocInfo = (WAPI_AssocInfo *)(extra); - int i = 0, j = 0; - hddLog(LOG1, "The function iw_qcom_set_wapi_assoc_info called"); - hddLog(LOG1, "%s: Received length %d", __func__, wrqu->data.length); - hddLog(LOG1, "%s: Received data %s", __func__, (char*)extra); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - VOS_ASSERT(pWapiAssocInfo); - - hddLog(LOG1, "%s: INPUT DATA:\nElement ID:0x%02x Length:0x%02x Version:0x%04x\n",__func__,pWapiAssocInfo->elementID,pWapiAssocInfo->length,pWapiAssocInfo->version); - hddLog(LOG1,"%s: akm Suite Cnt:0x%04x",__func__,pWapiAssocInfo->akmSuiteCount); - for(i =0 ; i < 16 ; i++) - hddLog(LOG1,"akm suite[%02d]:0x%08lx",i,pWapiAssocInfo->akmSuite[i]); - - hddLog(LOG1,"%s: Unicast Suite Cnt:0x%04x",__func__,pWapiAssocInfo->unicastSuiteCount); - for(i =0 ; i < 16 ; i++) - hddLog(LOG1, "Unicast suite[%02d]:0x%08lx",i,pWapiAssocInfo->unicastSuite[i]); - - hddLog(LOG1,"%s: Multicast suite:0x%08lx Wapi capa:0x%04x",__func__,pWapiAssocInfo->multicastSuite,pWapiAssocInfo->wapiCability); - hddLog(LOG1, "%s: BKID Cnt:0x%04x\n",__func__,pWapiAssocInfo->bkidCount); - for(i = 0 ; i < 16 ; i++) { - hddLog(LOG1, "BKID List[%02d].bkid:0x",i); - for(j = 0 ; j < 16 ; j++) - hddLog(LOG1,"%02x",pWapiAssocInfo->bkidList[i].bkid[j]); - } - - /* We are not using the entire IE as provided by the supplicant. - * This is being calculated by SME. This is the same as in the - * case of WPA. Only the auth mode information needs to be - * extracted here*/ - if ( pWapiAssocInfo->akmSuite[0] == WAPI_PSK_AKM_SUITE ) { - hddLog(LOG1, "%s: WAPI AUTH MODE SET TO PSK",__func__); - pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK; - } - - if ( pWapiAssocInfo->akmSuite[0] == WAPI_CERT_AKM_SUITE) { - hddLog(LOG1, "%s: WAPI AUTH MODE SET TO CERTIFICATE",__func__); - pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT; - } - return 0; -} - -static int iw_qcom_set_wapi_key(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - eHalStatus halStatus = eHAL_STATUS_SUCCESS; - tANI_U32 roamId = 0xFF; - tANI_U8 *pKeyPtr = NULL; - v_BOOL_t isConnected = TRUE; - tCsrRoamSetKey setKey; - int i = 0; - WLAN_WAPI_KEY *pWapiKey = (WLAN_WAPI_KEY *)(extra); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - hddLog(LOG1, "The function iw_qcom_set_wapi_key called "); - hddLog(LOG1, "%s: Received length %d", __func__, wrqu->data.length); - hddLog(LOG1, "%s: Received data %s", __func__, (char*)extra); - - hddLog(LOG1,":%s: INPUT DATA:\nKey Type:0x%02x Key Direction:0x%02x KEY ID:0x%02x\n", __func__, pWapiKey->keyType, pWapiKey->keyDirection, pWapiKey->keyId); - hddLog(LOG1,"Add Index:0x"); - for(i =0 ; i < 12 ; i++) - hddLog(LOG1,"%02x",pWapiKey->addrIndex[i]); - - hddLog(LOG1,"\n%s: WAPI ENCRYPTION KEY LENGTH:0x%04x", __func__,pWapiKey->wpiekLen); - hddLog(LOG1, "WAPI ENCRYPTION KEY:0x"); - for(i =0 ; i < 16 ; i++) - hddLog(LOG1,"%02x",pWapiKey->wpiek[i]); - - hddLog(LOG1,"\n%s: WAPI INTEGRITY CHECK KEY LENGTH:0x%04x", __func__,pWapiKey->wpickLen); - hddLog(LOG1,"WAPI INTEGRITY CHECK KEY:0x"); - for(i =0 ; i < 16 ; i++) - hddLog(LOG1,"%02x",pWapiKey->wpick[i]); - - hddLog(LOG1,"\nWAPI PN NUMBER:0x"); - for(i = 0 ; i < 16 ; i++) - hddLog(LOG1,"%02x",pWapiKey->pn[i]); - - // Clear the setkey memory - vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); - // Store Key ID - setKey.keyId = (unsigned char)( pWapiKey->keyId ); - // SET WAPI Encryption - setKey.encType = eCSR_ENCRYPT_TYPE_WPI; - // Key Directionn both TX and RX - setKey.keyDirection = eSIR_TX_RX; // Do WE NEED to update this based on Key Type as GRP/UNICAST?? - // the PAE role - setKey.paeRole = 0 ; - - switch ( pWapiKey->keyType ) - { - case PAIRWISE_KEY: - { - isConnected = hdd_connIsConnected(pHddStaCtx); - vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN); - break; - } - case GROUP_KEY: - { - vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac ); - break; - } - default: - { - //Any other option is invalid. - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "[%4d] %s() failed to Set Key. Invalid key type %d", __LINE__,__func__ , -1 ); - - hddLog(LOGE," %s: Error WAPI Key Add Type",__func__); - halStatus = !eHAL_STATUS_SUCCESS; // NEED TO UPDATE THIS WITH CORRECT VALUE - break; // NEED RETURN FROM HERE ???? - } - } - - // Concatenating the Encryption Key (EK) and the MIC key (CK): EK followed by CK - setKey.keyLength = (v_U16_t)((pWapiKey->wpiekLen)+(pWapiKey->wpickLen)); - pKeyPtr = setKey.Key; - memcpy( pKeyPtr, pWapiKey->wpiek, pWapiKey->wpiekLen ); - pKeyPtr += pWapiKey->wpiekLen; - memcpy( pKeyPtr, pWapiKey->wpick, pWapiKey->wpickLen ); - - // Set the new key with SME. - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - - if ( isConnected ) { - halStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); - if ( halStatus != eHAL_STATUS_SUCCESS ) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "[%4d] sme_RoamSetKey returned ERROR status= %d", __LINE__, halStatus ); - - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; - } - } -#if 0 /// NEED TO CHECK ON THIS - else - { - // Store the keys in the adapter to be moved to the profile & passed to - // SME in the ConnectRequest if we are not yet in connected state. - memcpy( &pAdapter->setKey[ setKey.keyId ], &setKey, sizeof( setKey ) ); - pAdapter->fKeySet[ setKey.keyId ] = TRUE; - - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - " Saving key [idx= %d] to apply when moving to connected state ", - setKey.keyId ); - - } -#endif - return halStatus; -} - -static int iw_qcom_set_wapi_bkid(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); -#ifdef WLAN_DEBUG - int i = 0; - WLAN_BKID_LIST *pBkid = ( WLAN_BKID_LIST *) extra; -#endif - - hddLog(LOG1, "The function iw_qcom_set_wapi_bkid called"); - hddLog(LOG1, "%s: Received length %d", __func__, wrqu->data.length); - hddLog(LOG1, "%s: Received data %s", __func__, (char*)extra); - - hddLog(LOG1,"%s: INPUT DATA:\n BKID Length:0x%08lx\n", __func__,pBkid->length); - hddLog(LOG1,"%s: BKID Cnt:0x%04lx",pBkid->BKIDCount); - - hddLog(LOG1,"BKID KEY LIST[0]:0x"); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - -#ifdef WLAN_DEBUG - for(i =0 ; i < 16 ; i++) - hddLog(LOG1,"%02x",pBkid->BKID[0].bkid[i]); -#endif - - return 0; -} - -static int iw_qcom_get_wapi_bkid(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* Yet to implement this function, 19th April 2010 */ - hddLog(LOG1, "The function iw_qcom_get_wapi_bkid called "); - - return 0; -} -#endif /* FEATURE_WLAN_WAPI */ - -#ifdef WLAN_FEATURE_VOWIFI_11R -// -// -// Each time the supplicant has the auth_request or reassoc request -// IEs ready. This is pushed to the driver. The driver will inturn use -// it to send out the auth req and reassoc req for 11r FT Assoc. -// -static int iw_set_fties(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - //v_CONTEXT_t pVosContext; - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - if (!wrqu->data.length) - { - hddLog(LOGE, FL("called with 0 length IEs\n")); - return -EINVAL; - } - if (wrqu->data.pointer == NULL) - { - hddLog(LOGE, FL("called with NULL IE\n")); - return -EINVAL; - } - - // Added for debug on reception of Re-assoc Req. - if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) - { - hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"), - wrqu->data.length); - hddLog(LOGE, FL("Should be Re-assoc Req IEs\n")); - } - -#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__, wrqu->data.length); -#endif - - // Pass the received FT IEs to SME - sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, extra, - wrqu->data.length); - - return 0; -} -#endif - -static int iw_set_dynamic_mcbc_filter(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tpRcvFltMcAddrList pRequest = (tpRcvFltMcAddrList)extra; - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - tpSirWlanSetRxpFilters wlanRxpFilterParam; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - tpSirRcvFltMcAddrList mc_addr_list_ptr; - int idx; - eHalStatus ret_val; - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - if ((HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting) || - (HDD_MULTICAST_FILTER_LIST_CLEAR == pRequest->mcastBcastFilterSetting)) - { -#ifdef WLAN_FEATURE_PACKET_FILTERING - - mc_addr_list_ptr = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); - if (NULL == mc_addr_list_ptr) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: vos_mem_alloc failed", __func__); - return -ENOMEM; - } - - mc_addr_list_ptr->ulMulticastAddrCnt = pRequest->mcast_addr_cnt; - - if (mc_addr_list_ptr->ulMulticastAddrCnt > HDD_MAX_NUM_MULTICAST_ADDRESS) - mc_addr_list_ptr->ulMulticastAddrCnt = HDD_MAX_NUM_MULTICAST_ADDRESS; - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s MC Addr List Cnt %d", __func__, - mc_addr_list_ptr->ulMulticastAddrCnt); - - for (idx = 0; idx < mc_addr_list_ptr->ulMulticastAddrCnt; idx++) - { - memcpy(&mc_addr_list_ptr->multicastAddr[idx], - pRequest->multicastAddr[idx], HDD_WLAN_MAC_ADDR_LEN); - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s MC Addr for Idx %d ="MAC_ADDRESS_STR, __func__, - idx, MAC_ADDR_ARRAY(mc_addr_list_ptr->multicastAddr[idx])); - } - - if (HDD_MULTICAST_FILTER_LIST_CLEAR == pRequest->mcastBcastFilterSetting) - mc_addr_list_ptr->action = 1; //clear - else - mc_addr_list_ptr->action = 0; //set - - ret_val = sme_8023MulticastList(hHal, pAdapter->sessionId, mc_addr_list_ptr); - vos_mem_free(mc_addr_list_ptr); - if (eHAL_STATUS_SUCCESS != ret_val) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to Set MC Address List", - __func__); - return -EINVAL; - } -#endif //WLAN_FEATURE_PACKET_FILTERING - } - else - { - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, - "%s: Set MC BC Filter Config request: %d suspend %d", - __func__, pRequest->mcastBcastFilterSetting, - pHddCtx->hdd_wlan_suspended); - - pHddCtx->configuredMcastBcastFilter = pRequest->mcastBcastFilterSetting; - - if (pHddCtx->hdd_wlan_suspended) - { - wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); - if (NULL == wlanRxpFilterParam) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: vos_mem_alloc failed", __func__); - return -EINVAL; - } - - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - pRequest->mcastBcastFilterSetting; - wlanRxpFilterParam->setMcstBcstFilter = TRUE; - - hdd_conf_hostoffload(pAdapter, TRUE); - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - pHddCtx->configuredMcastBcastFilter; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s:MC/BC changed Req %d Set %d En %d", - __func__, - pHddCtx->configuredMcastBcastFilter, - wlanRxpFilterParam->configuredMcstBcstFilterSetting, - wlanRxpFilterParam->setMcstBcstFilter); - - if (eHAL_STATUS_SUCCESS != - sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), - wlanRxpFilterParam)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Failure to execute set HW MC/BC Filter request", - __func__); - vos_mem_free(wlanRxpFilterParam); - return -EINVAL; - } - - } - } - - return 0; -} - -static int iw_clear_dynamic_mcbc_filter(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - tpSirWlanSetRxpFilters wlanRxpFilterParam; - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: ", __func__); - - //Reset the filter to INI value as we have to clear the dynamic filter - pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; - - //Configure FW with new setting - if (pHddCtx->hdd_wlan_suspended) - { - wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); - if (NULL == wlanRxpFilterParam) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: vos_mem_alloc failed", __func__); - return -EINVAL; - } - - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - pHddCtx->configuredMcastBcastFilter; - wlanRxpFilterParam->setMcstBcstFilter = TRUE; - - hdd_conf_hostoffload(pAdapter, TRUE); - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - pHddCtx->configuredMcastBcastFilter; - - if (eHAL_STATUS_SUCCESS != - sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), - wlanRxpFilterParam)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Failure to execute set HW MC/BC Filter request", - __func__); - vos_mem_free(wlanRxpFilterParam); - return -EINVAL; - } - } - return 0; -} - -static int iw_set_host_offload(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tpHostOffloadRequest pRequest = (tpHostOffloadRequest) extra; - tSirHostOffloadReq offloadRequest; - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - /* Debug display of request components. */ - switch (pRequest->offloadType) - { - case WLAN_IPV4_ARP_REPLY_OFFLOAD: - hddLog(VOS_TRACE_LEVEL_WARN, "%s: Host offload request: ARP reply", __func__); - switch (pRequest->enableOrDisable) - { - case WLAN_OFFLOAD_DISABLE: - hddLog(VOS_TRACE_LEVEL_WARN, " disable"); - break; - case WLAN_OFFLOAD_ARP_AND_BC_FILTER_ENABLE: - hddLog(VOS_TRACE_LEVEL_WARN, " BC Filtering enable"); - case WLAN_OFFLOAD_ENABLE: - hddLog(VOS_TRACE_LEVEL_WARN, " ARP offload enable"); - hddLog(VOS_TRACE_LEVEL_WARN, " IP address: %d.%d.%d.%d", - pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1], - pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]); - } - break; - - case WLAN_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD: - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Host offload request: neighbor discovery\n", - __func__); - switch (pRequest->enableOrDisable) - { - case WLAN_OFFLOAD_DISABLE: - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " disable"); - break; - case WLAN_OFFLOAD_ENABLE: - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " enable"); - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " IP address: %x:%x:%x:%x:%x:%x:%x:%x", - *(v_U16_t *)(pRequest->params.hostIpv6Addr), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 2), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 4), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 6), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 8), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 10), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 12), - *(v_U16_t *)(pRequest->params.hostIpv6Addr + 14)); - } - } - - /* Execute offload request. The reason that we can copy the request information - from the ioctl structure to the SME structure is that they are laid out - exactly the same. Otherwise, each piece of information would have to be - copied individually. */ - memcpy(&offloadRequest, pRequest, wrqu->data.length); - if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, &offloadRequest)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute host offload request\n", - __func__); - return -EINVAL; - } - - return 0; -} - -static int iw_set_keepalive_params(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tpKeepAliveRequest pRequest = (tpKeepAliveRequest) extra; - tSirKeepAliveReq keepaliveRequest; - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return 0; - } - - /* Debug display of request components. */ - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: Set Keep Alive Request : TimePeriod %d size %zu", - __func__, pRequest->timePeriod, sizeof(tKeepAliveRequest)); - - switch (pRequest->packetType) - { - case WLAN_KEEP_ALIVE_NULL_PKT: - hddLog(VOS_TRACE_LEVEL_WARN, "%s: Keep Alive Request: Tx NULL", __func__); - break; - - case WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP: - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Keep Alive Request: Tx UnSolicited ARP RSP\n", - __func__); - - hddLog(VOS_TRACE_LEVEL_WARN, " Host IP address: %d.%d.%d.%d", - pRequest->hostIpv4Addr[0], pRequest->hostIpv4Addr[1], - pRequest->hostIpv4Addr[2], pRequest->hostIpv4Addr[3]); - - hddLog(VOS_TRACE_LEVEL_WARN, " Dest IP address: %d.%d.%d.%d", - pRequest->destIpv4Addr[0], pRequest->destIpv4Addr[1], - pRequest->destIpv4Addr[2], pRequest->destIpv4Addr[3]); - - hddLog(VOS_TRACE_LEVEL_WARN, " Dest MAC address: %d:%d:%d:%d:%d:%d", - pRequest->destMacAddr[0], pRequest->destMacAddr[1], - pRequest->destMacAddr[2], pRequest->destMacAddr[3], - pRequest->destMacAddr[4], pRequest->destMacAddr[5]); - break; - } - - /* Execute keep alive request. The reason that we can copy the request information - from the ioctl structure to the SME structure is that they are laid out - exactly the same. Otherwise, each piece of information would have to be - copied individually. */ - memcpy(&keepaliveRequest, pRequest, wrqu->data.length); - - hddLog(VOS_TRACE_LEVEL_ERROR, "set Keep: TP before SME %d\n", keepaliveRequest.timePeriod); - - if (eHAL_STATUS_SUCCESS != sme_SetKeepAlive(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, &keepaliveRequest)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Keep Alive\n", - __func__); - return -EINVAL; - } - - return 0; -} - -#ifdef WLAN_FEATURE_PACKET_FILTERING -int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, - tANI_U8 sessionId) -{ - tSirRcvPktFilterCfgType packetFilterSetReq = {0}; - tSirRcvFltPktClearParam packetFilterClrReq = {0}; - int i=0; - - if (pHddCtx->cfg_ini->disablePacketFilter) - { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Packet Filtering Disabled. Returning ", - __func__ ); - return 0; - } - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - /* Debug display of request components. */ - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Packet Filter Request : FA %d params %d", - __func__, pRequest->filterAction, pRequest->numParams); - - switch (pRequest->filterAction) - { - case HDD_RCV_FILTER_SET: - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set Packet Filter Request for Id: %d", - __func__, pRequest->filterId); - - packetFilterSetReq.filterId = pRequest->filterId; - if ( pRequest->numParams >= HDD_MAX_CMP_PER_PACKET_FILTER) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Number of Params exceed Max limit %d\n", - __func__, pRequest->numParams); - return -EINVAL; - } - packetFilterSetReq.numFieldParams = pRequest->numParams; - packetFilterSetReq.coalesceTime = 0; - packetFilterSetReq.filterType = 1; - for (i=0; i < pRequest->numParams; i++) - { - packetFilterSetReq.paramsData[i].protocolLayer = pRequest->paramsData[i].protocolLayer; - packetFilterSetReq.paramsData[i].cmpFlag = pRequest->paramsData[i].cmpFlag; - packetFilterSetReq.paramsData[i].dataOffset = pRequest->paramsData[i].dataOffset; - packetFilterSetReq.paramsData[i].dataLength = pRequest->paramsData[i].dataLength; - packetFilterSetReq.paramsData[i].reserved = 0; - - hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type %d\n", - pRequest->paramsData[i].protocolLayer, pRequest->paramsData[i].cmpFlag, - packetFilterSetReq.filterType); - - hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d\n", - pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength); - - memcpy(&packetFilterSetReq.paramsData[i].compareData, - pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength); - memcpy(&packetFilterSetReq.paramsData[i].dataMask, - pRequest->paramsData[i].dataMask, pRequest->paramsData[i].dataLength); - - hddLog(VOS_TRACE_LEVEL_INFO, "CData %d CData %d CData %d CData %d CData %d CData %d\n", - pRequest->paramsData[i].compareData[0], pRequest->paramsData[i].compareData[1], - pRequest->paramsData[i].compareData[2], pRequest->paramsData[i].compareData[3], - pRequest->paramsData[i].compareData[4], pRequest->paramsData[i].compareData[5]); - - hddLog(VOS_TRACE_LEVEL_INFO, "MData %d MData %d MData %d MData %d MData %d MData %d\n", - pRequest->paramsData[i].dataMask[0], pRequest->paramsData[i].dataMask[1], - pRequest->paramsData[i].dataMask[2], pRequest->paramsData[i].dataMask[3], - pRequest->paramsData[i].dataMask[4], pRequest->paramsData[i].dataMask[5]); - } - - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, &packetFilterSetReq, sessionId)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Set Filter\n", - __func__); - return -EINVAL; - } - - break; - - case HDD_RCV_FILTER_CLEAR: - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Clear Packet Filter Request for Id: %d\n", - __func__, pRequest->filterId); - packetFilterClrReq.filterId = pRequest->filterId; - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, &packetFilterClrReq, sessionId)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter\n", - __func__); - return -EINVAL; - } - break; - - default : - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Packet Filter Request: Invalid %d\n", - __func__, pRequest->filterAction); - return -EINVAL; - } - return 0; -} - -int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, - tANI_U8 sessionId) -{ - tSirRcvPktFilterCfgType packetFilterSetReq = {0}; - tSirRcvFltPktClearParam packetFilterClrReq = {0}; - - if (NULL == pHddCtx) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL(" NULL HDD Context Passed")); - return -EINVAL; - } - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if (pHddCtx->cfg_ini->disablePacketFilter) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Packet Filtering Disabled. Returning ", - __func__ ); - return -EINVAL; - } - - switch (filterType) - { - /* For setting IPV6 MC and UC Filter we need to configure - * 2 filters, one for MC and one for UC. - * The Filter ID shouldn't be swapped, which results in making - * UC Filter ineffective. - * We have Hardcode all the values - * - * Reason for a seperate UC filter is because, driver need to - * specify the FW that the specific filter is for unicast - * otherwise FW will not pass the unicast frames by default - * through the filter. This is required to avoid any performance - * hits when no unicast filter is set and only MC/BC are set. - * The way driver informs host is by using the MAC protocol - * layer, CMP flag set to MAX, CMP Data set to 1. - */ - - case HDD_FILTER_IPV6_MC_UC: - /* Setting IPV6 MC Filter below - */ - packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; - packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; - packetFilterSetReq.numFieldParams = 2; - packetFilterSetReq.paramsData[0].protocolLayer = - HDD_FILTER_PROTO_TYPE_MAC; - packetFilterSetReq.paramsData[0].cmpFlag = - HDD_FILTER_CMP_TYPE_NOT_EQUAL; - packetFilterSetReq.paramsData[0].dataOffset = - WLAN_HDD_80211_FRM_DA_OFFSET; - packetFilterSetReq.paramsData[0].dataLength = 1; - packetFilterSetReq.paramsData[0].compareData[0] = - HDD_IPV6_MC_CMP_DATA; - - packetFilterSetReq.paramsData[1].protocolLayer = - HDD_FILTER_PROTO_TYPE_ARP; - packetFilterSetReq.paramsData[1].cmpFlag = - HDD_FILTER_CMP_TYPE_NOT_EQUAL; - packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; - packetFilterSetReq.paramsData[1].dataLength = 2; - packetFilterSetReq.paramsData[1].compareData[0] = - HDD_IPV6_CMP_DATA_0; - packetFilterSetReq.paramsData[1].compareData[1] = - HDD_IPV6_CMP_DATA_1; - - - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, - &packetFilterSetReq, sessionId)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Failure to execute Set IPv6 Mulicast Filter", - __func__); - return -EINVAL; - } - - memset( &packetFilterSetReq, 0, sizeof(tSirRcvPktFilterCfgType)); - - /* - * Setting IPV6 UC Filter below - */ - packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; - packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_UC; - packetFilterSetReq.numFieldParams = 2; - packetFilterSetReq.paramsData[0].protocolLayer = - HDD_FILTER_PROTO_TYPE_MAC; - packetFilterSetReq.paramsData[0].cmpFlag = - HDD_FILTER_CMP_TYPE_MAX; - packetFilterSetReq.paramsData[0].dataOffset = 0; - packetFilterSetReq.paramsData[0].dataLength = 1; - packetFilterSetReq.paramsData[0].compareData[0] = - HDD_IPV6_UC_CMP_DATA; - - packetFilterSetReq.paramsData[1].protocolLayer = - HDD_FILTER_PROTO_TYPE_ARP; - packetFilterSetReq.paramsData[1].cmpFlag = - HDD_FILTER_CMP_TYPE_NOT_EQUAL; - packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; - packetFilterSetReq.paramsData[1].dataLength = 2; - packetFilterSetReq.paramsData[1].compareData[0] = - HDD_IPV6_CMP_DATA_0; - packetFilterSetReq.paramsData[1].compareData[1] = - HDD_IPV6_CMP_DATA_1; - - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, - &packetFilterSetReq, sessionId)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Failure to execute Set IPv6 Unicast Filter", - __func__); - return -EINVAL; - } - - break; - - case HDD_FILTER_IPV6_MC: - /* - * IPV6 UC Filter might be already set, - * clear the UC Filter. As the Filter - * IDs are static, we can directly clear it. - */ - packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; - packetFilterClrReq.filterId = HDD_FILTER_ID_IPV6_UC; - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, - &packetFilterClrReq, sessionId)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Failure to execute Clear IPv6 Unicast Filter", - __func__); - return -EINVAL; - } - - /* - * Setting IPV6 MC Filter below - */ - packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; - packetFilterSetReq.numFieldParams = 2; - packetFilterSetReq.paramsData[0].protocolLayer = - HDD_FILTER_PROTO_TYPE_MAC; - packetFilterSetReq.paramsData[0].cmpFlag = - HDD_FILTER_CMP_TYPE_NOT_EQUAL; - packetFilterSetReq.paramsData[0].dataOffset = - WLAN_HDD_80211_FRM_DA_OFFSET; - packetFilterSetReq.paramsData[0].dataLength = 1; - packetFilterSetReq.paramsData[0].compareData[0] = - HDD_IPV6_MC_CMP_DATA; - - packetFilterSetReq.paramsData[1].protocolLayer = - HDD_FILTER_PROTO_TYPE_ARP; - packetFilterSetReq.paramsData[1].cmpFlag = - HDD_FILTER_CMP_TYPE_NOT_EQUAL; - packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; - packetFilterSetReq.paramsData[1].dataLength = 2; - packetFilterSetReq.paramsData[1].compareData[0] = - HDD_IPV6_CMP_DATA_0; - packetFilterSetReq.paramsData[1].compareData[1] = - HDD_IPV6_CMP_DATA_1; - - - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, - &packetFilterSetReq, sessionId)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Failure to execute Set IPv6 Multicast Filter", - __func__); - return -EINVAL; - } - break; - - default : - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, - "%s: Packet Filter Request: Invalid", - __func__); - return -EINVAL; - } - return 0; -} - -void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set) -{ - v_U8_t i; - tpSirRcvFltMcAddrList pMulticastAddrs = NULL; - tHalHandle hHal = NULL; - hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; - - if (NULL == pHddCtx) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD CTX is NULL")); - return; - } - - hHal = pHddCtx->hHal; - - if (NULL == hHal) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("HAL Handle is NULL")); - return; - } - - /* Check if INI is enabled or not, other wise just return - */ - if (pHddCtx->cfg_ini->fEnableMCAddrList) - { - pMulticastAddrs = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); - if (NULL == pMulticastAddrs) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Could not allocate Memory")); - return; - } - - if (set) - { - /* Following pre-conditions should be satisfied before wei - * configure the MC address list. - */ - if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || - (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) - && pAdapter->mc_addr_list.mc_cnt - && (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - { - pMulticastAddrs->ulMulticastAddrCnt = - pAdapter->mc_addr_list.mc_cnt; - for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) - { - memcpy(&(pMulticastAddrs->multicastAddr[i][0]), - &(pAdapter->mc_addr_list.addr[i][0]), - sizeof(pAdapter->mc_addr_list.addr[i])); - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: %s multicast filter: addr =" - MAC_ADDRESS_STR, - __func__, set ? "setting" : "clearing", - MAC_ADDR_ARRAY(pMulticastAddrs->multicastAddr[i])); - } - /* Set multicast filter */ - sme_8023MulticastList(hHal, pAdapter->sessionId, - pMulticastAddrs); - } - } - else - { - /* Need to clear only if it was previously configured - */ - if (pAdapter->mc_addr_list.isFilterApplied) - { - pMulticastAddrs->ulMulticastAddrCnt = 0; - sme_8023MulticastList(hHal, pAdapter->sessionId, - pMulticastAddrs); - } - - } - pAdapter->mc_addr_list.isFilterApplied = set ? TRUE : FALSE; - vos_mem_free(pMulticastAddrs); - } - else - { - hddLog(VOS_TRACE_LEVEL_INFO, - FL("gMCAddrListEnable is not enabled in INI")); - } - return; -} - -static int iw_set_packet_filter_params(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tpPacketFilterCfg pRequest = (tpPacketFilterCfg) extra; - - return wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest, pAdapter->sessionId); -} -#endif -static int iw_get_statistics(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - VOS_STATUS vos_status = VOS_STATUS_SUCCESS; - eHalStatus status = eHAL_STATUS_SUCCESS; - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - char *p = extra; - int tlen = 0; - tCsrSummaryStatsInfo *pStats = &(pAdapter->hdd_stats.summary_stat); - - tCsrGlobalClassAStatsInfo *aStats = &(pAdapter->hdd_stats.ClassA_stat); - tCsrGlobalClassDStatsInfo *dStats = &(pAdapter->hdd_stats.ClassD_stat); - - ENTER(); - - if (pHddCtx->isLogpInProgress) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EINVAL; - } - - if (eConnectionState_Associated != (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) { - - wrqu->txpower.value = 0; - } - else { - status = sme_GetStatistics( pHddCtx->hHal, eCSR_HDD, - SME_SUMMARY_STATS | - SME_GLOBAL_CLASSA_STATS | - SME_GLOBAL_CLASSB_STATS | - SME_GLOBAL_CLASSC_STATS | - SME_GLOBAL_CLASSD_STATS | - SME_PER_STA_STATS, - hdd_StatisticsCB, 0, FALSE, - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter ); - - if (eHAL_STATUS_SUCCESS != status) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to retrieve SME statistics", - __func__); - return -EINVAL; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS); - if (!VOS_IS_STATUS_SUCCESS(vos_status)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME timeout while retrieving statistics", - __func__); - /*Remove the SME statistics list by passing NULL in callback argument*/ - status = sme_GetStatistics( pHddCtx->hHal, eCSR_HDD, - SME_SUMMARY_STATS | - SME_GLOBAL_CLASSA_STATS | - SME_GLOBAL_CLASSB_STATS | - SME_GLOBAL_CLASSC_STATS | - SME_GLOBAL_CLASSD_STATS | - SME_PER_STA_STATS, - NULL, 0, FALSE, - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter ); - - return -EINVAL; - } - FILL_TLV(p, (tANI_U8)WLAN_STATS_RETRY_CNT, - (tANI_U8) sizeof (pStats->retry_cnt), - (char*) &(pStats->retry_cnt[0]), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_MUL_RETRY_CNT, - (tANI_U8) sizeof (pStats->multiple_retry_cnt), - (char*) &(pStats->multiple_retry_cnt[0]), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_FRM_CNT, - (tANI_U8) sizeof (pStats->tx_frm_cnt), - (char*) &(pStats->tx_frm_cnt[0]), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_FRM_CNT, - (tANI_U8) sizeof (pStats->rx_frm_cnt), - (char*) &(pStats->rx_frm_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_FRM_DUP_CNT, - (tANI_U8) sizeof (pStats->frm_dup_cnt), - (char*) &(pStats->frm_dup_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_FAIL_CNT, - (tANI_U8) sizeof (pStats->fail_cnt), - (char*) &(pStats->fail_cnt[0]), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_FAIL_CNT, - (tANI_U8) sizeof (pStats->rts_fail_cnt), - (char*) &(pStats->rts_fail_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_ACK_FAIL_CNT, - (tANI_U8) sizeof (pStats->ack_fail_cnt), - (char*) &(pStats->ack_fail_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_SUC_CNT, - (tANI_U8) sizeof (pStats->rts_succ_cnt), - (char*) &(pStats->rts_succ_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_DISCARD_CNT, - (tANI_U8) sizeof (pStats->rx_discard_cnt), - (char*) &(pStats->rx_discard_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_ERROR_CNT, - (tANI_U8) sizeof (pStats->rx_error_cnt), - (char*) &(pStats->rx_error_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BYTE_CNT, - (tANI_U8) sizeof (dStats->tx_uc_byte_cnt[0]), - (char*) &(dStats->tx_uc_byte_cnt[0]), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BYTE_CNT, - (tANI_U8) sizeof (dStats->rx_byte_cnt), - (char*) &(dStats->rx_byte_cnt), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_RATE, - (tANI_U8) sizeof (dStats->rx_rate), - (char*) &(dStats->rx_rate), - tlen); - - /* Transmit rate, in units of 500 kbit/sec */ - FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_RATE, - (tANI_U8) sizeof (aStats->tx_rate), - (char*) &(aStats->tx_rate), - tlen); - - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_UC_BYTE_CNT, - (tANI_U8) sizeof (dStats->rx_uc_byte_cnt[0]), - (char*) &(dStats->rx_uc_byte_cnt[0]), - tlen); - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_MC_BYTE_CNT, - (tANI_U8) sizeof (dStats->rx_mc_byte_cnt), - (char*) &(dStats->rx_mc_byte_cnt), - tlen); - FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BC_BYTE_CNT, - (tANI_U8) sizeof (dStats->rx_bc_byte_cnt), - (char*) &(dStats->rx_bc_byte_cnt), - tlen); - FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_UC_BYTE_CNT, - (tANI_U8) sizeof (dStats->tx_uc_byte_cnt[0]), - (char*) &(dStats->tx_uc_byte_cnt[0]), - tlen); - FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_MC_BYTE_CNT, - (tANI_U8) sizeof (dStats->tx_mc_byte_cnt), - (char*) &(dStats->tx_mc_byte_cnt), - tlen); - FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BC_BYTE_CNT, - (tANI_U8) sizeof (dStats->tx_bc_byte_cnt), - (char*) &(dStats->tx_bc_byte_cnt), - tlen); - - wrqu->data.length = tlen; - - } - - EXIT(); - - return 0; -} - - -#ifdef FEATURE_WLAN_SCAN_PNO - -/*Max Len for PNO notification*/ -#define MAX_PNO_NOTIFY_LEN 100 -void found_pref_network_cb (void *callbackContext, - tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) -{ - hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext; - union iwreq_data wrqu; - char buf[MAX_PNO_NOTIFY_LEN+1]; - - hddLog(VOS_TRACE_LEVEL_WARN, "A preferred network was found: %s with rssi: -%d", - pPrefNetworkFoundInd->ssId.ssId, pPrefNetworkFoundInd->rssi); - - // create the event - memset(&wrqu, 0, sizeof(wrqu)); - memset(buf, 0, sizeof(buf)); - - snprintf(buf, MAX_PNO_NOTIFY_LEN, "QCOM: Found preferred network: %s with RSSI of -%u", - pPrefNetworkFoundInd->ssId.ssId, - (unsigned int)pPrefNetworkFoundInd->rssi); - - wrqu.data.pointer = buf; - wrqu.data.length = strlen(buf); - - // send the event - - wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); - -} - - -/*string based input*/ -VOS_STATUS iw_set_pno(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra, int nOffset) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - /* pnoRequest is a large struct, so we make it static to avoid stack - overflow. This API is only invoked via ioctl, so it is - serialized by the kernel rtnl_lock and hence does not need to be - reentrant */ - static tSirPNOScanReq pnoRequest; - char *ptr; - v_U8_t i,j, ucParams, ucMode; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "PNO data len %d data %s", - wrqu->data.length, - extra); - - if (wrqu->data.length <= nOffset ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "PNO input is not correct"); - return VOS_STATUS_E_FAILURE; - } - - pnoRequest.enable = 0; - pnoRequest.ucNetworksCount = 0; - /*----------------------------------------------------------------------- - Input is string based and expected to be like this: - - <enabled> <netw_count> - for each network: - <ssid_len> <ssid> <authentication> <encryption> - <ch_num> <channel_list optional> <bcast_type> <rssi_threshold> - <scan_timers> <scan_time> <scan_repeat> <scan_time> <scan_repeat> - - e.g: - 1 2 4 test 0 0 3 1 6 11 2 40 5 test2 4 4 6 1 2 3 4 5 6 1 0 2 5 2 300 0 - - this translates into: - ----------------------------- - enable PNO - look for 2 networks: - test - with authentication type 0 and encryption type 0, - that can be found on 3 channels: 1 6 and 11 , - SSID bcast type is unknown (directed probe will be sent if AP not found) - and must meet -40dBm RSSI - - test2 - with auth and enrytption type 4/4 - that can be found on 6 channels 1, 2, 3, 4, 5 and 6 - bcast type is non-bcast (directed probe will be sent) - and must not meet any RSSI threshold - - scan every 5 seconds 2 times, scan every 300 seconds until stopped - -----------------------------------------------------------------------*/ - ptr = extra + nOffset; - - if (1 != sscanf(ptr,"%hhu%n", &(pnoRequest.enable), &nOffset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "PNO enable input is not valid %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - if ( 0 == pnoRequest.enable ) - { - /*Disable PNO*/ - memset(&pnoRequest, 0, sizeof(pnoRequest)); - sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest, - pAdapter->sessionId, - found_pref_network_cb, pAdapter); - return VOS_STATUS_SUCCESS; - } - - ptr += nOffset; - - if (1 != sscanf(ptr,"%hhu %n", &(pnoRequest.ucNetworksCount), &nOffset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "PNO count input not valid %s",ptr); - return VOS_STATUS_E_FAILURE; - - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "PNO enable %d networks count %d offset %d", - pnoRequest.enable, - pnoRequest.ucNetworksCount, - nOffset); - - /* Parameters checking: - ucNetworksCount has to be larger than 0*/ - if (( 0 == pnoRequest.ucNetworksCount ) || - ( pnoRequest.ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS )) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Network input is not correct"); - return VOS_STATUS_E_FAILURE; - } - - ptr += nOffset; - - for ( i = 0; i < pnoRequest.ucNetworksCount; i++ ) - { - - pnoRequest.aNetworks[i].ssId.length = 0; - - ucParams = sscanf(ptr,"%hhu %n", - &(pnoRequest.aNetworks[i].ssId.length),&nOffset); - - if (1 != ucParams) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "PNO ssid length input is not valid %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - if (( 0 == pnoRequest.aNetworks[i].ssId.length ) || - ( pnoRequest.aNetworks[i].ssId.length > 32 ) ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "SSID Len %d is not correct for network %d", - pnoRequest.aNetworks[i].ssId.length, i); - return VOS_STATUS_E_FAILURE; - } - - /*Advance to SSID*/ - ptr += nOffset; - - memcpy(pnoRequest.aNetworks[i].ssId.ssId, ptr, - pnoRequest.aNetworks[i].ssId.length); - ptr += pnoRequest.aNetworks[i].ssId.length; - - ucParams = sscanf(ptr,"%u %u %hhu %n", - &(pnoRequest.aNetworks[i].authentication), - &(pnoRequest.aNetworks[i].encryption), - &(pnoRequest.aNetworks[i].ucChannelCount), - &nOffset); - - if ( 3 != ucParams ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "Incorrect cmd %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "PNO len %d ssid 0x%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx" - "auth %d encry %d channel count %d offset %d", - pnoRequest.aNetworks[i].ssId.length, - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[0]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[4]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[8]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[12]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[16]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[20]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[24]), - *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[28]), - pnoRequest.aNetworks[i].authentication, - pnoRequest.aNetworks[i].encryption, - pnoRequest.aNetworks[i].ucChannelCount, - nOffset ); - - /*Advance to channel list*/ - ptr += nOffset; - - if (SIR_PNO_MAX_NETW_CHANNELS < pnoRequest.aNetworks[i].ucChannelCount) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "Incorrect number of channels"); - return VOS_STATUS_E_FAILURE; - } - - if ( 0 != pnoRequest.aNetworks[i].ucChannelCount) - { - for ( j = 0; j < pnoRequest.aNetworks[i].ucChannelCount; j++) - { - if (1 != sscanf(ptr,"%hhu %n", - &(pnoRequest.aNetworks[i].aChannels[j]), - &nOffset)) - { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "PNO network channel input is not valid %s",ptr); - return VOS_STATUS_E_FAILURE; - } - /*Advance to next channel number*/ - ptr += nOffset; - } - } - - if (1 != sscanf(ptr,"%u %n", - &(pnoRequest.aNetworks[i].bcastNetwType), - &nOffset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "PNO broadcast network type input is not valid %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "PNO bcastNetwType %d offset %d", - pnoRequest.aNetworks[i].bcastNetwType, - nOffset ); - - /*Advance to rssi Threshold*/ - ptr += nOffset; - - if (1 != sscanf(ptr,"%d %n", - &(pnoRequest.aNetworks[i].rssiThreshold), - &nOffset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "PNO rssi threshold input is not valid %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "PNO rssi %d offset %d", - pnoRequest.aNetworks[i].rssiThreshold, - nOffset ); - /*Advance to next network*/ - ptr += nOffset; - }/*For ucNetworkCount*/ - - ucParams = sscanf(ptr,"%hhu %n", - &(pnoRequest.scanTimers.ucScanTimersCount), - &nOffset); - - /*Read the scan timers*/ - if (( 1 == ucParams ) && ( pnoRequest.scanTimers.ucScanTimersCount > 0 )) - { - ptr += nOffset; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Scan timer count %d offset %d", - pnoRequest.scanTimers.ucScanTimersCount, - nOffset ); - - if ( SIR_PNO_MAX_SCAN_TIMERS < pnoRequest.scanTimers.ucScanTimersCount ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Incorrect cmd - too many scan timers"); - return VOS_STATUS_E_FAILURE; - } - - for ( i = 0; i < pnoRequest.scanTimers.ucScanTimersCount; i++ ) - { - ucParams = sscanf(ptr,"%u %u %n", - &(pnoRequest.scanTimers.aTimerValues[i].uTimerValue), - &( pnoRequest.scanTimers.aTimerValues[i].uTimerRepeat), - &nOffset); - - if (2 != ucParams) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Incorrect cmd - diff params then expected %d", ucParams); - return VOS_STATUS_E_FAILURE; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "PNO Timer value %d Timer repeat %d offset %d", - pnoRequest.scanTimers.aTimerValues[i].uTimerValue, - pnoRequest.scanTimers.aTimerValues[i].uTimerRepeat, - nOffset ); - - ptr += nOffset; - } - - } - else - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "No scan timers provided param count %d scan timers %d", - ucParams, pnoRequest.scanTimers.ucScanTimersCount ); - - /*Scan timers defaults to 5 minutes*/ - pnoRequest.scanTimers.ucScanTimersCount = 1; - pnoRequest.scanTimers.aTimerValues[0].uTimerValue = 60; - pnoRequest.scanTimers.aTimerValues[0].uTimerRepeat = 0; - } - - ucParams = sscanf(ptr,"%hhu %n",&(ucMode), &nOffset); - - pnoRequest.modePNO = ucMode; - /*for LA we just expose suspend option*/ - if (( 1 != ucParams )||( ucMode >= SIR_PNO_MODE_MAX )) - { - pnoRequest.modePNO = SIR_PNO_MODE_ON_SUSPEND; - } - - sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest, - pAdapter->sessionId, - found_pref_network_cb, pAdapter); - - return VOS_STATUS_SUCCESS; -}/*iw_set_pno*/ - -VOS_STATUS iw_set_rssi_filter(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra, int nOffset) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - v_U8_t rssiThreshold = 0; - v_U8_t nRead; - - nRead = sscanf(extra + nOffset,"%hhu", - &rssiThreshold); - - if ( 1 != nRead ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "Incorrect format"); - return VOS_STATUS_E_FAILURE; - } - - sme_SetRSSIFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), rssiThreshold); - return VOS_STATUS_SUCCESS; -} - - -static int iw_set_pno_priv(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Set PNO Private"); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - return iw_set_pno(dev,info,wrqu,extra,0); -} -#endif /*FEATURE_WLAN_SCAN_PNO*/ - -//Common function to SetBand -int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - tANI_U8 band = 0; - eCsrBand currBand = eCSR_BAND_MAX; - - band = ptr[WLAN_HDD_UI_SET_BAND_VALUE_OFFSET] - '0'; /*convert the band value from ascii to integer*/ - - switch(band) - { - case WLAN_HDD_UI_BAND_AUTO: - band = eCSR_BAND_ALL; - break; - case WLAN_HDD_UI_BAND_5_GHZ: - band = eCSR_BAND_5G; - break; - case WLAN_HDD_UI_BAND_2_4_GHZ: - band = eCSR_BAND_24; - break; - default: - band = eCSR_BAND_MAX; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change band to %u", - __func__, band); - - if (band == eCSR_BAND_MAX) - { - /* Received change band request with invalid band value */ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Invalid band value %u", __func__, band); - return -EIO; - } - - if ( (band == eCSR_BAND_24 && pHddCtx->cfg_ini->nBandCapability==2) || - (band == eCSR_BAND_5G && pHddCtx->cfg_ini->nBandCapability==1) || - (band == eCSR_BAND_ALL && pHddCtx->cfg_ini->nBandCapability!=0)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: band value %u violate INI settings %u", __func__, - band, pHddCtx->cfg_ini->nBandCapability); - return -EIO; - } - - if (eHAL_STATUS_SUCCESS != sme_GetFreqBand(hHal, &currBand)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: Failed to get current band config", - __func__); - return -EIO; - } - - if (currBand != band) - { - /* Change band request received. - * Abort pending scan requests, flush the existing scan results, - * and change the band capability - */ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: Current band value = %u, new setting %u ", - __func__, currBand, band); - - if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) - { - hdd_station_ctx_t *pHddStaCtx = &(pAdapter)->sessionCtx.station; - eHalStatus status = eHAL_STATUS_SUCCESS; - long lrc; - - /* STA already connected on current band, So issue disconnect first, - * then change the band*/ - - hddLog(VOS_TRACE_LEVEL_INFO, - "%s STA connected in band %u, Changing band to %u, Issuing Disconnect", - __func__, csrGetCurrentBand(hHal), band); - - pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; - INIT_COMPLETION(pAdapter->disconnect_comp_var); - - status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); - - if ( eHAL_STATUS_SUCCESS != status) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s csrRoamDisconnect failure, returned %d \n", - __func__, (int)status ); - return -EINVAL; - } - - lrc = wait_for_completion_interruptible_timeout( - &pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - - if (lrc <= 0) { - - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while waiting for csrRoamDisconnect ", - __func__, (0 == lrc) ? "Timeout" : "Interrupt"); - - return (0 == lrc) ? -ETIMEDOUT : -EINTR; - } - } - - hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId); - sme_ScanFlushResult(hHal, pAdapter->sessionId); -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - sme_UpdateBgScanConfigIniChannelList(hHal, (eCsrBand) band); -#endif - if (eHAL_STATUS_SUCCESS != sme_SetFreqBand(hHal, (eCsrBand)band)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: failed to set the band value to %u ", - __func__, band); - return -EINVAL; - } - wlan_hdd_cfg80211_update_band(pHddCtx->wiphy, (eCsrBand)band); - } - return 0; -} - -static int iw_set_band_config(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tANI_U8 *ptr = extra; - int ret = 0; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: ", __func__); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if (memcmp(ptr, "SETBAND ", 8) == 0) - { - /* Change band request received */ - ret = hdd_setBand_helper(dev, ptr); - return ret; - - } - return 0; -} - -static int iw_set_power_params_priv(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Set power params Private"); - return iw_set_power_params(dev,info,wrqu,extra,0); -} - - - -/*string based input*/ -VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra, int nOffset) -{ - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tSirSetPowerParamsReq powerRequest; - char *ptr; - v_U8_t ucType; - v_U32_t uTotalSize, uValue; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Power Params data len %d data %s", - wrqu->data.length, - extra); - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; - } - - if (wrqu->data.length <= nOffset ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "set power param input is not correct"); - return VOS_STATUS_E_FAILURE; - } - - uTotalSize = wrqu->data.length - nOffset; - - /*----------------------------------------------------------------------- - Input is string based and expected to be like this: - - <param_type> <param_value> <param_type> <param_value> ... - - e.g: - 1 2 2 3 3 0 4 1 5 1 - - e.g. setting just a few: - 1 2 4 1 - - parameter types: - ----------------------------- - 1 - Ignore DTIM - 2 - Listen Interval - 3 - Broadcast Multicas Filter - 4 - Beacon Early Termination - 5 - Beacon Early Termination Interval - -----------------------------------------------------------------------*/ - powerRequest.uIgnoreDTIM = SIR_NOCHANGE_POWER_VALUE; - powerRequest.uListenInterval = SIR_NOCHANGE_POWER_VALUE; - powerRequest.uBcastMcastFilter = SIR_NOCHANGE_POWER_VALUE; - powerRequest.uEnableBET = SIR_NOCHANGE_POWER_VALUE; - powerRequest.uBETInterval = SIR_NOCHANGE_POWER_VALUE; - - ptr = extra + nOffset; - - while ( uTotalSize ) - { - if (1 != sscanf(ptr,"%hhu %n", &(ucType), &nOffset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid input parameter type %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - uTotalSize -= nOffset; - - if (!uTotalSize) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid input parameter type : %d with no value at offset %d", - ucType, nOffset); - return VOS_STATUS_E_FAILURE; - } - - ptr += nOffset; - - if (1 != sscanf(ptr,"%u %n", &(uValue), &nOffset)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid input parameter value %s",ptr); - return VOS_STATUS_E_FAILURE; - } - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Power request parameter %d value %d offset %d", - ucType, uValue, nOffset); - - switch (ucType) - { - case eSIR_IGNORE_DTIM: - powerRequest.uIgnoreDTIM = uValue; - break; - case eSIR_LISTEN_INTERVAL: - powerRequest.uListenInterval = uValue; - break; - case eSIR_MCAST_BCAST_FILTER: - powerRequest.uBcastMcastFilter = uValue; - break; - case eSIR_ENABLE_BET: - powerRequest.uEnableBET = uValue; - break; - case eSIR_BET_INTERVAL: - powerRequest.uBETInterval = uValue; - break; - default: - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid input parameter type : %d with value: %d at offset %d", - ucType, uValue, nOffset); - return VOS_STATUS_E_FAILURE; - } - - uTotalSize -= nOffset; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Power request parameter %d Total size", - uTotalSize); - ptr += nOffset; - /* This is added for dynamic Tele LI enable (0xF1) /disable (0xF0)*/ - if(!(uTotalSize - nOffset) && - (powerRequest.uListenInterval != SIR_NOCHANGE_POWER_VALUE)) - { - uTotalSize = 0; - } - - }/*Go for as long as we have a valid string*/ - - /* put the device into full power*/ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); - - /* Apply the power save params*/ - sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); - - /* put the device back to power save*/ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); - - return VOS_STATUS_SUCCESS; -}/*iw_set_power_params*/ - - -// Define the Wireless Extensions to the Linux Network Device structure -// A number of these routines are NULL (meaning they are not implemented.) - -static const iw_handler we_handler[] = -{ - (iw_handler) iw_set_commit, /* SIOCSIWCOMMIT */ - (iw_handler) iw_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) iw_set_freq, /* SIOCSIWFREQ */ - (iw_handler) iw_get_freq, /* SIOCGIWFREQ */ - (iw_handler) iw_set_mode, /* SIOCSIWMODE */ - (iw_handler) iw_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) iw_get_range, /* SIOCGIWRANGE */ - (iw_handler) iw_set_priv, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) iw_set_ap_address, /* SIOCSIWAP */ - (iw_handler) iw_get_ap_address, /* SIOCGIWAP */ - (iw_handler) iw_set_mlme, /* SIOCSIWMLME */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) iw_set_scan, /* SIOCSIWSCAN */ - (iw_handler) iw_get_scan, /* SIOCGIWSCAN */ - (iw_handler) iw_set_essid, /* SIOCSIWESSID */ - (iw_handler) iw_get_essid, /* SIOCGIWESSID */ - (iw_handler) iw_set_nick, /* SIOCSIWNICKN */ - (iw_handler) iw_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) iw_set_bitrate, /* SIOCSIWRATE */ - (iw_handler) iw_get_bitrate, /* SIOCGIWRATE */ - (iw_handler) iw_set_rts_threshold,/* SIOCSIWRTS */ - (iw_handler) iw_get_rts_threshold,/* SIOCGIWRTS */ - (iw_handler) iw_set_frag_threshold, /* SIOCSIWFRAG */ - (iw_handler) iw_get_frag_threshold, /* SIOCGIWFRAG */ - (iw_handler) iw_set_tx_power, /* SIOCSIWTXPOW */ - (iw_handler) iw_get_tx_power, /* SIOCGIWTXPOW */ - (iw_handler) iw_set_retry, /* SIOCSIWRETRY */ - (iw_handler) iw_get_retry, /* SIOCGIWRETRY */ - (iw_handler) iw_set_encode, /* SIOCSIWENCODE */ - (iw_handler) iw_get_encode, /* SIOCGIWENCODE */ - (iw_handler) iw_set_power_mode, /* SIOCSIWPOWER */ - (iw_handler) iw_get_power_mode, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) iw_set_genie, /* SIOCSIWGENIE */ - (iw_handler) iw_get_genie, /* SIOCGIWGENIE */ - (iw_handler) iw_set_auth, /* SIOCSIWAUTH */ - (iw_handler) iw_get_auth, /* SIOCGIWAUTH */ - (iw_handler) iw_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) iw_get_encodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; - -static const iw_handler we_private[] = { - - [WLAN_PRIV_SET_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_setint_getnone, //set priv ioctl - [WLAN_PRIV_SET_NONE_GET_INT - SIOCIWFIRSTPRIV] = iw_setnone_getint, //get priv ioctl - [WLAN_PRIV_SET_CHAR_GET_NONE - SIOCIWFIRSTPRIV] = iw_setchar_getnone, //get priv ioctl - [WLAN_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone, - [WLAN_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_get_char_setnone, - [WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, //action priv ioctl - [WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_var_ints_getnone, - [WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec, - [WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec, - [WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec, -#ifdef FEATURE_OEM_DATA_SUPPORT - [WLAN_PRIV_SET_OEM_DATA_REQ - SIOCIWFIRSTPRIV] = iw_set_oem_data_req, //oem data req Specifc - [WLAN_PRIV_GET_OEM_DATA_RSP - SIOCIWFIRSTPRIV] = iw_get_oem_data_rsp, //oem data req Specifc -#endif - -#ifdef FEATURE_WLAN_WAPI - [WLAN_PRIV_SET_WAPI_MODE - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_mode, - [WLAN_PRIV_GET_WAPI_MODE - SIOCIWFIRSTPRIV] = iw_qcom_get_wapi_mode, - [WLAN_PRIV_SET_WAPI_ASSOC_INFO - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_assoc_info, - [WLAN_PRIV_SET_WAPI_KEY - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_key, - [WLAN_PRIV_SET_WAPI_BKID - SIOCIWFIRSTPRIV] = iw_qcom_set_wapi_bkid, - [WLAN_PRIV_GET_WAPI_BKID - SIOCIWFIRSTPRIV] = iw_qcom_get_wapi_bkid, -#endif /* FEATURE_WLAN_WAPI */ -#ifdef WLAN_FEATURE_VOWIFI_11R - [WLAN_PRIV_SET_FTIES - SIOCIWFIRSTPRIV] = iw_set_fties, -#endif - [WLAN_PRIV_SET_HOST_OFFLOAD - SIOCIWFIRSTPRIV] = iw_set_host_offload, - [WLAN_GET_WLAN_STATISTICS - SIOCIWFIRSTPRIV] = iw_get_statistics, - [WLAN_SET_KEEPALIVE_PARAMS - SIOCIWFIRSTPRIV] = iw_set_keepalive_params -#ifdef WLAN_FEATURE_PACKET_FILTERING - , - [WLAN_SET_PACKET_FILTER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_packet_filter_params -#endif -#ifdef FEATURE_WLAN_SCAN_PNO - , - [WLAN_SET_PNO - SIOCIWFIRSTPRIV] = iw_set_pno_priv -#endif - , - [WLAN_SET_BAND_CONFIG - SIOCIWFIRSTPRIV] = iw_set_band_config, - [WLAN_PRIV_SET_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_set_dynamic_mcbc_filter, - [WLAN_PRIV_CLEAR_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_clear_dynamic_mcbc_filter, - [WLAN_SET_POWER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_power_params_priv, -#ifdef FEATURE_OEM_DATA_SUPPORT -#ifdef QCA_WIFI_2_0 - [WLAN_PRIV_GET_OEM_DATA_CAP - SIOCIWFIRSTPRIV] = iw_get_oem_data_cap, -#endif -#endif - [WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed, -}; - -/*Maximum command length can be only 15 */ -static const struct iw_priv_args we_private_args[] = { - - { WE_ENABLE_STRICT_FCC_REG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setStrictFCCreg" }, - - /* handlers for main ioctl */ - { WLAN_PRIV_SET_INT_GET_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "" }, - - /* handlers for sub-ioctl */ - { WE_SET_11D_STATE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "set11Dstate" }, - - { WE_WOWL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "wowl" }, - - { WE_SET_POWER, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setPower" }, - - { WE_SET_MAX_ASSOC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setMaxAssoc" }, - - { WE_SET_SAP_AUTO_CHANNEL_SELECTION, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setAutoChannel" }, - - { WE_SET_DATA_INACTIVITY_TO, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "inactivityTO" }, - - { WE_SET_MAX_TX_POWER, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setMaxTxPower" }, - - { WE_SET_MAX_TX_POWER_2_4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setTxMaxPower2G" }, - - { WE_SET_MAX_TX_POWER_5_0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setTxMaxPower5G" }, - - /* SAP has TxMax whereas STA has MaxTx, adding TxMax for STA - * as well to keep same syntax as in SAP. Now onwards, STA - * will support both */ - { WE_SET_MAX_TX_POWER, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setTxMaxPower" }, - - /* set Higher DTIM Transition (DTIM1 to DTIM3) - * 1 = enable and 0 = disable */ - { - WE_SET_HIGHER_DTIM_TRANSITION, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setHDtimTransn" }, - - { WE_SET_TM_LEVEL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setTmLevel" }, - -#ifdef QCA_WIFI_2_0 - { WE_SET_PHYMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "setphymode" }, - - { WE_SET_NSS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "nss" }, - - { WE_SET_LDPC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "ldpc" }, - - { WE_SET_TX_STBC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "tx_stbc" }, - - { WE_SET_RX_STBC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "rx_stbc" }, - - { WE_SET_SHORT_GI, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "shortgi" }, - - { WE_SET_RTSCTS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "enablertscts" }, - - { WE_SET_CHWIDTH, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "chwidth" }, - - { WE_SET_ANI_EN_DIS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "anienable" }, - - { WE_SET_ANI_POLL_PERIOD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "aniplen" }, - - { WE_SET_ANI_LISTEN_PERIOD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "anilislen" }, - - { WE_SET_ANI_OFDM_LEVEL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "aniofdmlvl" }, - - { WE_SET_ANI_CCK_LEVEL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "aniccklvl" }, - - { WE_SET_DYNAMIC_BW, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "cwmenable" }, - - { WE_SET_TX_CHAINMASK, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "txchainmask" }, - - { WE_SET_RX_CHAINMASK, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "rxchainmask" }, - - { WE_SET_11N_RATE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "set11NRates" }, - - { WE_SET_VHT_RATE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "set11ACRates" }, - - { WE_SET_AMPDU, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "ampdu" }, - - { WE_SET_AMSDU, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "amsdu" }, - - { WE_SET_TXPOW_2G, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "txpow2g" }, - - { WE_SET_TXPOW_5G, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "txpow5g" }, - - { WE_SET_POWER_GATING, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "pwrgating" }, - - /* Sub-cmds DBGLOG specific commands */ - { WE_DBGLOG_LOG_LEVEL , - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_loglevel" }, - - { WE_DBGLOG_VAP_ENABLE , - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_vapon" }, - - { WE_DBGLOG_VAP_DISABLE , - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_vapoff" }, - - { WE_DBGLOG_MODULE_ENABLE , - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_modon" }, - - { WE_DBGLOG_MODULE_DISABLE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_modoff" }, - - { WE_DBGLOG_MOD_LOG_LEVEL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_mod_loglevel" }, - - { WE_DBGLOG_TYPE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_type" }, - { WE_DBGLOG_REPORT_ENABLE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "dl_report" }, - - { WE_SET_TXRX_FWSTATS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "txrx_fw_stats" }, - - { WE_TXRX_FWSTATS_RESET, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "txrx_fw_st_rst" }, - - { WE_PPS_PAID_MATCH, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "paid_match" }, - - - { WE_PPS_GID_MATCH, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "gid_match" }, - - - { WE_PPS_EARLY_TIM_CLEAR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "tim_clear" }, - - - { WE_PPS_EARLY_DTIM_CLEAR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "dtim_clear" }, - - - { WE_PPS_EOF_PAD_DELIM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "eof_delim" }, - - - { WE_PPS_MACADDR_MISMATCH, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "mac_match" }, - - - { WE_PPS_DELIM_CRC_FAIL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "delim_fail" }, - - - { WE_PPS_GID_NSTS_ZERO, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "nsts_zero" }, - - - { WE_PPS_RSSI_CHECK, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "rssi_chk" }, -#endif - - { WLAN_PRIV_SET_NONE_GET_INT, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "" }, - - /* handlers for sub-ioctl */ - { WE_GET_11D_STATE, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get11Dstate" }, - - { WE_IBSS_STATUS, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getAdhocStatus" }, - - { WE_PMC_STATE, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "pmcState" }, - - { WE_GET_WLAN_DBG, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getwlandbg" }, - - { WE_MODULE_DOWN_IND, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "moduleDownInd" }, - - { WE_GET_MAX_ASSOC, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getMaxAssoc" }, - - { WE_GET_WDI_DBG, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getwdidbg" }, - - { WE_GET_SAP_AUTO_CHANNEL_SELECTION, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getAutoChannel" }, - - { WE_GET_CONCURRENCY_MODE, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getconcurrency" }, - -#ifdef QCA_WIFI_2_0 - { WE_GET_NSS, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_nss" }, - - { WE_GET_LDPC, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_ldpc" }, - - { WE_GET_TX_STBC, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_tx_stbc" }, - - { WE_GET_RX_STBC, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_rx_stbc" }, - - { WE_GET_SHORT_GI, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_shortgi" }, - - { WE_GET_RTSCTS, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_rtscts" }, - - { WE_GET_CHWIDTH, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_chwidth" }, - - { WE_GET_ANI_EN_DIS, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_anienable" }, - - { WE_GET_ANI_POLL_PERIOD, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_aniplen" }, - - { WE_GET_ANI_LISTEN_PERIOD, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_anilislen" }, - - { WE_GET_ANI_OFDM_LEVEL, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_aniofdmlvl" }, - - { WE_GET_ANI_CCK_LEVEL, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_aniccklvl" }, - - { WE_GET_DYNAMIC_BW, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_cwmenable" }, - - { WE_GET_TX_CHAINMASK, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_txchainmask" }, - - { WE_GET_RX_CHAINMASK, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_rxchainmask" }, - - { WE_GET_11N_RATE, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_11nrate" }, - - { WE_GET_AMPDU, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_ampdu" }, - - { WE_GET_AMSDU, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_amsdu" }, - - { WE_GET_TXPOW_2G, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_txpow2g" }, - - { WE_GET_TXPOW_5G, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_txpow5g" }, - - { WE_GET_POWER_GATING, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_pwrgating" }, - - { WE_GET_PPS_PAID_MATCH, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_paid_match"}, - - - { WE_GET_PPS_GID_MATCH, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_gid_match"}, - - - { WE_GET_PPS_EARLY_TIM_CLEAR, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_tim_clear"}, - - - { WE_GET_PPS_EARLY_DTIM_CLEAR, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_dtim_clear"}, - - - { WE_GET_PPS_EOF_PAD_DELIM, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_eof_delim"}, - - - { WE_GET_PPS_MACADDR_MISMATCH, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_mac_match"}, - - - { WE_GET_PPS_DELIM_CRC_FAIL, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_delim_fail"}, - - - { WE_GET_PPS_GID_NSTS_ZERO, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_nsts_zero"}, - - - { WE_GET_PPS_RSSI_CHECK, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_rssi_chk"}, -#endif - - /* handlers for main ioctl */ - { WLAN_PRIV_SET_CHAR_GET_NONE, - IW_PRIV_TYPE_CHAR| 512, - 0, - "" }, - - /* handlers for sub-ioctl */ - { WE_WOWL_ADD_PTRN, - IW_PRIV_TYPE_CHAR| 512, - 0, - "wowlAddPtrn" }, - - { WE_WOWL_DEL_PTRN, - IW_PRIV_TYPE_CHAR| 512, - 0, - "wowlDelPtrn" }, - -#if defined WLAN_FEATURE_VOWIFI - /* handlers for sub-ioctl */ - { WE_NEIGHBOR_REPORT_REQUEST, - IW_PRIV_TYPE_CHAR | 512, - 0, - "neighbor" }, -#endif - { WE_SET_AP_WPS_IE, - IW_PRIV_TYPE_CHAR| 512, - 0, - "set_ap_wps_ie" }, - - { WE_SET_CONFIG, - IW_PRIV_TYPE_CHAR| 512, - 0, - "setConfig" }, - - /* handlers for main ioctl */ - { WLAN_PRIV_SET_THREE_INT_GET_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, - 0, - "" }, - - /* handlers for sub-ioctl */ - { WE_SET_WLAN_DBG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, - 0, - "setwlandbg" }, - - { WE_SET_WDI_DBG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, - 0, - "setwdidbg" }, - - { WE_SET_SAP_CHANNELS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, - 0, - "setsapchannels" }, - - /* handlers for main ioctl */ - { WLAN_PRIV_GET_CHAR_SET_NONE, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "" }, - - /* handlers for sub-ioctl */ - { WE_WLAN_VERSION, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "version" }, - { WE_GET_STATS, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getStats" }, - { WE_GET_STATES, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getHostStates" }, - { WE_GET_CFG, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getConfig" }, -#ifdef WLAN_FEATURE_11AC - { WE_GET_RSSI, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getRSSI" }, -#endif -#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) - { WE_GET_ROAM_RSSI, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getRoamRSSI" }, -#endif - { WE_GET_WMM_STATUS, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getWmmStatus" }, - { - WE_GET_CHANNEL_LIST, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getChannelList" }, -#ifdef FEATURE_WLAN_TDLS - { - WE_GET_TDLS_PEERS, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getTdlsPeers" }, -#endif -#ifdef WLAN_FEATURE_11W - { - WE_GET_11W_INFO, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getPMFInfo" }, -#endif -#ifdef FEATURE_CESIUM_PROPRIETARY - { - WE_GET_IBSS_STA_INFO, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getIbssSTAs" }, -#endif -#ifdef QCA_WIFI_2_0 - { WE_GET_PHYMODE, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getphymode" }, -#endif - - /* handlers for main ioctl */ - { WLAN_PRIV_SET_NONE_GET_NONE, - 0, - 0, - "" }, - - /* handlers for sub-ioctl */ - { WE_CLEAR_STATS, - 0, - 0, - "clearStats" }, - { WE_INIT_AP, - 0, - 0, - "initAP" }, -#ifdef FEATURE_CESIUM_PROPRIETARY - { - WE_IBSS_GET_PEER_INFO_ALL, - 0, - 0, - "ibssPeerInfoAll" }, -#endif - { WE_STOP_AP, - 0, - 0, - "exitAP" }, - { WE_ENABLE_AMP, - 0, - 0, - "enableAMP" }, - { WE_DISABLE_AMP, - 0, - 0, - "disableAMP" }, - { WE_ENABLE_DXE_STALL_DETECT, - 0, - 0, - "dxeStallDetect" }, - { WE_DISPLAY_DXE_SNAP_SHOT, - 0, - 0, - "dxeSnapshot" }, - { WE_DISPLAY_DATAPATH_SNAP_SHOT, - 0, - 0, - "dataSnapshot"}, - { - WE_SET_REASSOC_TRIGGER, - 0, - 0, - "reassoc" }, -#ifdef QCA_WIFI_2_0 - { WE_DUMP_AGC_START, - 0, - 0, - "dump_agc_start" }, - - { WE_DUMP_AGC, - 0, - 0, - "dump_agc" }, - - { WE_DUMP_CHANINFO_START, - 0, - 0, - "dump_chninfo_en" }, - - { WE_DUMP_CHANINFO, - 0, - 0, - "dump_chninfo" }, - - { WE_DUMP_WATCHDOG, - 0, - 0, - "dump_watchdog" }, -#ifdef DEBUG - { WE_SET_FW_CRASH_INJECT, - 0, - 0, - "crash_inject" }, -#endif -#endif - /* handlers for main ioctl */ - { WLAN_PRIV_SET_VAR_INT_GET_NONE, - IW_PRIV_TYPE_INT | MAX_VAR_ARGS, - 0, - "" }, - - /* handlers for sub-ioctl */ - { WE_LOG_DUMP_CMD, - IW_PRIV_TYPE_INT | MAX_VAR_ARGS, - 0, - "dump" }, -#ifdef FEATURE_CESIUM_PROPRIETARY - { WE_IBSS_GET_PEER_INFO, - IW_PRIV_TYPE_INT | MAX_VAR_ARGS, - 0, - "ibssPeerInfo" }, -#endif - /* handlers for sub ioctl */ - { - WE_MCC_CONFIG_CREDENTIAL, - IW_PRIV_TYPE_INT | MAX_VAR_ARGS, - 0, - "setMccCrdnl" }, - - /* handlers for sub ioctl */ - { - WE_MCC_CONFIG_PARAMS, - IW_PRIV_TYPE_INT | MAX_VAR_ARGS, - 0, - "setMccConfig" }, - -#ifdef FEATURE_WLAN_TDLS - /* handlers for sub ioctl */ - { - WE_TDLS_CONFIG_PARAMS, - IW_PRIV_TYPE_INT | MAX_VAR_ARGS, - 0, - "setTdlsConfig" }, -#endif - - /* handlers for main ioctl */ - { WLAN_PRIV_ADD_TSPEC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | HDD_WLAN_WMM_PARAM_COUNT, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "addTspec" }, - - /* handlers for main ioctl */ - { WLAN_PRIV_DEL_TSPEC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "delTspec" }, - - /* handlers for main ioctl */ - { WLAN_PRIV_GET_TSPEC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getTspec" }, - -#ifdef FEATURE_OEM_DATA_SUPPORT - /* handlers for main ioctl - OEM DATA */ - { - WLAN_PRIV_SET_OEM_DATA_REQ, - IW_PRIV_TYPE_BYTE | sizeof(struct iw_oem_data_req) | IW_PRIV_SIZE_FIXED, - 0, - "set_oem_data_req" }, - - /* handlers for main ioctl - OEM DATA */ - { - WLAN_PRIV_GET_OEM_DATA_RSP, - 0, - IW_PRIV_TYPE_BYTE | MAX_OEM_DATA_RSP_LEN, - "get_oem_data_rsp" }, -#endif - -#ifdef FEATURE_WLAN_WAPI - /* handlers for main ioctl SET_WAPI_MODE */ - { WLAN_PRIV_SET_WAPI_MODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "SET_WAPI_MODE" }, - - /* handlers for main ioctl GET_WAPI_MODE */ - { WLAN_PRIV_GET_WAPI_MODE, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "GET_WAPI_MODE" }, - - /* handlers for main ioctl SET_ASSOC_INFO */ - { WLAN_PRIV_SET_WAPI_ASSOC_INFO, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 400, - 0, - "SET_WAPI_ASSOC" }, - - /* handlers for main ioctl SET_WAPI_KEY */ - { WLAN_PRIV_SET_WAPI_KEY, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 71, - 0, - "SET_WAPI_KEY" }, - - /* handlers for main ioctl SET_WAPI_BKID */ - { WLAN_PRIV_SET_WAPI_BKID, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 24, - 0, - "SET_WAPI_BKID" }, - - /* handlers for main ioctl GET_WAPI_BKID */ - { WLAN_PRIV_GET_WAPI_BKID, - 0, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 24, - "GET_WAPI_BKID" }, -#endif /* FEATURE_WLAN_WAPI */ - - /* handlers for main ioctl - host offload */ - { - WLAN_PRIV_SET_HOST_OFFLOAD, - IW_PRIV_TYPE_BYTE | sizeof(tHostOffloadRequest), - 0, - "setHostOffload" }, - - { - WLAN_GET_WLAN_STATISTICS, - 0, - IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN, - "getWlanStats" }, - - { - WLAN_SET_KEEPALIVE_PARAMS, - IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN, - 0, - "setKeepAlive" }, -#ifdef WLAN_FEATURE_PACKET_FILTERING - { - WLAN_SET_PACKET_FILTER_PARAMS, - IW_PRIV_TYPE_BYTE | sizeof(tPacketFilterCfg), - 0, - "setPktFilter" }, -#endif -#ifdef FEATURE_WLAN_SCAN_PNO - { - WLAN_SET_PNO, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - 0, - "setpno" }, -#endif - { - WLAN_SET_BAND_CONFIG, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - 0, - "SETBAND" }, - /* handlers for dynamic MC BC ioctl */ - { - WLAN_PRIV_SET_MCBC_FILTER, - IW_PRIV_TYPE_BYTE | sizeof(tRcvFltMcAddrList), - 0, - "setMCBCFilter" }, - { - WLAN_PRIV_CLEAR_MCBC_FILTER, - 0, - 0, - "clearMCBCFilter" }, - { - WLAN_SET_POWER_PARAMS, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - 0, - "setpowerparams" }, -#ifdef FEATURE_OEM_DATA_SUPPORT -#ifdef QCA_WIFI_2_0 - { - WLAN_PRIV_GET_OEM_DATA_CAP, - 0, - IW_PRIV_TYPE_BYTE | sizeof(struct iw_oem_data_cap), - "getOemDataCap" }, -#endif -#endif - { - WLAN_GET_LINK_SPEED, - IW_PRIV_TYPE_CHAR | 18, - IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, -}; - - - -const struct iw_handler_def we_handler_def = { - .num_standard = sizeof(we_handler) / sizeof(we_handler[0]), - .num_private = sizeof(we_private) / sizeof(we_private[0]), - .num_private_args = sizeof(we_private_args) / sizeof(we_private_args[0]), - - .standard = (iw_handler *)we_handler, - .private = (iw_handler *)we_private, - .private_args = we_private_args, - .get_wireless_stats = get_wireless_stats, -}; - -int hdd_validate_mcc_config(hdd_adapter_t *pAdapter, v_UINT_t staId, v_UINT_t arg1, v_UINT_t arg2, v_UINT_t arg3) -{ - v_U32_t cmd = 288; //Command to RIVA - hdd_context_t *pHddCtx = NULL; - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - /* - *configMccParam : specify the bit which needs to be modified - *allowed to update based on wlan_qcom_cfg.ini - * configuration - * Bit 0 : SCHEDULE_TIME_SLICE MIN : 5 MAX : 20 - * Bit 1 : MAX_NULL_SEND_TIME MIN : 1 MAX : 10 - * Bit 2 : TX_EARLY_STOP_TIME MIN : 1 MAX : 10 - * Bit 3 : RX_DRAIN_TIME MIN : 1 MAX : 10 - * Bit 4 : CHANNEL_SWITCH_TIME MIN : 1 MAX : 20 - * Bit 5 : MIN_CHANNEL_TIME MIN : 5 MAX : 20 - * Bit 6 : PARK_BEFORE_TBTT MIN : 1 MAX : 5 - * Bit 7 : MIN_AFTER_DTIM MIN : 5 MAX : 15 - * Bit 8 : TOO_CLOSE_MARGIN MIN : 1 MAX : 3 - * Bit 9 : Reserved - */ - switch (arg1) - { - //Update MCC SCHEDULE_TIME_SLICE parameter - case MCC_SCHEDULE_TIME_SLICE_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0001) - { - if((arg2 >= 5) && (arg2 <= 20)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC MAX_NULL_SEND_TIME parameter - case MCC_MAX_NULL_SEND_TIME_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0002) - { - if((arg2 >= 1) && (arg2 <= 10)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC TX_EARLY_STOP_TIME parameter - case MCC_TX_EARLY_STOP_TIME_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0004) - { - if((arg2 >= 1) && (arg2 <= 10)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC RX_DRAIN_TIME parameter - case MCC_RX_DRAIN_TIME_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0008) - { - if((arg2 >= 1) && (arg2 <= 10)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC CHANNEL_SWITCH_TIME parameter - case MCC_CHANNEL_SWITCH_TIME_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0010) - { - if((arg2 >= 1) && (arg2 <= 20)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC MIN_CHANNEL_TIME parameter - case MCC_MIN_CHANNEL_TIME_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0020) - { - if((arg2 >= 5) && (arg2 <= 20)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC PARK_BEFORE_TBTT parameter - case MCC_PARK_BEFORE_TBTT_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0040) - { - if((arg2 >= 1) && (arg2 <= 5)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC MIN_AFTER_DTIM parameter - case MCC_MIN_AFTER_DTIM_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0080) - { - if((arg2 >= 5) && (arg2 <= 15)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - //Update MCC TOO_CLOSE_MARGIN parameter - case MCC_TOO_CLOSE_MARGIN_CFG_PARAM : - if( pHddCtx->cfg_ini->configMccParam & 0x0100) - { - if((arg2 >= 1) && (arg2 <= 3)) - { - logPrintf(hHal, cmd, staId, arg1, arg2, arg3); - } - else - { - hddLog(LOGE, "%s : Enter a valid MCC configuration value\n",__FUNCTION__); - return 0; - } - } - break; - - default : - hddLog(LOGE, "%s : Uknown / Not allowed to configure parameter : %d\n", - __FUNCTION__,arg1); - break; - } - return 0; -} - -int hdd_set_wext(hdd_adapter_t *pAdapter) -{ - hdd_wext_state_t *pwextBuf; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - - pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - - // Now configure the roaming profile links. To SSID and bssid. - pwextBuf->roamProfile.SSIDs.numOfSSIDs = 0; - pwextBuf->roamProfile.SSIDs.SSIDList = &pHddStaCtx->conn_info.SSID; - - pwextBuf->roamProfile.BSSIDs.numOfBSSIDs = 0; - pwextBuf->roamProfile.BSSIDs.bssid = &pHddStaCtx->conn_info.bssId; - - /*Set the numOfChannels to zero to scan all the channels*/ - pwextBuf->roamProfile.ChannelInfo.numOfChannels = 0; - pwextBuf->roamProfile.ChannelInfo.ChannelList = NULL; - - /* Default is no encryption */ - pwextBuf->roamProfile.EncryptionType.numEntries = 1; - pwextBuf->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - - pwextBuf->roamProfile.mcEncryptionType.numEntries = 1; - pwextBuf->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; - - pwextBuf->roamProfile.BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; - - /* Default is no authentication */ - pwextBuf->roamProfile.AuthType.numEntries = 1; - pwextBuf->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; - - pwextBuf->roamProfile.phyMode = eCSR_DOT11_MODE_TAURUS; - pwextBuf->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; - - /*Set the default scan mode*/ - pAdapter->scan_info.scan_mode = eSIR_ACTIVE_SCAN; - - hdd_clearRoamProfileIe(pAdapter); - - return VOS_STATUS_SUCCESS; - - } - -int hdd_register_wext(struct net_device *dev) - { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - VOS_STATUS status; - - ENTER(); - - // Zero the memory. This zeros the profile structure. - memset(pwextBuf, 0,sizeof(hdd_wext_state_t)); - - init_completion(&(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->completion_var); - - - status = hdd_set_wext(pAdapter); - - if(!VOS_IS_STATUS_SUCCESS(status)) { - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: hdd_set_wext failed!!\n")); - return eHAL_STATUS_FAILURE; - } - - if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->vosevent))) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos event init failed!!\n")); - return eHAL_STATUS_FAILURE; - } - - if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->scanevent))) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD scan event init failed!!\n")); - return eHAL_STATUS_FAILURE; - } - - // Register as a wireless device - dev->wireless_handlers = (struct iw_handler_def *)&we_handler_def; - - EXIT(); - return 0; -} - -int hdd_UnregisterWext(struct net_device *dev) -{ -#if 0 - hdd_wext_state_t *wextBuf; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - - ENTER(); - // Set up the pointer to the Wireless Extensions state structure - wextBuf = pAdapter->pWextState; - - // De-allocate the Wireless Extensions state structure - kfree(wextBuf); - - // Clear out the pointer to the Wireless Extensions state structure - pAdapter->pWextState = NULL; - - EXIT(); -#endif - dev->wireless_handlers = NULL; - return 0; -} - - diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 9892d527c5dd..7c2922b45d67 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -119,22 +119,6 @@ static void cbNotifySetRoamScanNProbes(hdd_context_t *pHddCtx, unsigned long Not static void cbNotifySetRoamScanHomeAwayTime(hdd_context_t *pHddCtx, unsigned long NotifyId) { - tANI_U16 scanChannelMaxTime = 0; - - /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)), - * where RFS is the RF Switching time. It is twice RFS to consider the - * time to go off channel and return to the home channel. */ - - scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal)); - if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)" - " Hence enforcing home away time to disable (0)", - __func__, pHddCtx->cfg_ini->nRoamScanHomeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))); - pHddCtx->cfg_ini->nRoamScanHomeAwayTime = 0; - } - sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nRoamScanHomeAwayTime, eANI_BOOLEAN_TRUE); } #endif @@ -207,22 +191,6 @@ static void cbNotifySetNeighborScanMinChanTime(hdd_context_t *pHddCtx, unsigned static void cbNotifySetNeighborScanMaxChanTime(hdd_context_t *pHddCtx, unsigned long NotifyId) { - tANI_U16 homeAwayTime = 0; - - /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)), - * where RFS is the RF Switching time. It is twice RFS to consider the - * time to go off channel and return to the home channel. */ - homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal)); - if (homeAwayTime < (pHddCtx->cfg_ini->nNeighborScanMaxChanTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)" - " Hence enforcing home away time to disable (0)", - __func__, homeAwayTime, (pHddCtx->cfg_ini->nNeighborScanMaxChanTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))); - homeAwayTime = 0; - pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime; - sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE); - } sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nNeighborScanMaxChanTime); } #endif @@ -2450,6 +2418,13 @@ REG_VARIABLE( CFG_HT_SMPS_CAP_FEATURE, WLAN_PARAM_Integer, CFG_HT_SMPS_CAP_FEATURE_MIN, CFG_HT_SMPS_CAP_FEATURE_MAX ), +REG_VARIABLE( CFG_DISABLE_DFS_CH_SWITCH, WLAN_PARAM_Integer, + hdd_config_t, disableDFSChSwitch, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_DFS_CH_SWITCH_DEFAULT, + CFG_DISABLE_DFS_CH_SWITCH_MIN, + CFG_DISABLE_DFS_CH_SWITCH_MAX ), + REG_VARIABLE( CFG_ENABLE_FIRST_SCAN_2G_ONLY_NAME, WLAN_PARAM_Integer, hdd_config_t, enableFirstScan2GOnly, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -4489,7 +4464,7 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) temp = (temp & 0xFFF3) | (pConfig->vhtTxMCS2x2 << 2); VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, - "vhtRxMCS2x2 - %x temp - %lu enable2x2 %d\n", + "vhtRxMCS2x2 - %x temp - %u enable2x2 %d\n", pConfig->vhtRxMCS2x2, temp, pConfig->enable2x2); if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_TX_MCS_MAP, @@ -4604,7 +4579,12 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) } else { +#ifndef QCA_WIFI_2_0 val = WNI_CFG_ASSOC_STA_LIMIT_STADEF; +#else + val = pConfig->maxNumberOfPeers; +#endif + } if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ASSOC_STA_LIMIT, val, NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) @@ -4841,15 +4821,6 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.nRoamIntraBand = pConfig->nRoamIntraBand; smeConfig.csrConfig.nProbes = pConfig->nProbes; - if (pConfig->nRoamScanHomeAwayTime < (pConfig->nNeighborScanMaxChanTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: Invalid config, Home away time(%d) is less than twice RF switching time + channel max time(%d)" - " Hence enforcing home away time to disable (0)", - __func__, pConfig->nRoamScanHomeAwayTime, - (pConfig->nNeighborScanMaxChanTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))); - pConfig->nRoamScanHomeAwayTime = 0; - } smeConfig.csrConfig.nRoamScanHomeAwayTime = pConfig->nRoamScanHomeAwayTime; #endif smeConfig.csrConfig.fFirstScanOnly2GChnl = pConfig->enableFirstScan2GOnly; diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 6bfa05319375..acdfd9a8ceaf 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -531,7 +531,8 @@ enum wlan_hdd_tm_attr WLAN_HDD_TM_ATTR_INVALID = 0, WLAN_HDD_TM_ATTR_CMD = 1, WLAN_HDD_TM_ATTR_DATA = 2, - WLAN_HDD_TM_ATTR_TYPE = 3, + WLAN_HDD_TM_ATTR_STREAM_ID = 3, + WLAN_HDD_TM_ATTR_TYPE = 4, /* keep last */ WLAN_HDD_TM_ATTR_AFTER_LAST, WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1, @@ -712,6 +713,10 @@ int wlan_hdd_cfg80211_init(struct device *dev, } #endif/*FEATURE_WLAN_SCAN_PNO*/ +#if defined(QCA_WIFI_2_0) && defined (QCA_WIFI_FTM) && !defined(QCA_WIFI_ISOC) + if (vos_get_conparam() != VOS_FTM_MODE) { +#endif + #ifdef CONFIG_ENABLE_LINUX_REG /* even with WIPHY_FLAG_CUSTOM_REGULATORY, driver can still register regulatory callback and @@ -724,6 +729,10 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->reg_notifier = wlan_hdd_crda_reg_notifier; #endif +#if defined(QCA_WIFI_2_0) && defined (QCA_WIFI_FTM) && !defined(QCA_WIFI_ISOC) + } +#endif + wiphy->max_scan_ssids = MAX_SCAN_SSID; wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH; @@ -1818,10 +1827,12 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); struct qc_mac_acl_entry *acl_entry = NULL; v_SINT_t i; + hdd_config_t *iniConfig; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); ENTER(); + iniConfig = pHddCtx->cfg_ini; pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig; @@ -1832,6 +1843,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int; + pConfig->disableDFSChSwitch = iniConfig->disableDFSChSwitch; + //channel is already set in the set_channel Call back //pConfig->channel = pCommitConfig->channel; @@ -5490,6 +5503,21 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_Connecting); + /* After 8-way handshake supplicant should give the scan command + * in that it update the additional IEs, But because of scan + * enhancements, the supplicant is not issuing the scan command now. + * So the unicast frames which are sent from the host are not having + * the additional IEs. If it is P2P CLIENT and there is no additional + * IE present in roamProfile, then use the addtional IE form scan_info + */ + + if ((pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) && + (!pRoamProfile->pAddIEScan)) + { + pRoamProfile->pAddIEScan = &pAdapter->scan_info.scanAddIE.addIEdata[0]; + pRoamProfile->nAddIEScanLength = pAdapter->scan_info.scanAddIE.length; + } + status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, pRoamProfile, &roamId); diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c index a0f507b3ead0..4badb4ae5543 100644 --- a/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1707,7 +1707,7 @@ VOS_STATUS hdd_wlan_re_init(void *hif_sc) adf_ctx = vos_mem_malloc(sizeof(adf_os_device_t)); if (!adf_ctx) { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to allocate adf_ctx"); + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to allocate adf_ctx", __func__); goto err_re_init; } vos_mem_zero(adf_ctx, sizeof(adf_os_device_t)); @@ -1720,6 +1720,25 @@ VOS_STATUS hdd_wlan_re_init(void *hif_sc) /* The driver should always be initialized in STA mode after SSR */ hdd_set_conparam(0); +#ifdef CONFIG_ENABLE_LINUX_REG + vosStatus = vos_nv_open(); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + /* NV module cannot be initialized */ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_nv_open failed", __func__); + goto err_re_init; + } +#ifdef QCA_WIFI_ISOC + vosStatus = vos_init_wiphy_from_nv_bin(); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + /* NV module cannot be initialized */ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_init_wiphy failed", __func__); + goto err_re_init; + } +#endif +#endif + /* Re-open VOSS, it is a re-open b'se control transport was never closed. */ vosStatus = vos_open(&pVosContext, 0); if (!VOS_IS_STATUS_SUCCESS(vosStatus)) @@ -1764,6 +1783,24 @@ VOS_STATUS hdd_wlan_re_init(void *hif_sc) goto err_vosclose; } +#ifdef CONFIG_ENABLE_LINUX_REG +#ifndef QCA_WIFI_ISOC + /* initialize the NV module. This is required so that + we can initialize the channel information in wiphy + from the NV.bin data. The channel information in + wiphy needs to be initialized before wiphy registration */ + + vosStatus = vos_init_wiphy_from_eeprom(); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + /* NV module cannot be initialized */ + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vos_init_wiphy_from_eeprom failed", __func__); + goto err_vosclose; + } +#endif +#endif + vosStatus = hdd_set_sme_chan_list(pHddCtx); if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { hddLog(VOS_TRACE_LEVEL_FATAL, diff --git a/CORE/HDD/src/wlan_hdd_ftm.c b/CORE/HDD/src/wlan_hdd_ftm.c index c5257e8cee61..9bcf52d99110 100644 --- a/CORE/HDD/src/wlan_hdd_ftm.c +++ b/CORE/HDD/src/wlan_hdd_ftm.c @@ -80,6 +80,7 @@ #include "ol_fw.h" #include "testmode.h" #include "wlan_hdd_cfg80211.h" +#include "if_pci.h" #endif #define RXMODE_DISABLE_ALL 0 @@ -562,8 +563,14 @@ static VOS_STATUS wlan_ftm_vos_open( v_CONTEXT_t pVosContext, v_SIZE_t hddContex macOpenParms.powersaveOffloadEnabled = pHddCtx->cfg_ini->enablePowersaveOffload; +#ifndef QCA_WIFI_ISOC + vStatus = WDA_open(gpVosContext, gpVosContext->pHDDContext, + NULL, NULL, + &macOpenParms); +#else vStatus = WDA_open(gpVosContext, gpVosContext->pHDDContext, NULL, &macOpenParms); +#endif if (!VOS_IS_STATUS_SUCCESS(vStatus)) { /* Critical Error ... Cannot proceed further */ @@ -622,6 +629,7 @@ static VOS_STATUS wlan_ftm_vos_open( v_CONTEXT_t pVosContext, v_SIZE_t hddContex goto err_nv_close; } +#ifndef QCA_WIFI_FTM /* Now proceed to open the SME */ vStatus = sme_Open(gpVosContext->pMACContext); if (!VOS_IS_STATUS_SUCCESS(vStatus)) @@ -641,8 +649,13 @@ static VOS_STATUS wlan_ftm_vos_open( v_CONTEXT_t pVosContext, v_SIZE_t hddContex "%s: VOSS successfully Opened", __func__); return VOS_STATUS_SUCCESS; } +#else + return VOS_STATUS_SUCCESS; +#endif +#ifndef QCA_WIFI_FTM err_mac_close: +#endif macClose(gpVosContext->pMACContext); err_nv_close: @@ -701,6 +714,7 @@ static VOS_STATUS wlan_ftm_vos_close( v_CONTEXT_t vosContext ) VOS_STATUS vosStatus; pVosContextType gpVosContext = (pVosContextType)vosContext; +#ifndef QCA_WIFI_FTM vosStatus = sme_Close(((pVosContextType)vosContext)->pMACContext); if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { @@ -708,6 +722,7 @@ static VOS_STATUS wlan_ftm_vos_close( v_CONTEXT_t vosContext ) "%s: Failed to close BAL",__func__); VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); } +#endif vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext); if (!VOS_IS_STATUS_SUCCESS(vosStatus)) @@ -744,13 +759,14 @@ static VOS_STATUS wlan_ftm_vos_close( v_CONTEXT_t vosContext ) VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); } -#if defined(QCA_WIFI_2_0) && defined(QCA_WIFI_FTM) +#if defined(QCA_WIFI_2_0) && defined(QCA_WIFI_FTM) && !defined(QCA_WIFI_ISOC) if (gpVosContext->htc_ctx) { HTCStop(gpVosContext->htc_ctx); HTCDestroy(gpVosContext->htc_ctx); gpVosContext->htc_ctx = NULL; } + hif_disable_isr(gpVosContext->pHIFContext); #endif vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq); diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 93e4edab15db..d86b142aceff 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -555,6 +555,18 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa pHddApCtx->wepKey[i].keyLength = 0; } } + + // We should restart OS transmit queues if we came here after + // radar detection and channel change + if (VOS_TRUE == pHddCtx->dfs_radar_found) + { + pHddCtx->dfs_radar_found = VOS_FALSE; + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) + { + netif_tx_start_all_queues(dev); + } + } + //Fill the params for sending IWEVCUSTOM Event with SOFTAP.enabled startBssEvent = "SOFTAP.enabled"; memset(&we_custom_start_event, '\0', sizeof(we_custom_start_event)); @@ -859,6 +871,11 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa hdd_stop_p2p_link(pHostapdAdapter, usrDataForCallback); return VOS_STATUS_SUCCESS; + case eSAP_CHANNEL_CHANGE_EVENT: + hddLog(LOG1, FL("Received eSAP_CHANNEL_CHANGE_EVENT event\n")); + /* TODO Need to indicate operating channel change to hostapd */ + return VOS_STATUS_SUCCESS; + default: hddLog(LOG1,"SAP message is not handled\n"); goto stopbss; @@ -1140,6 +1157,14 @@ static iw_softap_setparam(struct net_device *dev, } #ifdef QCA_WIFI_2_0 + case QCSAP_PARAM_SET_TXRX_FW_STATS: + { + hddLog(LOG1, "QCSAP_PARAM_SET_TXRX_FW_STATS val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID, + set_value, VDEV_CMD); + break; + } /* Firmware debug log */ case QCSAP_DBGLOG_LOG_LEVEL: { @@ -3005,7 +3030,8 @@ static VOS_STATUS wlan_hdd_get_classAstats_for_station(hdd_adapter_t *pAdapter, 0, // not periodic FALSE, //non-cached results staid, - &context); + &context, + pAdapter->sessionId ); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -3213,6 +3239,9 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hideSSID" }, { QCSAP_PARAM_SET_MC_RATE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMcRate" }, + { QCSAP_PARAM_SET_TXRX_FW_STATS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txrx_fw_stats" }, + #ifdef QCA_WIFI_2_0 /* Sub-cmds DBGLOG specific commands */ diff --git a/CORE/HDD/src/wlan_hdd_ipa.c b/CORE/HDD/src/wlan_hdd_ipa.c index 2b4e5b301738..4c065c248275 100644 --- a/CORE/HDD/src/wlan_hdd_ipa.c +++ b/CORE/HDD/src/wlan_hdd_ipa.c @@ -47,68 +47,65 @@ Include Files #include <linux/skbuff.h> #include <linux/list.h> #include <linux/debugfs.h> -#include <wlan_hdd_softap_tx_rx.h> - -#include "vos_sched.h" -#include "wlan_qct_tl.h" -#include "ol_txrx_peer_find.h" -#include "tl_shim.h" #define HDD_IPA_DESC_BUFFER_RATIO 4 #define HDD_IPA_IPV4_NAME_EXT "_ipv4" #define HDD_IPA_IPV6_NAME_EXT "_ipv6" #define HDD_IPA_RX_INACTIVITY_MSEC_DELAY 2000 -#define HDD_IPA_WLAN_HDR_ONLY_LEN 4 + +const uint8_t ipa_set_tx_hdr[] = { +/*IPA-WLAN HDR */ + 0x00, 0x00, /* Reserved */ +#define HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET 2 +#define HDD_IPA_WLAN_HDR_DEV_TYPE_MASK 0x80 +#define HDD_IPA_WLAN_HDR_DEV_TYPE_AP 0x80 +#define HDD_IPA_WLAN_HDR_DEV_TYPE_STA 0x00 +#define HDD_IPA_WLAN_HDR_DEV_ID_MASK 0x7F #define HDD_IPA_WLAN_HDR_STA_ID_OFFSET 3 -#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0 - -struct llc_snap_hdr { - uint8_t dsap; - uint8_t ssap; - uint8_t resv[4]; - __be16 eth_type; -} __packed; - -struct ipa_tx_hdr { - struct ethhdr eth; - struct llc_snap_hdr llc_snap; -} __packed; - -/* For Tx pipes, use 802.3 Header format */ -struct ipa_tx_hdr ipa_set_tx_hdr = { - { - {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc}, /* Des_MAC filled by IPA */ - {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff}, /* Src. MAC filled by IPA */ - 0x00 /* length can be zero */ - }, - { + 0x00, 0x00, + /* dev_id and sta_id filled by wlan*/ + + /* 802.3 header - 14 bytes*/ +#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 4 + 0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc, + /* Des_MAC filled by IPA */ +#define HDD_IPA_WLAN_HDR_SRC_MAC_OFFSET 10 + 0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff, + /* Src. MAC filled by IPA */ + 0x00, 0x00, + /* length can be zero */ + + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, /* LLC SNAP header 8 bytes */ - 0xaa, 0xaa, - {0x03, 0x00, 0x00, 0x00}, - 0x0008 /* type value(2 bytes) ,filled by wlan */ - /* 0x0800 - IPV4, 0x86dd - IPV6 */ - } +#define HDD_IPA_WLAN_TX_HDR_IP_VER_OFFSET 24 + 0x08, 0x00 + /* type value(2 bytes) ,filled by wlan */ + /* 0x0800 - IPV4, 0x86dd - IPV6 */ }; -struct ipa_rx_hdr { - uint8_t hdr[HDD_IPA_WLAN_HDR_ONLY_LEN]; - struct ethhdr eth; -} __packed; - -/* For Rx pipe, use Ethernet-II Header format */ -struct ipa_rx_hdr ipa_set_rx_hdr = { - {0x00, 0x00, 0x00, 0x00}, /* 4 bytes header */ - { - {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc}, /* Des_MAC filled by IPA */ - {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff}, /* Src. MAC filled by IPA */ - 0x0008 /* type value(2 bytes) ,filled by wlan */ - /* 0x0800 - IPV4, 0x86dd - IPV6 */ - } +// For Rx pipe, use Ethernet-II Header format +const uint8_t ipa_set_rx_hdr[] = { + 0x00, 0x00, /* Reserved */ + 0x00, 0x00, + /* dev_id and sta_id filled by wlan*/ + + /* 802.3 header - 14 bytes*/ + 0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc, + /* Des_MAC filled by IPA */ + 0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff, + /* Src. MAC filled by IPA */ +#define HDD_IPA_WLAN_RX_HDR_IP_VER_OFFSET 16 + 0x08, 0x00 + /* type value(2 bytes) ,filled by wlan */ + /* 0x0800 - IPV4, 0x86dd - IPV6 */ }; + #define HDD_IPA_WLAN_TX_HDR_LEN sizeof(ipa_set_tx_hdr) #define HDD_IPA_WLAN_RX_HDR_LEN sizeof(ipa_set_rx_hdr) +#define HDD_IPA_WLAN_HDR_ONLY_LEN 4 +#define HDD_IPA_MAX_TX_PIPE_MAP 8 #define HDD_IPA_WLAN_HDR_PARTIAL 1 #define HDD_IPA_LOG(LVL, fmt, args...) VOS_TRACE(VOS_MODULE_ID_HDD, LVL, \ @@ -122,9 +119,10 @@ enum hdd_ipa_rm_state { }; enum hdd_ipa_pipe_index { - HDD_IPA_TX_WLAN0_PIPE, - HDD_IPA_TX_WLAN1_PIPE, - HDD_IPA_TX_WLAN2_PIPE, + HDD_IPA_TX_VI_PIPE, + HDD_IPA_TX_VO_PIPE, + HDD_IPA_TX_BE_PIPE, + HDD_IPA_TX_BK_PIPE, HDD_IPA_RX_PIPE, HDD_IPA_MAX_PIPE }; @@ -134,22 +132,38 @@ enum hdd_ipa_ip_ver { HDD_IPA_IPV6 = 2 }; -#define HDD_IPA_WLAN_MAX_STA_ID 255 - -uint8_t wlan_sta_id_2_hdd_pipe_id[HDD_IPA_WLAN_MAX_STA_ID] = {0xFF}; - -uint8_t hdd_pipe_id_2_ipa_client_id[HDD_IPA_MAX_PIPE] = { +uint8_t hdd_ipa_pipe_client[HDD_IPA_MAX_PIPE] = { IPA_CLIENT_WLAN1_CONS, IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN3_CONS, + IPA_CLIENT_WLAN4_CONS, IPA_CLIENT_WLAN1_PROD }; -uint8_t ipa_client_id_2_hdd_pipe_id[IPA_CLIENT_MAX] = { - [IPA_CLIENT_WLAN1_CONS] = HDD_IPA_TX_WLAN0_PIPE, - [IPA_CLIENT_WLAN2_CONS] = HDD_IPA_TX_WLAN1_PIPE, - [IPA_CLIENT_WLAN3_CONS] = HDD_IPA_TX_WLAN2_PIPE, - [IPA_CLIENT_WLAN1_PROD] = HDD_IPA_RX_PIPE +uint8_t hdd_ipa_pipe_client_AC[] = { + HDD_LINUX_AC_VI, + HDD_LINUX_AC_VO, + HDD_LINUX_AC_BE, + HDD_LINUX_AC_BK +}; + +static struct hdd_ipa_tx_pipe_map{ + uint8_t tos_value; + enum ipa_client_type client; + uint8_t ac; +} hdd_ipa_tx_pipe_map_info[HDD_IPA_MAX_TX_PIPE_MAP] = { + /* BK */ + {1, IPA_CLIENT_WLAN1_CONS, HDD_LINUX_AC_BK}, + {2, IPA_CLIENT_WLAN1_CONS, HDD_LINUX_AC_BK}, + /* BE */ + {0, IPA_CLIENT_WLAN2_CONS, HDD_LINUX_AC_BE}, + {3, IPA_CLIENT_WLAN2_CONS, HDD_LINUX_AC_BE}, + /* VI */ + {4, IPA_CLIENT_WLAN3_CONS, HDD_LINUX_AC_VI}, + {5, IPA_CLIENT_WLAN3_CONS, HDD_LINUX_AC_VI}, + /* VO */ + {6, IPA_CLIENT_WLAN4_CONS, HDD_LINUX_AC_VO}, + {7, IPA_CLIENT_WLAN4_CONS, HDD_LINUX_AC_VO}, }; struct hdd_ipa_sys_pipe { @@ -171,8 +185,6 @@ struct hdd_ipa_priv { struct list_head free_desc_head; struct list_head pend_desc_head; - struct ol_txrx_vdev_t *pipe_to_vdev[HDD_IPA_MAX_PIPE]; - hdd_context_t *hdd_ctx; struct dentry *debugfs_dir; @@ -189,6 +201,7 @@ struct hdd_ipa_priv { uint64_t rx_ipa_hw_maxed_out; + uint64_t tx_ipa_recv; uint64_t freeq_empty; uint64_t freeq_cnt; @@ -211,11 +224,7 @@ struct hdd_ipa_priv { uint64_t rx_ipa_dh_reclaim; uint64_t rx_ipa_dh_not_used; #endif - uint64_t ipa_lb_cnt; - uint64_t tx_ipa_recv; - uint64_t tx_comp_cnt; - uint64_t tx_dp_err_cnt; - } stats; + }stats; }; enum hdd_ipa_evt { @@ -247,13 +256,13 @@ static inline void *hdd_ipa_kzalloc(uint32_t size) return data; } -static inline struct ipa_tx_data_desc *hdd_ipa_get_desc_from_freeq(void) +static inline struct ipa_tx_data_desc * hdd_ipa_get_desc_from_freeq(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; struct ipa_tx_data_desc *desc = NULL; spin_lock_bh(&ghdd_ipa->q_lock); - if (!list_empty(&ghdd_ipa->free_desc_head)) { + if(!list_empty(&ghdd_ipa->free_desc_head)) { desc = list_first_entry(&ghdd_ipa->free_desc_head, struct ipa_tx_data_desc, link); list_del(&desc->link); hdd_ipa->stats.freeq_cnt--; @@ -408,9 +417,7 @@ void hdd_ipa_send_skb_to_network(adf_nbuf_t skb, hdd_adapter_t *adap_dev) { if (!adap_dev || (adap_dev && adap_dev->magic != WLAN_HDD_ADAPTER_MAGIC)) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid adapter: adap=0x%x", - adap_dev); - + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid sta_id"); adf_nbuf_free(skb); return; } @@ -431,10 +438,8 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, int send_desc_cnt) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - struct ipa_tx_data_desc *send_desc, *desc, *tmp; + struct ipa_tx_data_desc *send_desc; uint32_t cur_send_cnt = 0; - adf_nbuf_t buf; - #ifndef HDD_IPA_USE_IPA_RM_TIMER if (hdd_ipa->rm_timer_on) { del_timer(&hdd_ipa->rm_timer); @@ -475,42 +480,12 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, cur_send_cnt = send_desc_cnt; } hdd_ipa->stats.rx_ipa_sent_desc_cnt += cur_send_cnt; - -#ifdef HDD_IPA_EXTRA_DP_COUNTERS - hdd_ipa->stats.rx_ipa_dh_sent++; /* for desc head */ -#endif spin_unlock_bh(&hdd_ipa->q_lock); - if (ipa_tx_dp_mul(hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE], - send_desc_head) != 0) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ipa_tx_dp_mul failed!!! (cur_send_cnt=%d)", cur_send_cnt); - hdd_ipa->stats.tx_dp_err_cnt++; - spin_lock_bh(&hdd_ipa->q_lock); - - list_for_each_entry_safe(desc, tmp, - &send_desc_head->link, link) { - list_del(&desc->link); - buf = desc->priv; - adf_nbuf_free(buf); - desc->priv = NULL; - desc->pyld_buffer = NULL; - desc->pyld_len = 0; - list_add_tail(&desc->link, &hdd_ipa->free_desc_head); - hdd_ipa->stats.freeq_cnt++; -#ifdef HDD_IPA_EXTRA_DP_COUNTERS - hdd_ipa->stats.freeq_reclaim++; -#endif - hdd_ipa->pending_desc_cnt--; - } - - /* return anchor node */ - list_add_tail(&send_desc_head->link, &hdd_ipa->free_desc_head); - hdd_ipa->stats.freeq_cnt++; #ifdef HDD_IPA_EXTRA_DP_COUNTERS - hdd_ipa->stats.rx_ipa_dh_reclaim++; - hdd_ipa->stats.freeq_reclaim++; + hdd_ipa->stats.rx_ipa_dh_sent++; //for desc head #endif - spin_unlock_bh(&hdd_ipa->q_lock); - } + ipa_tx_dp_mul(hdd_ipa_pipe_client[HDD_IPA_RX_PIPE], + send_desc_head); } else { #ifdef HDD_IPA_EXTRA_DP_COUNTERS hdd_ipa->stats.rx_ipa_hw_max_qued += send_desc_cnt; @@ -533,6 +508,12 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, static int hdd_ipa_is_ip_pkt(void *data, uint8_t ip_ver) { struct ethhdr *eth = (struct ethhdr *)data; + struct llc_snap_hdr { + uint8_t dsap; + uint8_t ssap; + uint8_t resv[4]; + __be16 eth_type; + } __packed; struct llc_snap_hdr *ls_hdr; uint16_t eth_type; int ret = 0; @@ -542,14 +523,16 @@ static int hdd_ipa_is_ip_pkt(void *data, uint8_t ip_ver) /* Non Ethernet II framing format */ ls_hdr = (struct llc_snap_hdr *)((uint8_t *)data + sizeof(struct ethhdr)); - - if (((ls_hdr->dsap == 0xAA) && (ls_hdr->ssap == 0xAA)) || - ((ls_hdr->dsap == 0xAB) && (ls_hdr->ssap == 0xAB))) - eth_type = be16_to_cpu(ls_hdr->eth_type); + /* TODO Is this needed + if ((ls_hdr->dsap == 0xAA && ls_hdr->ssap == 0xAA) || + (ls_hdr->dsap == 0xAB && ls_hdr->ssap == 0xAB)) + */ + eth_type = be16_to_cpu(ls_hdr->eth_type); } - if (((eth_type == ETH_P_IP) && (ip_ver == HDD_IPA_IPV4)) || - ((eth_type == ETH_P_IPV6) && (ip_ver == HDD_IPA_IPV6))) + if ((eth_type == ETH_P_IP) && (ip_ver == HDD_IPA_IPV4)) + ret = 1; + else if ((eth_type == ETH_P_IPV6) && (ip_ver == HDD_IPA_IPV6)) ret = 1; if (ret != 1) @@ -567,7 +550,7 @@ static void hdd_ipa_process_evt(int evt, void *priv) *done_desc_head, *done_desc, *tmp; hdd_adapter_t *adap_dev = NULL; adf_nbuf_t buf, next_buf; - uint8_t cur_cnt = 0; + uint8_t dev_id, cur_cnt = 0, iftype; switch (evt) { case HDD_IPA_RXT_EVT: @@ -588,6 +571,8 @@ static void hdd_ipa_process_evt(int evt, void *priv) } return; } + dev_id = adap_dev->dev->ifindex; + iftype = adap_dev->wdev.iftype; /* send_desc_head is a anchor node */ send_desc_head = hdd_ipa_get_desc_from_freeq(); if (!send_desc_head) { @@ -640,8 +625,19 @@ static void hdd_ipa_process_evt(int evt, void *priv) } skb_push(buf, HDD_IPA_WLAN_HDR_ONLY_LEN); - /* vos_mem_zero(((struct ipa_rx_hdr *)(buf->data))->hdr, HDD_IPA_WLAN_HDR_ONLY_LEN); */ - ((struct ipa_rx_hdr *)(buf->data))->hdr[HDD_IPA_WLAN_HDR_STA_ID_OFFSET] = rxt->sta_id; + memset(buf->data, 0, HDD_IPA_WLAN_HDR_ONLY_LEN); + buf->data[HDD_IPA_WLAN_HDR_STA_ID_OFFSET] = rxt->sta_id; + buf->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |= + dev_id & HDD_IPA_WLAN_HDR_DEV_ID_MASK; + if (iftype == NL80211_IFTYPE_AP || + iftype == NL80211_IFTYPE_P2P_GO) { + buf->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |= + HDD_IPA_WLAN_HDR_DEV_TYPE_AP; + } else { + buf->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |= + HDD_IPA_WLAN_HDR_DEV_TYPE_STA; + } + send_desc = hdd_ipa_get_desc_from_freeq(); if (send_desc) { send_desc->priv = buf; @@ -701,7 +697,7 @@ static void hdd_ipa_process_evt(int evt, void *priv) HDD_IPA_RM_GRANT_PENDING); hdd_ipa_rm_request(hdd_ipa); } - /* hdd_ipa_rm_request can immediately grant so check again. */ + //hdd_ipa_rm_request can immediately grant so check again. if (atomic_read(&hdd_ipa->rm_state) == HDD_IPA_RM_GRANT_PENDING) { spin_lock_bh(&hdd_ipa->q_lock); @@ -710,11 +706,6 @@ static void hdd_ipa_process_evt(int evt, void *priv) /* return anchor node */ list_add_tail(&send_desc_head->link, &hdd_ipa->free_desc_head); - hdd_ipa->stats.freeq_cnt++; -#ifdef HDD_IPA_EXTRA_DP_COUNTERS - hdd_ipa->stats.rx_ipa_dh_reclaim++; - hdd_ipa->stats.freeq_reclaim++; -#endif spin_unlock_bh(&hdd_ipa->q_lock); #ifdef HDD_IPA_EXTRA_DP_COUNTERS hdd_ipa->stats.rx_ipa_rm_qued += cur_cnt; @@ -800,7 +791,6 @@ VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rx_buf_list, rxt.sta_id = sta_id; rxt.rx_buf_list = rx_buf_list; - hdd_ipa_process_evt(HDD_IPA_RXT_EVT, &rxt); return VOS_STATUS_SUCCESS; @@ -814,174 +804,88 @@ void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) uint8_t client; struct ipa_tx_data_desc *done_desc_head; adf_nbuf_t skb; - uint8_t sta_id; + uint8_t sta_id, dev_id; hdd_adapter_t *adap_dev=NULL; client = *((uint8_t *)priv); - if (client != hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]) { + if (client != hdd_ipa_pipe_client[HDD_IPA_RX_PIPE]) { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "w2i cb wrong pipe: %d %x %x", client, priv, - &hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]); + &hdd_ipa_pipe_client[HDD_IPA_RX_PIPE]); return; } switch (evt) { case IPA_RECEIVE: skb = (adf_nbuf_t) data; - sta_id = ((struct ipa_rx_hdr *)(skb->data))->hdr[HDD_IPA_WLAN_HDR_STA_ID_OFFSET]; - - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "w2i -- skb:0x%p: %02x %02x %02x %02x %02x %02x %02x %02x", skb, - skb->data[0], skb->data[1], skb->data[2], skb->data[3], - skb->data[4], skb->data[5], skb->data[6], skb->data[7]); - - skb_pull(skb, HDD_IPA_WLAN_HDR_ONLY_LEN); - + sta_id = skb->data[HDD_IPA_WLAN_HDR_STA_ID_OFFSET]; + dev_id = skb->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET]; if (sta_id < ARRAY_SIZE(hdd_ipa->hdd_ctx->sta_to_adapter)) { adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id]; } else { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, - "w2i cb: wrong sta_id: %d", sta_id); + "w2i cb: wrong sta_id: %d", sta_id); } - + skb_pull(skb, HDD_IPA_WLAN_HDR_ONLY_LEN); hdd_ipa->stats.rx_ipa_excep++; hdd_ipa_send_skb_to_network(skb, adap_dev); break; case IPA_WRITE_DONE: done_desc_head = (struct ipa_tx_data_desc *)data; hdd_ipa_w2i_write_done_handler(done_desc_head); - break; - default: - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, - "w2i cb wrong event: 0x%x", evt); - return; + break; } } void hdd_ipa_nbuf_cb(adf_nbuf_t skb) { - struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - - /* TX COMP counter at frame free location. */ - hdd_ipa->stats.tx_comp_cnt++; - - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "0x%p", NBUF_OWNER_PRIV_DATA(skb)); - ipa_free_skb((struct ipa_rx_data *) NBUF_OWNER_PRIV_DATA(skb)); + ipa_free_skb(skb); } -#ifdef WLAN_TX_MUL -void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) +void hdd_ipa_tx_process(adf_nbuf_t skb, uint8_t ac) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - struct ipa_rx_data_mul *ipa_tx_desc; - adf_nbuf_t skb; - uint8_t client, pipe_id; - - if (evt == IPA_RECEIVE) { - client = *((uint8_t *)priv); - struct list_head *head = (struct list_head *)data; - - pipe_id = ipa_client_id_2_hdd_pipe_id[client]; - - if (hdd_ipa->pipe_to_vdev[pipe_id] == NULL) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail (vdev=NULL)"); - /* TODO: need to free ipa_desc and skb here */ - return; - } - - list_for_each_entry(ipa_tx_desc, head, link) { - if (ipa_tx_desc->dd == NULL) - break; - - /* TX frame Counter at HDD CB function called by IPA loopback, to push lower layer.*/ - hdd_ipa->stats.tx_ipa_recv++; - - skb = ipa_tx_desc->dd->skb; - - /* skb->dev = ipa_client_id_2_hdd_pipe_id[client]; */ - adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); - NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID; - NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb; - NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dd->dma_addr; - - NBUF_OWNER_PRIV_DATA(skb) = (unsigned long)ipa_tx_desc->dd; - - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "skb:0x%p: %02x %02x %02x %02x %02x %02x %02x %02x", skb, - skb->data[0], skb->data[1], skb->data[2], skb->data[3], - skb->data[4], skb->data[5], skb->data[6], skb->data[7]); - - skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, hdd_ipa->pipe_to_vdev[pipe_id], - ipa_tx_desc->dd->skb); - if (skb) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail"); - ipa_free_skb(ipa_tx_desc->dd); - continue; - } - } - ipa_free_desc(data); + uint8_t sta_id; + hdd_adapter_t *adap_dev; - } else { - /* HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "i2w cb wrong evt: %d", evt); - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Testing hack code data path"); */ - skb = (adf_nbuf_t) data; - dev_kfree_skb_any(skb); + skb->queue_mapping = ac; + sta_id = skb->data[HDD_IPA_WLAN_HDR_STA_ID_OFFSET]; + adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id]; + if (!adap_dev + || (adap_dev && adap_dev->magic != WLAN_HDD_ADAPTER_MAGIC)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid sta_id %d", sta_id); + ipa_free_skb(skb); + return; } + skb->dev = adap_dev->dev; + NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID; + NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb; + skb_pull(skb, HDD_IPA_WLAN_HDR_ONLY_LEN); + (adap_dev->dev->netdev_ops->ndo_start_xmit)(skb, adap_dev->dev); } -#else - void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - struct ipa_rx_data *ipa_tx_desc; adf_nbuf_t skb; - uint8_t client, pipe_id; + uint8_t client; + uint8_t i, ac = HDD_LINUX_AC_BE; if (evt == IPA_RECEIVE) { - /* TX frame Counter at HDD CB function called by IPA loopback, to push lower layer */ - hdd_ipa->stats.tx_ipa_recv++; - client = *((uint8_t *)priv); - ipa_tx_desc = (struct ipa_rx_data *)data; - skb = ipa_tx_desc->skb; - - adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); - NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID; - NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb; - NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dma_addr; - - NBUF_OWNER_PRIV_DATA(skb) = data; - - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "0x%p", NBUF_OWNER_PRIV_DATA(skb)); - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "skb:0x%p: %02x %02x %02x %02x %02x %02x %02x %02x", skb, - skb->data[0], skb->data[1], skb->data[2], skb->data[3], - skb->data[4], skb->data[5], skb->data[6], skb->data[7]); - - pipe_id = ipa_client_id_2_hdd_pipe_id[client]; - - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "client=%d, pipe_to_vdev[%d]=0x%x", client, pipe_id, hdd_ipa->pipe_to_vdev[pipe_id]); - - if (hdd_ipa->pipe_to_vdev[pipe_id] == NULL) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail (pipe_to_vdev[%d]=NULL)", pipe_id); - ipa_free_skb(ipa_tx_desc); - return; - } - - skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, hdd_ipa->pipe_to_vdev[pipe_id], - ipa_tx_desc->skb); - if (skb) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail"); - ipa_free_skb(ipa_tx_desc); - return; - } - } else { - /* HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "i2w cb wrong evt: %d", evt); - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Testing hack code data path"); */ skb = (adf_nbuf_t) data; - dev_kfree_skb_any(skb); - } + for (i = 0; i < HDD_IPA_MAX_TX_PIPE_MAP; i++) { + if (client == hdd_ipa_tx_pipe_map_info[i].client) { + ac = hdd_ipa_tx_pipe_map_info[i].ac; + break; + } + } + hdd_ipa->stats.tx_ipa_recv++; + hdd_ipa_tx_process(skb, ac); + } else + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "i2w cb wrong evt: %d", evt); } -#endif static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) { @@ -992,9 +896,9 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) for (i = 0; i < HDD_IPA_RX_PIPE; i++) { ipa = &hdd_ipa->sys_pipe[i].ipa_sys_params; - ipa->client = hdd_pipe_id_2_ipa_client_id[i]; + ipa->client = hdd_ipa_pipe_client[i]; ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize; - ipa->priv = &hdd_pipe_id_2_ipa_client_id[i]; + ipa->priv = &hdd_ipa_pipe_client[i]; ipa->notify = hdd_ipa_i2w_cb; ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_TX_HDR_LEN; @@ -1010,9 +914,9 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) ipa = &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].ipa_sys_params; - ipa->client = hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]; - ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize + sizeof(struct sps_iovec); /* To make sure total # of desc is 1 less than the desc FIFO size */ - ipa->priv = &hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]; + ipa->client = hdd_ipa_pipe_client[HDD_IPA_RX_PIPE]; + ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize; + ipa->priv = &hdd_ipa_pipe_client[HDD_IPA_RX_PIPE]; ipa->notify = hdd_ipa_w2i_cb; ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; @@ -1048,8 +952,10 @@ void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa) } } -int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, const char *ifname) +int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t iftype, + uint8_t sta_id, const char *ifname) { +#define HDD_IPA_TOS_MASK 0xE0 struct ipa_tx_intf tx_intf; struct ipa_rx_intf rx_intf; struct ipa_ioc_tx_intf_prop *tx_prop = NULL; @@ -1058,21 +964,23 @@ int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, con char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX]; char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX]; - int ip_max = HDD_IPA_IPV4; + int i, j, ip_max = HDD_IPA_IPV4; int ret = 0; if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) ip_max = HDD_IPA_IPV6; /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */ - tx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_tx_intf_prop) * ip_max); + tx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_tx_intf_prop) * + HDD_IPA_MAX_TX_PIPE_MAP * ip_max); if (!tx_prop) { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ENOMEM"); goto register_interface_fail; } /* Allocate RX properties, 1 each for IPv4 & IPv6 */ - rx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_rx_intf_prop) * ip_max); + rx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_rx_intf_prop) + * ip_max); if (!rx_prop) { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ENOMEM"); goto register_interface_fail; @@ -1082,28 +990,72 @@ int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, con snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s", ifname, HDD_IPA_IPV4_NAME_EXT); - snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s", - ifname, HDD_IPA_IPV6_NAME_EXT); - rx_prop[IPA_IP_v4].ip = IPA_IP_v4; - rx_prop[IPA_IP_v4].src_pipe = IPA_CLIENT_WLAN1_PROD; - rx_intf.num_props++; if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { + snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV6_NAME_EXT); rx_prop[IPA_IP_v6].ip = IPA_IP_v6; - rx_prop[IPA_IP_v6].src_pipe = IPA_CLIENT_WLAN1_PROD; - rx_intf.num_props++; } - - tx_prop[IPA_IP_v4].ip = IPA_IP_v4; - tx_prop[IPA_IP_v4].dst_pipe = hdd_pipe_id_2_ipa_client_id[wlan_sta_id_2_hdd_pipe_id[sta_id]]; - strlcpy(tx_prop[IPA_IP_v4].hdr_name, ipv4_hdr_name, IPA_RESOURCE_NAME_MAX); - tx_intf.num_props++; - if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { - tx_prop[IPA_IP_v6].ip = IPA_IP_v6; - tx_prop[IPA_IP_v6].dst_pipe = hdd_pipe_id_2_ipa_client_id[wlan_sta_id_2_hdd_pipe_id[sta_id]]; - strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name, - IPA_RESOURCE_NAME_MAX); + /* + TOS value: 1, 2 - > Maps to BK pipe [WLAN1_CONS] + TOS value: 0, 3 - > Maps to BE pipe [WLAN2_CONS] + TOS value: 4, 5 - > Maps to VI pipe [WLAN3_CONS] + TOS Value: 6, 7 - > Maps to VO pipe [WLAN4_CONS] + */ + + /* + IP-TOS - 8bits + : DSCP(6-bits) ECN(2-bits) + : DSCP - P2 P1 P0 X X X + where (P2 P1 P0) form 802.1D + So shifting tos_value by 5 bits before passing to IPA. Also IPA + required mask to be set for 3 MSB bits. + */ + + for (i = 0; i < HDD_IPA_MAX_TX_PIPE_MAP; i++) { + tx_prop[i].ip = IPA_IP_v4; + tx_prop[i].attrib.attrib_mask = IPA_FLT_TOS_MASKED; + tx_prop[i].attrib.tos_value = + hdd_ipa_tx_pipe_map_info[i].tos_value << 5; + tx_prop[i].attrib.tos_mask = HDD_IPA_TOS_MASK; + tx_prop[i].dst_pipe = hdd_ipa_tx_pipe_map_info[i].client; + strlcpy(tx_prop[i].hdr_name, ipv4_hdr_name, + IPA_RESOURCE_NAME_MAX); tx_intf.num_props++; + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { + j = i + HDD_IPA_MAX_TX_PIPE_MAP; + + tx_prop[j].ip = IPA_IP_v6; + tx_prop[j].attrib.attrib_mask = IPA_FLT_TOS_MASKED; + tx_prop[j].attrib.tos_value = + hdd_ipa_tx_pipe_map_info[i].tos_value << 5; + tx_prop[j].attrib.tos_mask = HDD_IPA_TOS_MASK; + tx_prop[j].dst_pipe = + hdd_ipa_tx_pipe_map_info[i].client; + strlcpy(tx_prop[j].hdr_name, ipv6_hdr_name, + IPA_RESOURCE_NAME_MAX); + tx_intf.num_props++; + } + } + + for (i = 0; i < ip_max; i++) { + rx_prop[i].attrib.attrib_mask = IPA_FLT_META_DATA; + if (iftype == NL80211_IFTYPE_AP || + iftype == NL80211_IFTYPE_P2P_GO) { + rx_prop[i].attrib.meta_data = + HDD_IPA_WLAN_HDR_DEV_TYPE_AP + << ((HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET-1) * 8); + } else { + rx_prop[i].attrib.meta_data = + HDD_IPA_WLAN_HDR_DEV_TYPE_STA + << ((HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET-1) * 8); + } + rx_prop[i].attrib.meta_data_mask = + HDD_IPA_WLAN_HDR_DEV_TYPE_MASK + << ((HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET-1) * 8); + rx_prop[i].src_pipe = IPA_CLIENT_WLAN1_PROD; + + rx_intf.num_props++; } tx_intf.prop = tx_prop; @@ -1118,15 +1070,14 @@ register_interface_fail: return ret; } -static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uint8_t *mac_addr) +static int hdd_ipa_add_header_info(uint8_t sta_id, uint8_t *mac_addr) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + uint8_t dev_id, wlan_iftype; char *ifname; struct ipa_ioc_add_hdr *ipahdr = NULL; - int i, ret = -EINVAL; + int ret = -EINVAL; hdd_adapter_t *adap_dev; - struct ol_txrx_pdev_t *pdev; - struct ol_txrx_vdev_t *vdev; adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id]; if (!adap_dev) { @@ -1134,40 +1085,12 @@ static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uin goto add_header_info_ctx_fail; } + dev_id = adap_dev->dev->ifindex; + wlan_iftype = adap_dev->wdev.iftype; ifname = adap_dev->dev->name; - for (i = 0; i < HDD_IPA_MAX_PIPE; i++) - hdd_ipa->pipe_to_vdev[i] = NULL; - - if (wlan_sta_id_2_hdd_pipe_id[sta_id] == 0xFF) { - switch (type) { - case WLAN_AP_CONNECT: - wlan_sta_id_2_hdd_pipe_id[sta_id] = HDD_IPA_TX_WLAN0_PIPE; /* TODO: need to expand to AP+AP */ - break; - case WLAN_STA_CONNECT: - /* Register pipe_to_vdev for STA mode */ - pdev = ((pVosContextType)(WLAN_HDD_GET_CTX(adap_dev)->pvosContext))->pdev_txrx_ctx; - /* find the "vdev" this STA interface belongs to */ - TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { - if (adf_os_mem_cmp(mac_addr, vdev->mac_addr.raw, IEEE80211_ADDR_LEN) == 0) { - hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN2_PIPE] = vdev; - break; - } - } - - wlan_sta_id_2_hdd_pipe_id[sta_id] = HDD_IPA_TX_WLAN2_PIPE; /* STA Mode */ - break; - default: - break; - } - } - - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, " wlan_sta_id_2_hdd_pipe_id[%d]: %d", - sta_id, wlan_sta_id_2_hdd_pipe_id[sta_id]); - - - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ifindex: %d Add Partial hdr: %s, %p\n", - sta_id, ifname, mac_addr); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Mode: %d Add Partial hdr: %s, %p\n", + wlan_iftype, ifname, mac_addr); if (ifname == NULL) { HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ifname NULL"); goto add_header_info_ctx_fail; @@ -1184,19 +1107,29 @@ static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uin ipahdr->commit = 0; ipahdr->num_hdrs = 1; /* Set the Source MAC */ - memcpy(ipahdr->hdr[0].hdr, (uint8_t *)&ipa_set_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN); - memcpy((uint8_t *)(((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->eth.h_source), mac_addr, + memcpy(ipahdr->hdr[0].hdr, ipa_set_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN); + memcpy(&ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_SRC_MAC_OFFSET], mac_addr, ETH_ALEN); + /* Check the interface is AP OR STA mode, and set the station ID */ + ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |= + dev_id & HDD_IPA_WLAN_HDR_DEV_ID_MASK; + ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_STA_ID_OFFSET] = sta_id; + if (wlan_iftype == NL80211_IFTYPE_AP || + wlan_iftype == NL80211_IFTYPE_P2P_GO) { + ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |= + HDD_IPA_WLAN_HDR_DEV_TYPE_AP; + } else { + ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |= + HDD_IPA_WLAN_HDR_DEV_TYPE_STA; + } + snprintf(ipahdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", ifname, HDD_IPA_IPV4_NAME_EXT); ipahdr->hdr[0].hdr_len = HDD_IPA_WLAN_TX_HDR_LEN; ipahdr->hdr[0].is_partial = HDD_IPA_WLAN_HDR_PARTIAL; ipahdr->hdr[0].hdr_hdl = 0; - /* Set the type to IPV4 in the header*/ - ((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->llc_snap.eth_type = cpu_to_be16(ETH_P_IP); - ret = ipa_add_hdr(ipahdr); if (ret) { @@ -1211,7 +1144,8 @@ static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uin snprintf(ipahdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", ifname, HDD_IPA_IPV6_NAME_EXT); /* Set the type to IPV6 in the header*/ - ((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6); + ipahdr->hdr[0].hdr[HDD_IPA_WLAN_TX_HDR_IP_VER_OFFSET] = 0x86; + ipahdr->hdr[0].hdr[HDD_IPA_WLAN_TX_HDR_IP_VER_OFFSET + 1] = 0xdd; ret = ipa_add_hdr(ipahdr); if (ret) { @@ -1224,7 +1158,7 @@ static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uin ipahdr->hdr[0].name, ipahdr->hdr[0].hdr_hdl); } /* Configure the TX and RX pipes filter rules */ - ret = hdd_ipa_register_interface(hdd_ipa, sta_id, ifname); + ret = hdd_ipa_register_interface(hdd_ipa, wlan_iftype, sta_id, ifname); add_header_info_fail: adf_os_mem_free(ipahdr); @@ -1272,8 +1206,6 @@ void hdd_ipa_clean_hdr(hdd_adapter_t *adap_dev, uint8_t sta_id) int ret; char name_ipa[IPA_RESOURCE_NAME_MAX]; - wlan_sta_id_2_hdd_pipe_id[sta_id] = 0xFF; - /* Remove the headers */ snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", adap_dev->dev->name, HDD_IPA_IPV4_NAME_EXT); @@ -1301,7 +1233,6 @@ static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type) int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id, enum ipa_wlan_event type, uint8_t *mac_addr) { - struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; hdd_adapter_t *adap_dev = Adapter; struct ipa_msg_meta meta; struct ipa_wlan_msg *msg; @@ -1320,7 +1251,7 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id, __stringify(WLAN_STA_DISCONNECT), __stringify(WLAN_CLIENT_CONNECT_EX), }; - struct ol_txrx_peer_t *peer; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: %s evt, MAC: %pM sta_id: %d", adap_dev->dev->name, hdd_ipa_event_name[type], @@ -1334,42 +1265,33 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id, switch (type) { case WLAN_STA_CONNECT: case WLAN_AP_CONNECT: - hdd_ipa_add_header_info(type, sta_id, mac_addr); + hdd_ipa_add_header_info(sta_id, mac_addr); break; case WLAN_STA_DISCONNECT: - hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN2_PIPE] = NULL; case WLAN_AP_DISCONNECT: hdd_ipa_clean_hdr(adap_dev, sta_id); break; case WLAN_CLIENT_CONNECT_EX: - /* Register pipe map to txrx_vdev into hdd_ipa */ - peer = ol_txrx_peer_find_by_local_id(((pVosContextType)(WLAN_HDD_GET_CTX(adap_dev))->pvosContext)->pdev_txrx_ctx, sta_id); - if (!peer) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid peer"); - return -EINVAL; - } - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%d %d", adap_dev->dev->ifindex, sta_id); - if (hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN0_PIPE] == NULL) { - hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN0_PIPE] = peer->vdev; /* TODO: need to expand to AP+AP */ - } - meta.msg_type = type; meta.msg_len = (sizeof(struct ipa_wlan_msg_ex) + - sizeof(struct ipa_wlan_hdr_attrib_val)); + sizeof(struct ipa_wlan_hdr_attrib_val) * 2); msg_ex = hdd_ipa_kzalloc (meta.msg_len); if (msg_ex == NULL) { HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ENOMEM"); return -ENOMEM; } strlcpy(msg_ex->name, adap_dev->dev->name, IPA_RESOURCE_NAME_MAX); - msg_ex->num_of_attribs = 1; + msg_ex->num_of_attribs = 2; msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR; msg_ex->attribs[0].offset = HDD_IPA_WLAN_HDR_DES_MAC_OFFSET; memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr, IPA_MAC_ADDR_SIZE); + msg_ex->attribs[1].attrib_type = WLAN_HDR_ATTRIB_STA_ID; + msg_ex->attribs[1].offset = HDD_IPA_WLAN_HDR_STA_ID_OFFSET; + msg_ex->attribs[1].u.sta_id = sta_id; ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn); if (ret) { @@ -1380,9 +1302,6 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id, } return 0; case WLAN_CLIENT_DISCONNECT: - /* TODO: need to expand to AP+AP */ - /* This will remove the vdev for rest of the connected clients */ - //hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN0_PIPE] = NULL; break; default: @@ -1418,7 +1337,7 @@ static int hdd_ipa_rx_pipe_desc_alloc(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; uint32_t i, max_desc_cnt; - int ret = 0; + int ret =0; struct ipa_tx_data_desc *tmp_desc; hdd_ipa->hw_desc_cnt = IPA_NUM_OF_FIFO_DESC( @@ -1541,6 +1460,11 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file, "RXT 5 skb:", hdd_ipa->stats.rxt_5); len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", "RXT > 5 skb:", hdd_ipa->stats.rxt_6); +#endif + len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", + "IPA TX Recieve:", hdd_ipa->stats.tx_ipa_recv); + +#ifdef HDD_IPA_EXTRA_DP_COUNTERS len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", "Free Queue use:", hdd_ipa->stats.freeq_use); len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", @@ -1550,14 +1474,7 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file, "Free Queue Empty:", hdd_ipa->stats.freeq_empty); len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", "Free Queue cnt:", hdd_ipa->stats.freeq_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", - "IPA LB Count:", hdd_ipa->stats.ipa_lb_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", - "IPA TX Recieve:", hdd_ipa->stats.tx_ipa_recv); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", - "TX COMP Count:", hdd_ipa->stats.tx_comp_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", - "TX DP Err Count:", hdd_ipa->stats.tx_dp_err_cnt); + if (len > buf_len) len = buf_len; @@ -1568,10 +1485,10 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file, } static const struct file_operations fops_ipa_stats = { - .read = hdd_ipa_debugfs_read_ipa_stats, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, + .read = hdd_ipa_debugfs_read_ipa_stats, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, }; @@ -1580,7 +1497,7 @@ int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa) #ifdef WLAN_OPEN_SOURCE hdd_ipa->debugfs_dir = debugfs_create_dir("cld", hdd_ipa->hdd_ctx->wiphy->debugfsdir); - if (!hdd_ipa->debugfs_dir) + if(!hdd_ipa->debugfs_dir) return -ENOMEM; debugfs_create_file("ipa-stats", S_IRUSR, hdd_ipa->debugfs_dir, @@ -1600,13 +1517,10 @@ int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa) VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) { struct hdd_ipa_priv *hdd_ipa = NULL; - int ret, i; + int ret; if (!hdd_ipa_is_enabled(hdd_ctx)) return 0; - for (i = 0; i < HDD_IPA_WLAN_MAX_STA_ID; i++) - wlan_sta_id_2_hdd_pipe_id[i] = 0xFF; - hdd_ipa = hdd_ipa_kzalloc(sizeof(struct hdd_ipa_priv)); if (!hdd_ipa) { HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "ENOMEM"); @@ -1671,68 +1585,6 @@ VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) return VOS_STATUS_SUCCESS; } -#if 0 -/** -* hdd_ipa_start_xmit() - This is a hack code for IPA loopback test -*/ -int hdd_ipa_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev); - hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); - uint8_t sta_id; - struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - - v_MACADDR_t *pDestMacAddress = (v_MACADDR_t *)skb->data; - - if (vos_is_macaddr_broadcast(pDestMacAddress) || - vos_is_macaddr_group(pDestMacAddress)) { - /* The BC/MC station ID is assigned during BSS starting phase. - SAP will return the station ID used for BC/MC traffic. */ - sta_id = pHddApCtx->uBCStaId; - hdd_softap_hard_start_xmit(skb, dev); - return NETDEV_TX_OK; - } else { - sta_id = *(uint8_t *)(((uint8_t *)(skb->data)) - 1); - if (sta_id == HDD_WLAN_INVALID_STA_ID) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN, - "Failed to find right station"); - goto drop_pkt; - } else if (FALSE == pAdapter->aStaInfo[sta_id].isUsed) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN, - "STA %d is unregistered", sta_id); - goto drop_pkt; - } - - if ((WLANTL_STA_CONNECTED != - pAdapter->aStaInfo[sta_id].tlSTAState) && - (WLANTL_STA_AUTHENTICATED != - pAdapter->aStaInfo[sta_id].tlSTAState)) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN, - "Station not connected yet"); - goto drop_pkt; - } else if (WLANTL_STA_CONNECTED == - pAdapter->aStaInfo[sta_id].tlSTAState) { - if (ntohs(skb->protocol) != - HDD_ETHERTYPE_802_1_X) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN, - "NON-EAPOL packet in no-Auth state"); - goto drop_pkt; - } - } - } - if (hdd_ipa_is_ip_pkt(skb->data, HDD_IPA_IPV4)) { - /* TX frame Counter at HDD entry from kernel network stack, before give frame to IPA Loopback */ - hdd_ipa->stats.ipa_lb_cnt++; - ipa_tx_dp(IPA_CLIENT_WLAN1_CONS, skb, NULL); - } else { - hdd_softap_hard_start_xmit(skb, dev); - } - - return NETDEV_TX_OK; -drop_pkt: - kfree_skb(skb); - return NETDEV_TX_OK; -} #endif -#endif + diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 0a4fcff7999a..500f73ad0f30 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -180,6 +180,7 @@ static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue, * Maximum buffer size used for returning the data back to user space */ #define WLAN_MAX_BUF_SIZE 1024 +#define WLAN_PRIV_DATA_MAX_LEN 4096 /* * Driver miracast parameters 0-Disabled @@ -726,6 +727,11 @@ hdd_extract_assigned_int_from_str { return NULL; } + + if (tempInt < 0) + { + tempInt = 0; + } *pOutPtr = tempInt; pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE); @@ -1760,7 +1766,8 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } - if (priv_data.total_len <= 0) + if (priv_data.total_len <= 0 || + priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s:invalid priv_data.total_len(%d)!!!", __func__, @@ -2556,7 +2563,6 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { tANI_U8 *value = command; tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT; - tANI_U16 homeAwayTime = 0; /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */ value = value + 19; @@ -2590,21 +2596,6 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) "%s: Received Command to change channel max time = %d", __func__, maxTime); pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime; - - /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)), - * where RFS is the RF Switching time. It is twice RFS to consider the - * time to go off channel and return to the home channel. */ - homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal)); - if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)" - " Hence enforcing home away time to disable (0)", - __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))); - homeAwayTime = 0; - pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime; - sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE); - } sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime); } else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0) @@ -2793,7 +2784,6 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { tANI_U8 *value = command; tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT; - tANI_U16 scanChannelMaxTime = 0; /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */ /* input value is in units of msec */ @@ -2826,20 +2816,6 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime); - - /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)), - * where RFS is the RF Switching time. It is twice RFS to consider the - * time to go off channel and return to the home channel. */ - scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal)); - if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)" - " Hence enforcing home away time to disable (0)", - __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME))); - homeAwayTime = 0; - } - if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime) { pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime; @@ -3443,8 +3419,9 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } - if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && - (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode)) + if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && + (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) && + (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "Received WLS_BATCHING_VERSION command in invalid mode %d " @@ -3953,7 +3930,7 @@ static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue, if ('\0' == *inPtr) return -EINVAL; /*getting the first argument ie measurement token*/ - v = sscanf(inPtr, "%32s ", buf); + v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; v = kstrtos32(buf, 10, &tempInt); @@ -3979,7 +3956,7 @@ static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue, /*no ie data after the number of ie fields argument and spaces*/ if ( '\0' == *inPtr ) return -EINVAL; - v = sscanf(inPtr, "%32s ", buf); + v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; v = kstrtos32(buf, 10, &tempInt); @@ -4710,6 +4687,8 @@ void hdd_update_tgt_cfg(void *context, void *param) hdd_ctx->target_fw_version = cfg->target_fw_version; + hdd_ctx->max_intf_count = cfg->max_intf_count; + hdd_update_tgt_services(hdd_ctx, &cfg->services); hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap); @@ -4718,6 +4697,53 @@ void hdd_update_tgt_cfg(void *context, void *param) hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap); #endif /* #ifdef WLAN_FEATURE_11AC */ } + +/* This function is invoked when a radar in found on the + * SAP current operating channel and Data Tx from netif + * has to be stopped to honor the DFS regulations. + * Actions: Stop the netif Tx queues,Indicate Radar present + * in HDD context for future usage. + */ +void hdd_dfs_indicate_radar(void *context, void *param) +{ + hdd_context_t *pHddCtx= (hdd_context_t *)context; + struct hdd_dfs_radar_ind *hdd_radar_event = + (struct hdd_dfs_radar_ind*)param; + hdd_adapter_list_node_t *pAdapterNode = NULL, + *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + if (pHddCtx == NULL) + { + return; + } + if (hdd_radar_event == NULL) + { + return; + } + + if (VOS_TRUE == hdd_radar_event->dfs_radar_status) + { + pHddCtx->dfs_radar_found = VOS_TRUE; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if (WLAN_HDD_SOFTAP == pAdapter->device_mode) + { + netif_tx_stop_all_queues(pAdapter->dev); + return; + } + else + { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + } + } +} #endif /* QCA_WIFI_2_0 && !QCA_WIFI_ISOC */ /**--------------------------------------------------------------------------- @@ -4748,8 +4774,8 @@ VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApB int v = 0; tANI_U8 tempBuf[32]; tANI_U8 tempByte = 0; - /* 12 hexa decimal digits and 5 ':' */ - tANI_U8 macAddress[17]; + /* 12 hexa decimal digits, 5 ':' and '\0' */ + tANI_U8 macAddress[18]; inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); @@ -4804,7 +4830,7 @@ VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApB } /*getting the next argument ie the channel number */ - v = sscanf(inPtr, "%32s ", tempBuf); + v = sscanf(inPtr, "%31s ", tempBuf); if (1 != v) return -EINVAL; v = kstrtos32(tempBuf, 10, &tempInt); @@ -4827,11 +4853,11 @@ VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApB } /*getting the next argument ie the dwell time */ - v = sscanf(inPtr, "%32s ", tempBuf); + v = sscanf(inPtr, "%31s ", tempBuf); if (1 != v) return -EINVAL; v = kstrtos32(tempBuf, 10, &tempInt); - if ( v < 0 || tempInt <= 0) return -EINVAL; + if ( v < 0 || tempInt < 0) return -EINVAL; *pDwellTime = tempInt; @@ -4942,7 +4968,7 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } /*getting the first argument ie the number of channels*/ - v = sscanf(inPtr, "%32s ", buf); + v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; v = kstrtos32(buf, 10, &tempInt); @@ -4993,7 +5019,7 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } } - v = sscanf(inPtr, "%32s ", buf); + v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; v = kstrtos32(buf, 10, &tempInt); @@ -5035,8 +5061,8 @@ VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, int tempInt; int v = 0; tANI_U8 tempBuf[32]; - /* 12 hexa decimal digits and 5 ':' */ - tANI_U8 macAddress[17]; + /* 12 hexa decimal digits, 5 ':' and '\0' */ + tANI_U8 macAddress[18]; inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); @@ -5091,7 +5117,7 @@ VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, } /*getting the next argument ie the channel number */ - v = sscanf(inPtr, "%32s ", tempBuf); + v = sscanf(inPtr, "%31s ", tempBuf); if (1 != v) return -EINVAL; v = kstrtos32(tempBuf, 10, &tempInt); @@ -5223,7 +5249,6 @@ v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr) } else { - separator = -1; /* Invalid MAC found */ return 0; } @@ -6495,6 +6520,16 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type); + if (pHddCtx->current_intf_count >= pHddCtx->max_intf_count){ + /* Max limit reached on the number of vdevs configured by the host. + * Return error + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d", + __func__,pHddCtx->current_intf_count, pHddCtx->max_intf_count); + return NULL; + } + /* * If Powersave Offload is enabled * Fw will take care incase of concurrency @@ -6695,6 +6730,10 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__); goto err_free_netdev; } + + /* Adapter successfully added. Increment the vdev count */ + pHddCtx->current_intf_count++; + } return pAdapter; @@ -6760,6 +6799,10 @@ VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, hdd_remove_adapter( pHddCtx, pAdapterNode ); vos_mem_free( pAdapterNode ); + /* Adapter removed. Decrement vdev count */ + if (pHddCtx->current_intf_count != 0) + pHddCtx->current_intf_count--; + #ifdef FEATURE_WLAN_TDLS mutex_unlock(&pHddCtx->tdls_lock); #endif @@ -8511,8 +8554,8 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) adf_ctx = vos_mem_malloc(sizeof(*adf_ctx)); if (!adf_ctx) { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to allocate adf_ctx"); - goto err_free_hdd_context; + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to allocate adf_ctx", __func__); + goto err_free_hdd_context; } vos_mem_zero(adf_ctx, sizeof(*adf_ctx)); #ifdef QCA_WIFI_ISOC @@ -8547,6 +8590,9 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) goto err_config; } + pHddCtx->current_intf_count=0; + pHddCtx->max_intf_count = WLAN_MAX_INTERFACES; + #ifndef QCA_WIFI_2_0 pHddCtx->cfg_ini->maxWoWFilters = WOWL_MAX_PTRNS_ALLOWED; #endif @@ -8720,6 +8766,19 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) goto err_vosclose; } + if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) + { + pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d", + __func__, enable_dfs_chan_scan); + } + if (0 == enable_11d || 1 == enable_11d) + { + pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d", + __func__, enable_11d); + } + /* Note that the vos_preStart() sequence triggers the cfg download. The cfg download must occur before we update the SME config since the SME config operation must access the cfg database */ @@ -8743,19 +8802,6 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) the INI file and from NV before vOSS has been started so that the final contents are available to send down to the cCPU */ - if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) - { - pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan; - hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d", - __func__, enable_dfs_chan_scan); - } - if (0 == enable_11d || 1 == enable_11d) - { - pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d; - hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d", - __func__, enable_11d); - } - // Apply the cfg.ini to cfg.dat if (FALSE == hdd_update_config_dat(pHddCtx)) { @@ -8973,24 +9019,32 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) if (country_code) { eHalStatus ret; + + INIT_COMPLETION(pAdapter->change_country_code); hdd_checkandupdate_dfssetting(pAdapter, country_code); #ifndef CONFIG_ENABLE_LINUX_REG hdd_checkandupdate_phymode(pAdapter, country_code); #endif - ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL, - country_code, - pAdapter, pHddCtx->pvosContext, - eSIR_TRUE, eSIR_TRUE); + ret = sme_ChangeCountryCode(pHddCtx->hHal, + (void *)(tSmeChangeCountryCallback) + wlan_hdd_change_country_code_callback, + country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE); if (eHAL_STATUS_SUCCESS == ret) { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: SME Change Country code from module param fail ret=%d", - __func__, ret); + ret = wait_for_completion_interruptible_timeout( + &pAdapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (0 >= ret) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME while setting country code timed out", __func__); + } } else { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: module country code set to %c%c", - __func__, country_code[0], country_code[1]); + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME Change Country code from module param fail ret=%d", __func__, ret); + ret = -EINVAL; } } diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c index 1e4a7deded7a..71ae70988494 100644 --- a/CORE/HDD/src/wlan_hdd_p2p.c +++ b/CORE/HDD/src/wlan_hdd_p2p.c @@ -99,18 +99,42 @@ static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, tANI_U32 nFrameLength, tANI_U8* pbFrames, tANI_U8 frameType ); -#ifdef QCA_WIFI_2_0 -static bool hdd_p2p_is_action_type_rsp( tActionFrmType actionFrmType ) + +static bool hdd_p2p_is_action_type_rsp( const u8 *buf ) { - if ( actionFrmType != WLAN_HDD_GO_NEG_REQ && - actionFrmType != WLAN_HDD_INVITATION_REQ && - actionFrmType != WLAN_HDD_DEV_DIS_REQ && - actionFrmType != WLAN_HDD_PROV_DIS_REQ ) - return TRUE; - else - return FALSE; + tActionFrmType actionFrmType; + const u8 *ouiPtr; + + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] != + WLAN_HDD_PUBLIC_ACTION_FRAME ) { + return VOS_FALSE; + } + + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] != + WLAN_HDD_VENDOR_SPECIFIC_ACTION ) { + return VOS_FALSE; + } + + ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET]; + + if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) { + return VOS_FALSE; + } + + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] != + WLAN_HDD_WFA_P2P_OUI_TYPE ) { + return VOS_FALSE; + } + + actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; + if ( actionFrmType != WLAN_HDD_INVITATION_REQ && + actionFrmType != WLAN_HDD_GO_NEG_REQ && + actionFrmType != WLAN_HDD_DEV_DIS_REQ && + actionFrmType != WLAN_HDD_PROV_DIS_REQ ) + return VOS_TRUE; + else + return VOS_FALSE; } -#endif eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx, eHalStatus status ) @@ -129,12 +153,9 @@ eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx, hddLog( LOG1, "Received remain on channel rsp"); cfgState->remain_on_chan_ctx = NULL; -#ifdef QCA_WIFI_2_0 + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request && !pAdapter->internalCancelRemainOnChReq ) -#else - if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request ) -#endif { if( cfgState->buf ) { @@ -155,9 +176,7 @@ eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx, #endif GFP_KERNEL); } -#ifdef QCA_WIFI_2_0 pAdapter->internalCancelRemainOnChReq = VOS_FALSE; -#endif if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) || ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) || @@ -431,6 +450,11 @@ void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ) if( pRemainChanCtx != NULL ) { + // Removing READY_EVENT_PROPOGATE_TIME from current time which gives + // more accurate Remain on Channel start time. + pRemainChanCtx->p2pRemOnChanTimeStamp = + vos_timer_get_system_time() - READY_EVENT_PROPOGATE_TIME; + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request ) { cfg80211_ready_on_channel( @@ -719,32 +743,46 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, if( offchan && wait) { int status; + tANI_U32 current_time = vos_timer_get_system_time(); // In case of P2P Client mode if we are already // on the same channel then send the frame directly -#ifdef QCA_WIFI_2_0 //For remain on channel we issue a passive scan to firmware //but currently there is no provision for dynamically extending //the dwell time therefore cancelling the ongoing remain on channel //and requesting for new one. //The below logic will be extended for request type action frames if //needed in future. - if ( (type == SIR_MAC_MGMT_FRAME) && + if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && - (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == - WLAN_HDD_PUBLIC_ACTION_FRAME) ) { + hdd_p2p_is_action_type_rsp(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET]) && + cfgState->remain_on_chan_ctx && + cfgState->current_freq == chan->center_freq ) { + + // In case of P2P Client mode if we are already + // on the same channel then send the frame directly only if + // there is enough remain on channel time left. + // If remain on channel time is about to expire in next 50ms + // then dont send frame without a fresh remain on channel as this may + // cause a race condition with lim remain_on_channel_timer which might + // expire by the time the action frame reaches lim layer. + + // Check remaining time of RoC only in case of GO NEG CNF. + actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; - if ( actionFrmType < MAX_P2P_ACTION_FRAME_TYPE && - hdd_p2p_is_action_type_rsp(actionFrmType) && - cfgState->remain_on_chan_ctx && - cfgState->current_freq == chan->center_freq ) { + + if ((actionFrmType != WLAN_HDD_GO_NEG_CNF) || + ((current_time - cfgState->remain_on_chan_ctx->p2pRemOnChanTimeStamp) > + (cfgState->remain_on_chan_ctx->duration - 50 ))) + { + hddLog(LOG1,"action frame: Extending the RoC\n"); status = wlan_hdd_check_remain_on_channel(pAdapter); if ( !status ) pAdapter->internalCancelRemainOnChReq = VOS_TRUE; } } -#endif + if((cfgState->remain_on_chan_ctx != NULL) && (cfgState->current_freq == chan->center_freq) ) @@ -1291,7 +1329,7 @@ int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, { hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - return NULL; + return ERR_PTR(-ENOSPC); #else return -EINVAL; #endif diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index e909b2d69f33..7d269b724701 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -1103,13 +1103,28 @@ VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext, return VOS_STATUS_E_FAILURE; } - pAdapter = pHddCtx->sta_to_adapter[*pStaId]; - if( NULL == pAdapter ) + STAId = *pStaId; + if (STAId >= WLAN_MAX_STA_COUNT) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid STAId %d passed by TL", __func__, STAId); + return VOS_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[STAId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } + if (FALSE == pAdapter->aStaInfo[STAId].isUsed ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Unregistered STAId %d passed by TL", __func__, STAId); + return VOS_STATUS_E_FAILURE; + } + /* Monitor traffic */ if ( pHddCtx->cfg_ini->enableTrafficMonitor ) { @@ -1132,21 +1147,6 @@ VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext, ++pAdapter->hdd_stats.hddTxRxStats.txFetched; - STAId = *pStaId; - if (STAId >= WLAN_MAX_STA_COUNT) - { - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, - "%s: Invalid STAId %d passed by TL", __func__, STAId); - return VOS_STATUS_E_FAILURE; - } - - if (FALSE == pAdapter->aStaInfo[STAId].isUsed ) - { - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, - "%s: Unregistered STAId %d passed by TL", __func__, STAId); - return VOS_STATUS_E_FAILURE; - } - *ppVosPacket = NULL; //Make sure the AC being asked for is sane diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c index 7e9c5e6d2a20..f8f7e6cd42de 100644 --- a/CORE/HDD/src/wlan_hdd_tdls.c +++ b/CORE/HDD/src/wlan_hdd_tdls.c @@ -30,10 +30,6 @@ \brief WLAN Host Device Driver implementation for TDLS - Copyright (c) 2012-2013 Qualcomm Atheros, Inc. - All Rights Reserved. - Qualcomm Atheros Confidential and Proprietary. - ========================================================================*/ #include <wlan_hdd_includes.h> diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index f57be8db267c..f9fcd0a9b4c9 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -1304,7 +1304,7 @@ VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext, } pAdapter = pHddCtx->sta_to_adapter[*pStaId]; - if( NULL == pAdapter ) + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index c092193455f6..e2c9a60dd69d 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -203,6 +203,15 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_PPS_GID_NSTS_ZERO 52 #define WE_PPS_RSSI_CHECK 53 #define WE_ENABLE_STRICT_FCC_REG 54 +#define WE_SET_HTSMPS 55 +/* Private ioctl for QPower */ +#define WE_SET_QPOWER_MAX_PSPOLL_COUNT 56 +#define WE_SET_QPOWER_MAX_TX_BEFORE_WAKE 57 +#define WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL 58 +#define WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL 59 + +#define WE_SET_BURST_ENABLE 60 +#define WE_SET_BURST_DUR 61 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) @@ -246,6 +255,14 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_GET_PPS_DELIM_CRC_FAIL 38 #define WE_GET_PPS_GID_NSTS_ZERO 39 #define WE_GET_PPS_RSSI_CHECK 40 +/* Private ioctl for QPower */ +#define WE_GET_QPOWER_MAX_PSPOLL_COUNT 41 +#define WE_GET_QPOWER_MAX_TX_BEFORE_WAKE 42 +#define WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL 43 +#define WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL 44 + +#define WE_GET_BURST_ENABLE 45 +#define WE_GET_BURST_DUR 46 #endif /* Private ioctls and their sub-ioctls */ @@ -261,6 +278,8 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_SET_AP_WPS_IE 4 //This is called in station mode to set probe rsp ie. #define WE_SET_CONFIG 5 +#define WLAN_PRIV_SET_CHAR_GET_NONE_BUFF_MAX 512 + /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 4) #define WE_SET_WLAN_DBG 1 @@ -396,6 +415,10 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #endif #define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31) +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28) +#define WE_SET_SMPS_PARAM 1 + #define WLAN_STATS_INVALID 0 #define WLAN_STATS_RETRY_CNT 1 #define WLAN_STATS_MUL_RETRY_CNT 2 @@ -1662,7 +1685,8 @@ static int iw_get_bitrate(struct net_device *dev, SME_GLOBAL_CLASSD_STATS | SME_PER_STA_STATS, hdd_StatisticsCB, 0, FALSE, - pHddStaCtx->conn_info.staId[0], pAdapter ); + pHddStaCtx->conn_info.staId[0], pAdapter, + pAdapter->sessionId ); if(eHAL_STATUS_SUCCESS != status) { @@ -2400,7 +2424,8 @@ VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) 0, // not periodic FALSE, //non-cached results pHddStaCtx->conn_info.staId[0], - &context); + &context, + pAdapter->sessionId ); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -2516,7 +2541,8 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) 0, // not periodic FALSE, //non-cached results pHddStaCtx->conn_info.staId[0], - &context); + &context, + pAdapter->sessionId); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -4819,6 +4845,31 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf break; } + case WE_SET_BURST_ENABLE: + { + hddLog(LOG1, "SET Burst enable val %d", set_value); + if ((set_value == 0) || (set_value == 1)) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + set_value, PDEV_CMD); + } + else + ret = -EINVAL; + break; + } + case WE_SET_BURST_DUR: + { + hddLog(LOG1, "SET Burst duration val %d", set_value); + if ((set_value > 0) && (set_value <= 8192)) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_DUR, + set_value, PDEV_CMD); + } + else + ret = -EINVAL; + break; + } + case WE_SET_TX_CHAINMASK: { hddLog(LOG1, "WMI_PDEV_PARAM_TX_CHAIN_MASK val %d", set_value); @@ -4963,7 +5014,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_PAID_MATCH val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_PAID_MATCH, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -4974,7 +5025,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_GID_MATCH val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_GID_MATCH, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -4985,7 +5036,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, " WMI_VDEV_PPS_EARLY_TIM_CLEAR val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -4996,7 +5047,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_EARLY_DTIM_CLEAR val %d", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -5007,7 +5058,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_EOF_PAD_DELIM val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_EOF_PAD_DELIM, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -5018,7 +5069,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_MACADDR_MISMATCH val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_MACADDR_MISMATCH, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -5029,7 +5080,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_DELIM_CRC_FAIL val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -5041,7 +5092,7 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_GID_NSTS_ZERO val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_GID_NSTS_ZERO, - set_value, VDEV_CMD); + set_value, PPS_CMD); break; } @@ -5053,7 +5104,57 @@ static int iw_setint_getnone(struct net_device *dev, struct iw_request_info *inf hddLog(LOG1, "WMI_VDEV_PPS_RSSI_CHECK val %d ", set_value); ret = process_wma_set_command((int)pAdapter->sessionId, (int)WMI_VDEV_PPS_RSSI_CHECK, - set_value, VDEV_CMD); + set_value, PPS_CMD); + break; + } + + case WE_SET_HTSMPS: + { + hddLog(LOG1, "WE_SET_HTSMPS val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_SMPS_FORCE_MODE_CMDID, + set_value, VDEV_CMD); + break; + } + + + case WE_SET_QPOWER_MAX_PSPOLL_COUNT: + { + hddLog(LOG1, "WE_SET_QPOWER_MAX_PSPOLL_COUNT val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + set_value, QPOWER_CMD); + break; + } + + case WE_SET_QPOWER_MAX_TX_BEFORE_WAKE: + { + hddLog(LOG1, "WE_SET_QPOWER_MAX_TX_BEFORE_WAKE val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE, + set_value, QPOWER_CMD); + break; + } + + case WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + { + hddLog(LOG1, "WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + set_value, QPOWER_CMD); + break; + } + + case WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + { + hddLog(LOG1, "WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + set_value, QPOWER_CMD); break; } @@ -5080,9 +5181,7 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in #ifdef WLAN_FEATURE_VOWIFI hdd_config_t *pConfig = pHddCtx->cfg_ini; #endif /* WLAN_FEATURE_VOWIFI */ - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received length %d", __func__, wrqu->data.length); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received data %s", __func__, extra); + char usr_buf[WLAN_PRIV_SET_CHAR_GET_NONE_BUFF_MAX]; if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { @@ -5091,15 +5190,32 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in return -EBUSY; } + if (wrqu->data.length > WLAN_PRIV_SET_CHAR_GET_NONE_BUFF_MAX) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Length of user data is too big", __func__); + return -E2BIG; + } + + if (copy_from_user(&usr_buf, wrqu->data.pointer, wrqu->data.length)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Copy from user failed", __func__); + return -EFAULT; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received length %d", __func__, wrqu->data.length); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received data %s", __func__, usr_buf); + switch(sub_cmd) { case WE_WOWL_ADD_PTRN: VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "ADD_PTRN\n"); - hdd_add_wowl_ptrn(pAdapter, extra); + hdd_add_wowl_ptrn(pAdapter, usr_buf); break; case WE_WOWL_DEL_PTRN: VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN\n"); - hdd_del_wowl_ptrn(pAdapter, extra); + hdd_del_wowl_ptrn(pAdapter, usr_buf); break; #if defined WLAN_FEATURE_VOWIFI case WE_NEIGHBOR_REPORT_REQUEST: @@ -5114,7 +5230,7 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in if( !neighborReq.no_ssid ) { neighborReq.ssid.length = (wrqu->data.length - 1) > 32 ? 32 : (wrqu->data.length - 1) ; - vos_mem_copy( neighborReq.ssid.ssId, extra, neighborReq.ssid.length ); + vos_mem_copy( neighborReq.ssid.ssId, usr_buf, neighborReq.ssid.length ); } callbackInfo.neighborRspCallback = NULL; @@ -5132,10 +5248,10 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in #endif case WE_SET_AP_WPS_IE: hddLog( LOGE, "Received WE_SET_AP_WPS_IE" ); - sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), extra, wrqu->data.length ); + sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), &usr_buf, wrqu->data.length ); break; case WE_SET_CONFIG: - vstatus = hdd_execute_config_command(pHddCtx, extra); + vstatus = hdd_execute_config_command(pHddCtx, usr_buf); if (VOS_STATUS_SUCCESS != vstatus) { ret = -EINVAL; @@ -5396,6 +5512,25 @@ static int iw_setnone_getint(struct net_device *dev, struct iw_request_info *inf break; } + case WE_GET_BURST_ENABLE: + { + hddLog(LOG1, "GET Burst enable value"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + PDEV_CMD); + break; + } + case WE_GET_BURST_DUR: + { + hddLog(LOG1, "GET Burst Duration value"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_DUR, + PDEV_CMD); + break; + } + case WE_GET_TX_CHAINMASK: { hddLog(LOG1, "GET WMI_PDEV_PARAM_TX_CHAIN_MASK"); @@ -5462,6 +5597,137 @@ static int iw_setnone_getint(struct net_device *dev, struct iw_request_info *inf break; } + case WE_GET_PPS_PAID_MATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_PAID_MATCH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_PAID_MATCH, + PPS_CMD); + break; + } + + case WE_GET_PPS_GID_MATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_GID_MATCH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_GID_MATCH, + PPS_CMD); + break; + } + + case WE_GET_PPS_EARLY_TIM_CLEAR: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_TIM_CLEAR"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, + PPS_CMD); + break; + } + + case WE_GET_PPS_EARLY_DTIM_CLEAR: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_DTIM_CLEAR"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, + PPS_CMD); + break; + } + + case WE_GET_PPS_EOF_PAD_DELIM: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_EOF_PAD_DELIM"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EOF_PAD_DELIM, + PPS_CMD); + break; + } + + case WE_GET_PPS_MACADDR_MISMATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_MACADDR_MISMATCH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_MACADDR_MISMATCH, + PPS_CMD); + break; + } + + case WE_GET_PPS_DELIM_CRC_FAIL: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_DELIM_CRC_FAIL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, + PPS_CMD); + break; + } + + case WE_GET_PPS_GID_NSTS_ZERO: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_GID_NSTS_ZERO"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_GID_NSTS_ZERO, + PPS_CMD); + break; + } + + case WE_GET_PPS_RSSI_CHECK: + { + + hddLog(LOG1, "GET WMI_VDEV_PPS_RSSI_CHECK"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_RSSI_CHECK, + PPS_CMD); + break; + } + + case WE_GET_QPOWER_MAX_PSPOLL_COUNT: + { + hddLog(LOG1, "WE_GET_QPOWER_MAX_PSPOLL_COUNT"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + QPOWER_CMD); + break; + } + + case WE_GET_QPOWER_MAX_TX_BEFORE_WAKE: + { + hddLog(LOG1, "WE_GET_QPOWER_MAX_TX_BEFORE_WAKE"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE, + QPOWER_CMD); + break; + } + + case WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + { + hddLog(LOG1, "WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + QPOWER_CMD); + break; + } + + case WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + { + hddLog(LOG1, "WE_GET_QPOWER_MAX_PSPOLL_COUNT"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + QPOWER_CMD); + break; + } + #endif default: @@ -6101,90 +6367,7 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in break; } - case WE_GET_PPS_PAID_MATCH: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_PAID_MATCH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_PAID_MATCH, - VDEV_CMD); - break; - } - case WE_GET_PPS_GID_MATCH: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_GID_MATCH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_GID_MATCH, - VDEV_CMD); - break; - } - case WE_GET_PPS_EARLY_TIM_CLEAR: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_TIM_CLEAR"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, - VDEV_CMD); - break; - } - case WE_GET_PPS_EARLY_DTIM_CLEAR: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_DTIM_CLEAR"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, - VDEV_CMD); - break; - } - case WE_GET_PPS_EOF_PAD_DELIM: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_EOF_PAD_DELIM"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_EOF_PAD_DELIM, - VDEV_CMD); - break; - } - case WE_GET_PPS_MACADDR_MISMATCH: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_MACADDR_MISMATCH"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_MACADDR_MISMATCH, - VDEV_CMD); - break; - } - case WE_GET_PPS_DELIM_CRC_FAIL: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_DELIM_CRC_FAIL"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, - VDEV_CMD); - break; - } - case WE_GET_PPS_GID_NSTS_ZERO: - { - hddLog(LOG1, "GET WMI_VDEV_PPS_GID_NSTS_ZERO"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_GID_NSTS_ZERO, - VDEV_CMD); - break; - } - case WE_GET_PPS_RSSI_CHECK: - { - - hddLog(LOG1, "GET WMI_VDEV_PPS_RSSI_CHECK"); - *value = wma_cli_get_command(wmapvosContext, - (int)pAdapter->sessionId, - (int)WMI_VDEV_PPS_RSSI_CHECK, - VDEV_CMD); - break; - } #endif - case WE_ENABLE_DXE_STALL_DETECT: { tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -7720,7 +7903,9 @@ static int iw_get_statistics(struct net_device *dev, SME_GLOBAL_CLASSD_STATS | SME_PER_STA_STATS, hdd_StatisticsCB, 0, FALSE, - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter ); + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + pAdapter, + pAdapter->sessionId ); if (eHAL_STATUS_SUCCESS != status) { @@ -7747,7 +7932,9 @@ static int iw_get_statistics(struct net_device *dev, SME_GLOBAL_CLASSD_STATS | SME_PER_STA_STATS, NULL, 0, FALSE, - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter ); + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + pAdapter, + pAdapter->sessionId ); return -EINVAL; } @@ -8337,9 +8524,6 @@ int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr) hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId); sme_ScanFlushResult(hHal, pAdapter->sessionId); -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - sme_UpdateBgScanConfigIniChannelList(hHal, (eCsrBand) band); -#endif if (eHAL_STATUS_SUCCESS != sme_SetFreqBand(hHal, (eCsrBand)band)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, @@ -8530,6 +8714,41 @@ VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *i return VOS_STATUS_SUCCESS; }/*iw_set_power_params*/ +int iw_set_two_ints_getnone(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int *value = (int *)extra; + int sub_cmd = value[0]; + int ret = 0; + + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + + switch(sub_cmd) + { + case WE_SET_SMPS_PARAM: + { + hddLog(LOG1, "WE_SET_SMPS_PARAM val %d %d", value[1], value[2]); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_SMPS_PARAM_CMDID, + value[1] << WMA_SMPS_PARAM_VALUE_S | value[2], VDEV_CMD); + break; + } + + default: + { + hddLog(LOGE, "Invalid IOCTL command %d", sub_cmd); + break; + } + } + return ret; +} + // Define the Wireless Extensions to the Linux Network Device structure // A number of these routines are NULL (meaning they are not implemented.) @@ -8643,6 +8862,7 @@ static const iw_handler we_private[] = { #endif #endif [WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed, + [WLAN_PRIV_SET_TWO_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_two_ints_getnone, }; /*Maximum command length can be only 15 */ @@ -8827,6 +9047,16 @@ static const struct iw_priv_args we_private_args[] = { 0, "amsdu" }, + { WE_SET_BURST_ENABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "burst_enable" }, + + { WE_SET_BURST_DUR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "burst_dur" }, + { WE_SET_TXPOW_2G, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, @@ -8935,6 +9165,28 @@ static const struct iw_priv_args we_private_args[] = { { WE_PPS_RSSI_CHECK, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_chk" }, + + { WE_SET_HTSMPS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "htsmps" }, + + + { WE_SET_QPOWER_MAX_PSPOLL_COUNT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qpspollcnt" }, + + { WE_SET_QPOWER_MAX_TX_BEFORE_WAKE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qtxwake" }, + + { WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qwakeintv" }, + + { WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qnodatapoll" }, + #endif { WLAN_PRIV_SET_NONE_GET_INT, @@ -9079,6 +9331,16 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_amsdu" }, + { WE_GET_BURST_ENABLE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_burst_en" }, + + { WE_GET_BURST_DUR, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_burst_dur" }, + { WE_GET_TXPOW_2G, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -9146,6 +9408,27 @@ static const struct iw_priv_args we_private_args[] = { 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_chk"}, + + { WE_GET_QPOWER_MAX_PSPOLL_COUNT, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qpspollcnt"}, + + { WE_GET_QPOWER_MAX_TX_BEFORE_WAKE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qtxwake"}, + + { WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qwakeintv"}, + + { WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qnodatapoll"}, + #endif /* handlers for main ioctl */ @@ -9517,6 +9800,16 @@ static const struct iw_priv_args we_private_args[] = { WLAN_GET_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, + + /* handlers for main ioctl */ + { WLAN_PRIV_SET_TWO_INT_GET_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, + "" }, + { WE_SET_SMPS_PARAM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_smps_param" }, + }; diff --git a/CORE/HDD/src/wlan_hdd_wmm.c b/CORE/HDD/src/wlan_hdd_wmm.c index c809e8686ec4..ff0bede2fbae 100644 --- a/CORE/HDD/src/wlan_hdd_wmm.c +++ b/CORE/HDD/src/wlan_hdd_wmm.c @@ -181,7 +181,9 @@ static void hdd_wmm_enable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext) } // are we in the appropriate power save modes? - if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_BEACON_MODE_POWER_SAVE)) + if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + ePMC_BEACON_MODE_POWER_SAVE)) { VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, "%s: BMPS is not enabled", @@ -189,7 +191,9 @@ static void hdd_wmm_enable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext) return; } - if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), ePMC_UAPSD_MODE_POWER_SAVE)) + if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + ePMC_UAPSD_MODE_POWER_SAVE)) { VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, "%s: U-APSD is not enabled", diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h index 152ca3253eab..5b637bd24d36 100644 --- a/CORE/MAC/inc/aniGlobal.h +++ b/CORE/MAC/inc/aniGlobal.h @@ -248,6 +248,7 @@ typedef struct sLimTimers * for a period of time on a particular DFS channel */ TX_TIMER gLimActiveToPassiveChannelTimer; + //********************TIMER SECTION ENDS************************************************** // ALL THE FIELDS BELOW THIS CAN BE ZEROED OUT in limInitialize //**************************************************************************************** @@ -911,6 +912,10 @@ tLimMlmOemDataRsp *gpLimMlmOemDataRsp; tSirDFSChannelList dfschannelList; tANI_U8 deauthMsgCnt; tANI_U8 gLimIbssStaLimit; + + /* Number of channel switch IEs sent so far */ + tANI_U8 gLimDfsChanSwTxCount; + tANI_U8 gLimDfsTargetChanNum; } tAniSirLim, *tpAniSirLim; typedef struct sLimMgmtFrameRegistration diff --git a/CORE/MAC/inc/qwlan_version.h b/CORE/MAC/inc/qwlan_version.h index 96e6baa38e77..a7005395ecaa 100644 --- a/CORE/MAC/inc/qwlan_version.h +++ b/CORE/MAC/inc/qwlan_version.h @@ -24,6 +24,7 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ + #ifndef QWLAN_VERSION_H #define QWLAN_VERSION_H /*=========================================================================== @@ -40,9 +41,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MAJOR 4 #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 -#define QWLAN_VERSION_EXTRA "D" -#define QWLAN_VERSION_BUILD 68 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 72 -#define QWLAN_VERSIONSTR "4.0.0.68D" +#define QWLAN_VERSIONSTR "4.0.0.72" #endif /* QWLAN_VERSION_H */ diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h index 1e612e8f808d..a2750c146f2e 100644 --- a/CORE/MAC/inc/sirApi.h +++ b/CORE/MAC/inc/sirApi.h @@ -2102,6 +2102,7 @@ typedef struct sAniGetPEStatsReq tANI_U16 msgLen; // length of the entire request tANI_U32 staId; // Per STA stats request must contain valid tANI_U32 statsMask; // categories of stats requested. look at ePEStatsMask + tANI_U8 sessionId; } tAniGetPEStatsReq, *tpAniGetPEStatsReq; /* @@ -4736,4 +4737,63 @@ typedef struct sSirChAvoidIndType } tSirChAvoidIndType; #endif /* FEATURE_WLAN_CH_AVOID */ +typedef struct sSirSmeDfsEventInd +{ + tANI_U32 sessionId; + tANI_U8 ieee_chan_number; + tANI_U32 chan_freq; + tANI_U32 dfs_radar_status; + int use_nol; +}tSirSmeDfsEventInd, *tpSirSmeDfsEventInd; + +typedef struct sSirChanChangeRequest +{ + tANI_U16 messageType; + tANI_U16 messageLen; + tANI_U8 sessionId; + tANI_U8 targetChannel; +}tSirChanChangeRequest, *tpSirChanChangeRequest; + +typedef struct sSirChanChangeResponse +{ + tANI_U8 sessionId; + tANI_U8 newChannelNumber; + tANI_U8 channelChangeStatus; + ePhyChanBondState secondaryChannelOffset; +}tSirChanChangeResponse, *tpSirChanChangeResponse; + +typedef struct sSirStartBeaconIndication +{ + tANI_U16 messageType; + tANI_U16 messageLen; + tANI_U8 sessionId; + tANI_U8 beaconStartStatus; +}tSirStartBeaconIndication, *tpSirStartBeaconIndication; + +/* Message format for requesting channel switch announcement to lower layers */ +typedef struct sSirDfsCsaIeRequest +{ + tANI_U16 msgType; + tANI_U16 msgLen; + tANI_U8 sessionId; + tANI_U8 targetChannel; + tANI_U8 csaIeRequired; +}tSirDfsCsaIeRequest, *tpSirDfsCsaIeRequest; + +/* Indication from lower layer indicating the completion of first beacon send + * after the beacon template update + */ +typedef struct sSirFirstBeaconTxCompleteInd +{ + tANI_U16 messageType; // eWNI_SME_MISSED_BEACON_IND + tANI_U16 length; + tANI_U8 bssIdx; +}tSirFirstBeaconTxCompleteInd, *tpSirFirstBeaconTxCompleteInd; + +typedef struct sSirSmeCSAIeTxCompleteRsp +{ + tANI_U8 sessionId; + tANI_U8 chanSwIeTxStatus; +}tSirSmeCSAIeTxCompleteRsp, *tpSirSmeCSAIeTxCompleteRsp; + #endif /* __SIR_API_H */ diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h index 68fa22a30b46..87d5e5b1d0f8 100644 --- a/CORE/MAC/inc/wniApi.h +++ b/CORE/MAC/inc/wniApi.h @@ -380,6 +380,14 @@ enum eWniMsgTypes #ifdef FEATURE_WLAN_CH_AVOID eWNI_SME_CH_AVOID_IND, #endif /* FEATURE_WLAN_CH_AVOID */ + /* DFS EVENTS */ + eWNI_SME_DFS_RADAR_FOUND, //RADAR found indication from DFS + eWNI_SME_CHANNEL_CHANGE_REQ,//Channel Change Request from SAP + eWNI_SME_CHANNEL_CHANGE_RSP,// Channel Change Response from WMA + eWNI_SME_START_BEACON_REQ,//Start Beacon Transmission. + eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ, //Transmit CSA IE in beacons + eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND, //To indicate completion of CSA IE + //update in beacons/probe rsp eWNI_SME_MSG_TYPES_END }; diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index 33ed8bed778a..f12920f14a66 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -634,6 +634,10 @@ typedef struct sSirMbMsgP2p #endif #endif +/* Handling of beacon tx indication from FW */ +#define SIR_HAL_BEACON_TX_SUCCESS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 242) +#define SIR_HAL_DFS_RADAR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 243) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) // CFG message types @@ -737,6 +741,7 @@ typedef struct sSirMbMsgP2p #define SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2B) #endif #define SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE (SIR_LIM_TIMEOUT_MSG_START + 0x2C) + #define SIR_LIM_MSG_TYPES_END (SIR_LIM_MSG_TYPES_BEGIN+0xFF) // SCH message types diff --git a/CORE/MAC/src/pe/include/limGlobal.h b/CORE/MAC/src/pe/include/limGlobal.h index 5613a15cc73b..d3f134597e20 100644 --- a/CORE/MAC/src/pe/include/limGlobal.h +++ b/CORE/MAC/src/pe/include/limGlobal.h @@ -87,6 +87,8 @@ #define IS_5G_BAND(__rfBand) ((__rfBand & 0x3) == 0x2) #define IS_24G_BAND(__rfBand) ((__rfBand & 0x3) == 0x1) +#define LIM_MAX_CSA_IE_UPDATES ( 5 ) + // enums exported by LIM are as follows /// System role definition @@ -575,7 +577,7 @@ typedef struct sLimChannelSwitchInfo tLimChannelSwitchState state; tANI_U8 primaryChannel; ePhyChanBondState secondarySubBand; - tANI_U32 switchCount; + tANI_S8 switchCount; tANI_U32 switchTimeoutValue; tANI_U8 switchMode; } tLimChannelSwitchInfo, *tpLimChannelSwitchInfo; diff --git a/CORE/MAC/src/pe/include/limSession.h b/CORE/MAC/src/pe/include/limSession.h index bc7109ca03c5..33089ff0ce3e 100644 --- a/CORE/MAC/src/pe/include/limSession.h +++ b/CORE/MAC/src/pe/include/limSession.h @@ -413,6 +413,9 @@ typedef struct sPESession // Added to Support BT-AMP tANI_U8 smpsMode; tANI_U8 chainMask; + + /* Flag to indicate Chan Sw announcement is required */ + tANI_U8 dfsIncludeChanSwIe; }tPESession, *tpPESession; #define LIM_MAX_ACTIVE_SESSIONS 4 diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c index 9e339bd6c335..1b0bbbac2c88 100644 --- a/CORE/MAC/src/pe/lim/limApi.c +++ b/CORE/MAC/src/pe/lim/limApi.c @@ -354,9 +354,13 @@ static void __limInitAssocVars(tpAniSirGlobal pMac) { limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); } +#ifdef QCA_WIFI_2_0 + /* This +1 is done because of peerIdx assign logic in limAssignPeerIdx */ + pMac->lim.gLimAssocStaLimit = val + 1; +#else pMac->lim.gLimAssocStaLimit = val; +#endif pMac->lim.gLimIbssStaLimit = val; - // Place holder for current authentication request // being handled pMac->lim.gpLimMlmAuthReq = NULL; diff --git a/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c b/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c index f87d74690d5b..6955b3546aa1 100644 --- a/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c +++ b/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c @@ -596,7 +596,12 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_ASSOC_STA_LIMIT" )); break; } +#ifdef QCA_WIFI_2_0 + /* This +1 is done becuse of peerIdx assign logic in limAssignPeerIdx */ + pMac->lim.gLimAssocStaLimit = (tANI_U16)val1 + 1; +#else pMac->lim.gLimAssocStaLimit = (tANI_U16)val1; +#endif break; case WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC: @@ -781,7 +786,12 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) } val = WNI_CFG_ASSOC_STA_LIMIT_STADEF; } +#ifdef QCA_WIFI_2_0 + /* This +1 is done becuse of peerIdx assign logic in limAssignPeerIdx */ + pMac->lim.gLimAssocStaLimit =(tANI_U16) val + 1; +#else pMac->lim.gLimAssocStaLimit = (tANI_U16)val; +#endif #if defined WLAN_FEATURE_VOWIFI rrmUpdateConfig( pMac, psessionEntry ); diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c index 42ef0936b4db..35d1665f1260 100644 --- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c +++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -1762,6 +1762,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: limHandleUpdateOlbcCache(pMac); break; + #if 0 case SIR_LIM_WPS_OVERLAP_TIMEOUT: limProcessWPSOverlapTimeout(pMac); @@ -2066,6 +2067,37 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) break; } + case WDA_DFS_RADAR_IND: + limSendSmeDfsEventNotify(pMac, limMsg->type, + (void *)limMsg->bodyptr); + /* limmsg->bodyptr will be freed up by SME/CSR */ + break; + + case WDA_DFS_BEACON_TX_SUCCESS_IND: + limProcessBeaconTxSuccessInd(pMac, limMsg->type, + (void *)limMsg->bodyptr); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_CHANNEL_CHANGE_REQ: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_START_BEACON_REQ: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + default: vos_mem_free((v_VOID_t*)limMsg->bodyptr); limMsg->bodyptr = NULL; diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c index fd9b6267e6e2..bd1e82d9f0f9 100644 --- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -1718,7 +1718,8 @@ limMlmAddBss ( pAddBssParams->halPersona=psessionEntry->pePersona; //pass on the session persona to hal - pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled || + limIsconnectedOnDFSChannel(pMlmStartReq->channelNumber); #if defined WLAN_FEATURE_VOWIFI_11R pAddBssParams->extSetStaKeyParamValid = 0; diff --git a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c index 2fafc8383623..771fc0857ce4 100644 --- a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -345,6 +345,7 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tLimMlmStartCnf *pLimMlmStartCnf; tANI_U8 smesessionId; tANI_U16 smetransactionId; + tANI_U8 channelId; if(pMsgBuf == NULL) { @@ -410,8 +411,21 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) smesessionId,smetransactionId); if (((tLimMlmStartCnf *) pMsgBuf)->resultCode == eSIR_SME_SUCCESS) { - //Configure beacon and send beacons to HAL - limSendBeaconInd(pMac, psessionEntry); + channelId = psessionEntry->pLimStartBssReq->channelId; + + // We should start beacon transmission only if the channel + // on which we are operating is non-DFS until the channel + // availability check is done. The PE will receive an explicit + // request from upper layers to start the beacon transmission + + + if ( (eLIM_STA_IN_IBSS_ROLE == psessionEntry->limSystemRole) || + ((eLIM_AP_ROLE == psessionEntry->limSystemRole) && + (vos_nv_getChannelEnabledState(channelId) != NV_CHANNEL_DFS)) ) + { + //Configure beacon and send beacons to HAL + limSendBeaconInd(pMac, psessionEntry); + } } } @@ -3703,6 +3717,7 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) pChnlParams = (tpSwitchChannelParams) body; status = pChnlParams->status; peSessionId = pChnlParams->peSessionId; + if((psessionEntry = peFindSessionBySessionId(pMac, peSessionId))== NULL) { vos_mem_free(body); @@ -3714,7 +3729,6 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) //Store this value to use in TPC report IE. rrmCacheMgmtTxPower( pMac, pChnlParams->txMgmtPower, psessionEntry ); #endif - vos_mem_free(body); channelChangeReasonCode = psessionEntry->channelChangeReasonCode; // initialize it back to invalid id psessionEntry->chainMask = pChnlParams->chainMask; @@ -3742,9 +3756,23 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) pMac->lim.gpchangeChannelCallback(pMac, status, pMac->lim.gpchangeChannelData, psessionEntry); } break; + case LIM_SWITCH_CHANNEL_SAP_DFS: + { + /* Note: This event code specific to SAP mode + * When SAP session issues channel change as performing + * DFS, we will come here. Other sessions, for e.g. P2P + * will have to define their own event code and channel + * switch handler. This is required since the SME may + * require completely different information for P2P unlike + * SAP. + */ + limSendSmeAPChannelSwitchResp(pMac, psessionEntry, pChnlParams); + } + break; default: break; } + vos_mem_free(body); } /** * limProcessStartScanRsp() diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index 2280d94cb328..45b62e18b086 100644 --- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -100,6 +100,12 @@ static void __limProcessSmeDisassocCnf(tpAniSirGlobal, tANI_U32 *); static void __limProcessSmeDeauthReq(tpAniSirGlobal, tANI_U32 *); static void __limProcessSmeSetContextReq(tpAniSirGlobal, tANI_U32 *); static tANI_BOOLEAN __limProcessSmeStopBssReq(tpAniSirGlobal, tpSirMsgQ pMsg); +static void limProcessSmeChannelChangeRequest(tpAniSirGlobal pMac, + tANI_U32 *pMsg); +static void limProcessSmeStartBeaconReq(tpAniSirGlobal pMac, + tANI_U32 *pMsg); +static void limProcessSmeDfsCacIndication(tpAniSirGlobal pMac, tANI_U32 *pMsg); +static void limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg); void __limProcessSmeAssocCnfNew(tpAniSirGlobal, tANI_U32, tANI_U32 *); @@ -5738,6 +5744,19 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) limSendSetTxPowerReq(pMac, pMsgBuf); break ; + + case eWNI_SME_CHANNEL_CHANGE_REQ: + limProcessSmeChannelChangeRequest(pMac, pMsgBuf); + break; + + case eWNI_SME_START_BEACON_REQ: + limProcessSmeStartBeaconReq(pMac, pMsgBuf); + break; + + case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: + limProcessSmeDfsCsaIeRequest(pMac, pMsgBuf); + break; + default: vos_mem_free((v_VOID_t*)pMsg->bodyptr); pMsg->bodyptr = NULL; @@ -5746,3 +5765,212 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) return bufConsumed; } /*** end limProcessSmeReqMessages() ***/ + +/** + * limProcessSmeStartBeaconReq() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function processes SME request messages from HDD or upper layer + * application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the SME message type + * @param *pMsgBuf A pointer to the SME message buffer + * @return Boolean - TRUE - if pMsgBuf is consumed and can be freed. + * FALSE - if pMsgBuf is not to be freed. + */ +static void +limProcessSmeStartBeaconReq(tpAniSirGlobal pMac, tANI_U32 * pMsg) +{ + tpSirStartBeaconIndication pBeaconStartInd; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + + if( pMsg == NULL ) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pBeaconStartInd = (tpSirStartBeaconIndication)pMsg; + sessionId = pBeaconStartInd->sessionId; + + if((psessionEntry = peFindSessionBySessionId(pMac, sessionId)) == NULL) + { + limLog(pMac, LOGW, "Session does not exist for given sessionId %d", + pBeaconStartInd->sessionId); + return; + } + + if (pBeaconStartInd->beaconStartStatus == VOS_TRUE) + { + /* + * Currently this Indication comes from SAP + * to start Beacon Tx on a DFS channel + * since beaconing has to be done on DFS + * channel only after CAC WAIT is completed. + * On a DFS Channel LIM does not start beacon + * Tx right after the WDA_ADD_BSS_RSP. + */ + limApplyConfiguration(pMac,psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + } + else + { + limLog(pMac, LOGE,FL("Invalid Beacon Start Indication")); + return; + } +} + +static void +limProcessSmeChannelChangeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + tpSirChanChangeRequest pChannelChangeReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + tPowerdBm maxTxPwr; + if( pMsg == NULL ) + { + limLog(pMac, LOGE,FL("pMsg is NULL")); + return; + } + pChannelChangeReq = (tpSirChanChangeRequest)pMsg; + sessionId = pChannelChangeReq->sessionId; + + if((psessionEntry = peFindSessionBySessionId(pMac, sessionId)) == NULL) + { + limLog(pMac, LOGW, "Session does not exist for given sessionId %d", + pChannelChangeReq->sessionId); + return; + } + + if (eLIM_AP_ROLE == psessionEntry->limSystemRole) + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_SAP_DFS; + else + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; + + maxTxPwr = cfgGetRegulatoryMaxTransmitPower( pMac, + pChannelChangeReq->targetChannel ); + + if (pChannelChangeReq->messageType == eWNI_SME_CHANNEL_CHANGE_REQ + && + maxTxPwr != WDA_MAX_TXPOWER_INVALID) + { + /* + * Issue a set channel request with + * with channel bonding mode as + * PHY_SINGLE_CHANNEL_CENTERED + * TODO:Handle the channel bonding mode + * 40Mhz and 80Mhz Channel width for SAP + * channel change. + */ + + /* Store the New Channel Params in psessionEntry */ + if (psessionEntry->currentOperChannel != + pChannelChangeReq->targetChannel) + { + limLog(pMac, LOGW,FL("switch old chnl %d --> new chnl %d "), + psessionEntry->currentOperChannel, + pChannelChangeReq->targetChannel); + + limSetChannel(pMac, pChannelChangeReq->targetChannel, + PHY_SINGLE_CHANNEL_CENTERED, + maxTxPwr, + psessionEntry->peSessionId); + + psessionEntry->currentOperChannel = + pChannelChangeReq->targetChannel; + + /* + *TODO:As of now the supported Channel width + * is only 20Mhz. AP Channel Bonding Mode for + * 40 Mhz and 80Mhz is pending implementation. + */ + psessionEntry->htSecondaryChannelOffset = + PHY_SINGLE_CHANNEL_CENTERED; + psessionEntry->htSupportedChannelWidthSet = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + psessionEntry->htRecommendedTxWidthSet = + psessionEntry->htSupportedChannelWidthSet; + } + + } + else + { + limLog(pMac, LOGE,FL("Invalid Request/maxTxPwr")); + } +} + +/** + * limProcessSmeDfsCsaIeRequest() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function processes SME request messages from HDD or upper layer + * application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + */ +static void +limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + + tpSirDfsCsaIeRequest pDfsCsaIeRequest = (tSirDfsCsaIeRequest *)pMsg; + //tANI_U8 sessionId = pDfsCsaIeRequest->sessionId; + tpPESession psessionEntry; + int i; + + if ( pMsg == NULL ) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + for (i=0; i<pMac->lim.maxBssId; i++) + { + psessionEntry = peFindSessionBySessionId(pMac, i); + if (psessionEntry && psessionEntry->valid && + eLIM_AP_ROLE == psessionEntry->limSystemRole) + { + break; + } + } + + /* target channel */ + psessionEntry->gLimChannelSwitch.primaryChannel = + pDfsCsaIeRequest->targetChannel; + + /* Channel switch announcement needs to be included in beacon */ + psessionEntry->dfsIncludeChanSwIe = VOS_TRUE; + psessionEntry->gLimChannelSwitch.switchCount = LIM_MAX_CSA_IE_UPDATES; + + /* Send CSA IE request from here */ + if (schSetFixedBeaconFields(pMac, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to set CSA IE in beacon"));) + return; + } + + /* First beacon update request is sent here, the remaining updates are + * done when the FW responds back after sending the first beacon after + * the template update + */ + limSendBeaconInd(pMac, psessionEntry); + psessionEntry->gLimChannelSwitch.switchCount--; + + return; +} diff --git a/CORE/MAC/src/pe/lim/limRMC.c b/CORE/MAC/src/pe/lim/limRMC.c deleted file mode 100644 index b5d5f5b21dc3..000000000000 --- a/CORE/MAC/src/pe/lim/limRMC.c +++ /dev/null @@ -1,1893 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/* - * This file limRMC.c contains the code - * for processing Leader-based Protocol messages to support Reliable multicast - * - */ -#include "wniApi.h" -#include "wniCfgSta.h" -#include "cfgApi.h" -#include "sirApi.h" -#include "schApi.h" -#include "utilsApi.h" -#include "limUtils.h" -#include "limTimerUtils.h" -#include "limSendMessages.h" -#include "limSendMessages.h" -#include "limSession.h" -#include "limSessionUtils.h" -#include "wlan_qct_wda.h" -#include "wlan_qct_tli.h" -#include "limRMC.h" - -/** - * DOC: Leader Based Protocol for Reliable Multicast - * - * This protocol proposes to achieve reliability in multicast transmissions - * by having a selected multicast receiver respond with 802.11 ACKs. - * This is designed for a peer to peer application that uses the underlying - * IBSS network. The STAs in the IBSS network perform the following different - * roles to support this protocol - - * - * 1) Multicast Transmitter: - * A node that delivers MCAST packets to every nodes and performs Reliable - * Multicast algorithm as a transmitter. - * 2) Multicast Receiver: - * All nodes that receive MCAST packets - * 3) Multicast Receiver Leader: - * A node that receives MCAST packets and performs a Reliable Multicast - * algorithm by sending ACK to transmitter for every multicast frame - * received. Multicast Receiver Leader is appointed by the Multicast - * Transmitter. - * - * The implementation in this file supports the roles of both Multicast - * Transmitter and the Multicast Receiver Leader. - * - * The firmware performs the Leader Selection algorithm and provides a candidate - * list. The implementation in this file, sends vendor specific 802.11 Action - * frame to notify the selected Multicast leader. - * - * The leader sets up its data path to send 802.11 ACKs for any received - * Multicast frames belonging to the specified Multicast Group. It then sends an - * Action frame to the transmitter to acknowledge that it has accepted the - * Leader role. - * - * On receiving an acknowledgement from the leader, the transmitter sets up its - * data path to expect 802.11 ACKs for Multicast transmissions. - * - * The function limProcessRMCMessages handles messages from HDD to enable or - * disable this protocol for a Multicast Group. It handles 802.11 Action frame - * receive events for this protocol. It also responds to firmware generated - * indications and events. - */ - -#if defined WLAN_FEATURE_RELIABLE_MCAST - -/* - * RMC utility routines - */ - -/** - * __rmcGroupHashFunction() - * - *FUNCTION: - * This function is called during scan hash entry operations - * - *LOGIC: - * - *ASSUMPTIONS: - * NA - * - *NOTE: - * NA - * - * @param transmitter - address of multicast transmitter - * - * @return Hash index - */ - -static tANI_U8 -__rmcGroupHashFunction(tSirMacAddr transmitter) -{ - tANI_U16 hash; - - /* - * Generate a hash using transmitter address - */ - hash = transmitter[0] + transmitter[1] + transmitter[2] + - transmitter[3] + transmitter[4] + transmitter[5]; - - return hash & (RMC_MCAST_GROUPS_HASH_SIZE - 1); -} - -/** - * __rmcGroupLookupHashEntry() - * - *FUNCTION: - * This function is called to lookup RMC group entries - * - *LOGIC: - * - *ASSUMPTIONS: - * Should be called with lkRmcLock held. - * - *NOTE: - * NA - * - * @param groupAddr - multicast group address - * transmitter - address of multicast transmitter - * role - transmitter or leader - * - * @return pointer to tLimRmcGroupContext - */ - -static tLimRmcGroupContext * -__rmcGroupLookupHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter) -{ - tANI_U8 index; - tLimRmcGroupContext *entry; - - index = __rmcGroupHashFunction(transmitter); - - /* Pick the correct hash table based on role */ - entry = pMac->rmcContext.rmcGroupRxHashTable[index]; - - PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Lookup:[%d] transmitter " - MAC_ADDRESS_STR ), index, - MAC_ADDR_ARRAY(transmitter));) - while (entry) - { - if (vos_mem_compare(transmitter, entry->transmitter, - sizeof(v_MACADDR_t))) - { - return entry; - } - - entry = entry->next; - } - - return NULL; -} - -/** - * __rmcGroupInsertHashEntry() - * - *FUNCTION: - * This function is called to insert RMC group entry - * - *LOGIC: - * - *ASSUMPTIONS: - * Should be called with lkRmcLock held. - * - *NOTE: - * NA - * - * @param transmitter - address of multicast transmitter - * - * @return pointer to tLimRmcGroupContext - */ -static tLimRmcGroupContext * -__rmcGroupInsertHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter) -{ - tANI_U8 index; - tLimRmcGroupContext *entry; - tLimRmcGroupContext **head; - - index = __rmcGroupHashFunction(transmitter); - - PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Insert:[%d] group " MAC_ADDRESS_STR - " transmitter " MAC_ADDRESS_STR), index, - MAC_ADDR_ARRAY(mcastGroupAddr), - MAC_ADDR_ARRAY(transmitter));) - - head = &pMac->rmcContext.rmcGroupRxHashTable[index]; - - entry = __rmcGroupLookupHashEntry(pMac, transmitter); - - if (entry) - { - /* If the entry exists, return it at the end */ - PELOGE(limLog(pMac, LOGE, FL("RMC: Hash Insert:" - MAC_ADDRESS_STR "exists"), MAC_ADDR_ARRAY(transmitter));) - } - else - { - entry = (tLimRmcGroupContext *)vos_mem_malloc(sizeof(*entry)); - - PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Insert:new entry %p"), entry);) - - if (entry) - { - vos_mem_copy(entry->transmitter, transmitter, sizeof(tSirMacAddr)); - entry->isLeader = eRMC_IS_NOT_A_LEADER; - - /* chain this entry */ - entry->next = *head; - *head = entry; - } - else - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Hash Insert:" MAC_ADDRESS_STR - " alloc failed"), MAC_ADDR_ARRAY(transmitter));) - } - } - - return entry; -} - -/** - * __rmcGroupDeleteHashEntry() - * - *FUNCTION: - * This function is called to delete a RMC group entry - * - *LOGIC: - * - *ASSUMPTIONS: - * Should be called with lkRmcLock held. - * - *NOTE: - * Make sure (for the transmitter role) that the entry is - * not in the Pending Response queue. - * - * @param transmitter - address of multicast transmitter - * - * @return status - */ -static tSirRetStatus -__rmcGroupDeleteHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter) -{ - tSirRetStatus status = eSIR_FAILURE; - tANI_U8 index; - tLimRmcGroupContext *entry, *prev, **head; - - index = __rmcGroupHashFunction(transmitter); - - head = &pMac->rmcContext.rmcGroupRxHashTable[index]; - entry = *head; - prev = NULL; - - while (entry) - { - if (vos_mem_compare(transmitter, entry->transmitter, - sizeof(v_MACADDR_t))) - { - if (*head == entry) - { - *head = entry->next; - } - else - { - prev->next = entry->next; - } - - PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Delete: entry %p " - " transmitter " MAC_ADDRESS_STR), entry - MAC_ADDR_ARRAY(transmitter));) - - /* free the group entry */ - vos_mem_free(entry); - - status = eSIR_SUCCESS; - break; - } - - prev = entry; - entry = entry->next; - } - - return status; -} - -/** - * __rmcGroupDeleteAllEntries() - * - *FUNCTION: - * This function is called to delete all RMC group entries - * for either transmitter or leader, depending on the parameter. - * - *LOGIC: - * - *ASSUMPTIONS: - * Should be called with lkRmcLock held. - * - *NOTE: - * - * @param pMac - * role - transmitter or leader - * @return - */ -static void -__rmcGroupDeleteAllEntries(tpAniSirGlobal pMac) -{ - tLimRmcGroupContext *entry, **head; - int index; - - PELOG1(limLog(pMac, LOG1, FL("RMC: Hash_Delete_All"),);) - - for (index = 0; index < RMC_MCAST_GROUPS_HASH_SIZE; index++) - { - head = &pMac->rmcContext.rmcGroupRxHashTable[index]; - - entry = *head; - - while (entry) - { - *head = entry->next; - /* free the group entry */ - vos_mem_free(entry); - entry = *head; - } - } -} - -/* End RMC utility routines */ - -/** - * \brief Send WDA_RMC_LEADER_REQ to HAL, in order - * to request for a Multicast Leader selection. - * - * \sa __limPostMsgLeaderReq - * - * \param pMac The global tpAniSirGlobal object - * - * \param cmd SUGGEST leader or BECOME leader - * - * \param mcastGroup Multicast Group address - * - * \param mcastTransmitter Multicast Transmitter address - - * \return none - * - */ -static void -__limPostMsgLeaderReq ( tpAniSirGlobal pMac, - tANI_U8 cmd, - tSirMacAddr mcastTransmitter) -{ - tSirMsgQ msg; - tSirRmcLeaderReq *pLeaderReq; - - pLeaderReq = vos_mem_malloc(sizeof(*pLeaderReq)); - if (NULL == pLeaderReq) - { - limLog(pMac, LOGE, FL("AllocateMemory() failed")); - return; - } - - pLeaderReq->cmd = cmd; - - vos_mem_copy(pLeaderReq->mcastTransmitter, mcastTransmitter, - sizeof(tSirMacAddr)); - - /* Initialize black list */ - vos_mem_zero(pLeaderReq->blacklist, sizeof(pLeaderReq->blacklist)); - - /* - * If there are a list of STA receivers that we do not want to be - * considered for Leader, send it here. - */ - if (eRMC_SUGGEST_LEADER_CMD == cmd) - { - /* TODO - Set the black list. */ - } - - msg.type = WDA_RMC_LEADER_REQ; - msg.bodyptr = pLeaderReq; - msg.bodyval = 0; - - MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); - if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) - { - vos_mem_free(pLeaderReq); - limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed")); - } - - return; -} - -/** - * \brief Send WDA_RMC_UPDATE_IND to HAL, in order - * to request for a Multicast Leader selection. - * - * \sa __limPostMsgUpdateInd - * - * \param pMac The global tpAniSirGlobal object - * - * \param indication Accepted or Cancelled - * - * \param role Leader or Transmitter - * - * \param mcastGroup Multicast Group address - * - * \param mcastTransmitter Multicast Transmitter address - * - * \param mcastLeader Multicast Leader address - * - * \return none - * - */ -static void -__limPostMsgUpdateInd ( tpAniSirGlobal pMac, - tANI_U8 indication, - tANI_U8 role, - tSirMacAddr mcastTransmitter, - tSirMacAddr mcastLeader) -{ - tSirMsgQ msg; - tSirRmcUpdateInd *pUpdateInd; - - pUpdateInd = vos_mem_malloc(sizeof(*pUpdateInd)); - if ( NULL == pUpdateInd ) - { - limLog(pMac, LOGE, FL("AllocateMemory() failed")); - return; - } - - vos_mem_zero(pUpdateInd, sizeof(*pUpdateInd)); - - pUpdateInd->indication = indication; - pUpdateInd->role = role; - - vos_mem_copy(pUpdateInd->mcastTransmitter, - mcastTransmitter, sizeof(tSirMacAddr)); - - vos_mem_copy(pUpdateInd->mcastLeader, - mcastLeader, sizeof(tSirMacAddr)); - - msg.type = WDA_RMC_UPDATE_IND; - msg.bodyptr = pUpdateInd; - msg.bodyval = 0; - - MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); - if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) - { - vos_mem_free(pUpdateInd); - limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed")); - } - - return; -} - -static char * -__limLeaderMessageToString(eRmcMessageType msgType) -{ - switch (msgType) - { - default: - return "Invalid"; - case eLIM_RMC_ENABLE_REQ: - return "RMC_ENABLE_REQ"; - case eLIM_RMC_DISABLE_REQ: - return "RMC_DISABLE_REQ"; - case eLIM_RMC_LEADER_SELECT_RESP: - return "RMC_LEADER_SELECT_RESP"; - case eLIM_RMC_LEADER_PICK_NEW: - return "RMC_LEADER_PICK_NEW"; - case eLIM_RMC_OTA_LEADER_INFORM_ACK: - return "RMC_OTA_LEADER_INFORM_ACK"; - case eLIM_RMC_OTA_LEADER_INFORM_SELECTED: - return "RMC_OTA_LEADER_INFORM_SELECTED"; - case eLIM_RMC_BECOME_LEADER_RESP: - return "RMC_BECOME_LEADER_RESP"; - case eLIM_RMC_OTA_LEADER_INFORM_CANCELLED: - return "RMC_OTA_LEADER_INFORM_CANCELLED"; - } -} - -static char * -__limLeaderStateToString(eRmcLeaderState state) -{ - switch (state) - { - default: - return "Invalid"; - case eRMC_IS_NOT_A_LEADER: - return "Device Not a Leader"; - case eRMC_LEADER_PENDING: - return "Pending firmware resp"; - case eRMC_IS_A_LEADER: - return "Device is Leader"; - } -} - -static char * -__limMcastTxStateToString(eRmcMcastTxState state) -{ - switch (state) - { - default: - return "Invalid"; - case eRMC_LEADER_NOT_SELECTED: - return "Not Selected"; - case eRMC_LEADER_ENABLE_REQUESTED: - return "Enable Requested"; - case eRMC_LEADER_OTA_REQUEST_SENT: - return "OTA Request Sent"; - case eRMC_LEADER_ACTIVE: - return "Active"; - } -} - -/** - * __rmcLeaderSelectTimerHandler() - * - *FUNCTION: - * This function is called upon timer expiry. - * - *LOGIC: This function handles unacked LEADER_INFORM messages. - * If a leader fails to respond, it tries the next one in - * the list. If all potential leaders are exhausted, the - * multicast group is removed. - * - *ASSUMPTIONS: - * NA - * - *NOTE: - * Only one entry is processed for every invocation if this routine. - * This allows us to use a single timer and makes sure we do not - * timeout a request too early. - * - * @param param - Message corresponding to the timer that expired - * - * @return None - */ - -void -__rmcLeaderSelectTimerHandler(void *pMacGlobal, tANI_U32 param) -{ - tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; - tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 }; - tSirRetStatus status; - tSirRMCInfo RMC; - tpPESession psessionEntry; - tANI_U32 cfgValue; - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:__rmcLeaderSelectTimerHandler:No active IBSS"));) - return; - } - - if (wlan_cfgGetInt(pMac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, - &cfgValue) != eSIR_SUCCESS) - { - /** - * Could not get Action Period Frequency value - * from CFG. Log error. - */ - limLog(pMac, LOGE, FL("could not retrieve ActionPeriodFrequency")); - } - - cfgValue = SYS_MS_TO_TICKS(cfgValue); - - if (pMac->rmcContext.rmcTimerValInTicks != cfgValue) - { - limLog(pMac, LOG1, FL("RMC LeaderSelect timer value changed")); - if (tx_timer_change(&pMac->rmcContext.gRmcLeaderSelectTimer, - cfgValue, 0) != TX_SUCCESS) - { - limLog(pMac, LOGE, - FL("Unable to change LeaderSelect Timer val")); - } - pMac->rmcContext.rmcTimerValInTicks = cfgValue; - } - - /* - * If we are in the scanning state then we need to return - * from this function without any further processing - */ - if (eLIM_HAL_SCANNING_STATE == pMac->lim.gLimHalScanState) - { - limLog(pMac, LOG1, FL("In scanning state, can't send action frm")); - if (tx_timer_activate(&pMac->rmcContext.gRmcLeaderSelectTimer) != - TX_SUCCESS) - { - limLog(pMac, LOGE, FL("In scanning state, " - "couldn't activate RMC LeaderSelect timer")); - } - return; - } - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("__rmcLeaderSelectTimerHandler lock acquire failed")); - if (tx_timer_activate(&pMac->rmcContext.gRmcLeaderSelectTimer)!= TX_SUCCESS) - { - limLog(pMac, LOGE, FL("could not activate RMC LeaderSelect timer")); - } - return; - } - - vos_mem_copy(&RMC.mcastLeader, &pMac->rmcContext.leader, - sizeof(tSirMacAddr)); - - if (VOS_FALSE == vos_mem_compare(&zeroMacAddr, - &pMac->rmcContext.leader, sizeof(tSirMacAddr))) - { - limLog(pMac, LOG1, - FL("RMC Periodic Leader_Select Leader " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pMac->rmcContext.leader)); - /* - * Re-arm timer - */ - if (tx_timer_activate(&pMac->rmcContext.gRmcLeaderSelectTimer)!= - TX_SUCCESS) - { - limLog(pMac, LOGE, FL("could not activate RMC Response timer")); - } - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS - (vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: __rmcLeaderSelectTimerHandler lock release failed")); - } - } - else - { - limLog(pMac, LOGE, - FL("RMC Deactivating timer because no leader was selected")); - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS - (vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: __rmcLeaderSelectTimerHandler lock release failed")); - } - - return; - } - - /* - * Handle periodic transmission of Leader_Select Action frame. - */ - - RMC.dialogToken = 0; - RMC.action = SIR_MAC_RMC_LEADER_INFORM_SELECTED; - - status = limSendRMCActionFrame(pMac, - SIR_MAC_RMC_MCAST_ADDRESS, - &RMC, - psessionEntry); - - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:__rmcLeaderSelectTimerHandler Action frame send failed"));) - } - - return; -} - -/** - * __limProcessRMCEnableRequest() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_ENABLE_REQ - * message from SME. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCEnableRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tSirSetRMCReq *setRmcReq = (tSirSetRMCReq *)pMsgBuf; - tpPESession psessionEntry; - - if (!setRmcReq) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Enable:NULL message") );) - return; - } - - /*Enable RMC*/ - pMac->rmcContext.rmcEnabled = TRUE; - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Enable RMC request no active IBSS"));) - pMac->rmcContext.state = eRMC_LEADER_NOT_SELECTED; - return; - } - - /* Send LBP_LEADER_REQ to f/w */ - __limPostMsgLeaderReq(pMac, eRMC_SUGGEST_LEADER_CMD, - setRmcReq->mcastTransmitter); - - pMac->rmcContext.state = eRMC_LEADER_ENABLE_REQUESTED; -} - -/** - * __limProcessRMCDisableRequest() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_DISABLE_REQ - * message from SME. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCDisableRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tpPESession psessionEntry; - tSirRMCInfo RMC; - tSirSetRMCReq *setRmcReq = (tSirSetRMCReq *)pMsgBuf; - tSirRetStatus status; - v_PVOID_t pvosGCtx; - VOS_STATUS vos_status; - v_MACADDR_t vosMcastTransmitter; - - /*Disable RMC*/ - pMac->rmcContext.rmcEnabled = FALSE; - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Disable:No active IBSS"));) - return; - } - - if (!setRmcReq) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Disable:NULL message") );) - return; - } - - /* Cancel pending timer */ - tx_timer_deactivate(&pMac->rmcContext.gRmcLeaderSelectTimer); - - vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; - vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; - vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; - vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; - vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; - vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; - - /* Disable RMC in TL */ - pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); - vos_status = WLANTL_DisableReliableMcast(pvosGCtx, &vosMcastTransmitter); - - if (VOS_STATUS_SUCCESS != vos_status) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Disable: TL disable failed"));) - } - - if (pMac->rmcContext.state == eRMC_LEADER_ACTIVE) - { - /* - * Send Leader_Inform_Cancelled Action frame to the Leader. - */ - RMC.dialogToken = 0; - RMC.action = SIR_MAC_RMC_LEADER_INFORM_CANCELLED; - vos_mem_copy(&RMC.mcastLeader, &pMac->rmcContext.leader, sizeof(tSirMacAddr)); - - status = limSendRMCActionFrame(pMac, pMac->rmcContext.leader, - &RMC, psessionEntry); - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Disable: Action frame send failed"));) - } - - pMac->rmcContext.state = eRMC_LEADER_NOT_SELECTED; - } - - /* send LBP_UPDATE_IND */ - __limPostMsgUpdateInd(pMac, eRMC_LEADER_CANCELLED, eRMC_TRANSMITTER_ROLE, - setRmcReq->mcastTransmitter, pMac->rmcContext.leader); - - vos_mem_zero(pMac->rmcContext.leader, sizeof(tSirMacAddr)); - -} - -/** - * __limProcessRMCLeaderSelectResponse() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_LEADER_SELECT_RESP - * message from the firmware. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCLeaderSelectResponse(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tSirRmcLeaderSelectInd *pRmcLeaderSelectInd; - tpPESession psessionEntry; - tSirRetStatus status; - v_PVOID_t pvosGCtx; - VOS_STATUS vos_status; - v_MACADDR_t vosMcastTransmitter; - tSirRMCInfo RMC; - - if (NULL == pMsgBuf) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Select_Resp:NULL message"));) - return; - } - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Leader_Select_Resp:No active IBSS"));) - pMac->rmcContext.state = eRMC_LEADER_NOT_SELECTED; - return; - } - - pRmcLeaderSelectInd = (tSirRmcLeaderSelectInd *)pMsgBuf; - - if (pMac->rmcContext.state != eRMC_LEADER_ENABLE_REQUESTED) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Select_Resp:Bad state %s"), - __limMcastTxStateToString(pMac->rmcContext.state) );) - return; - } - - if (pRmcLeaderSelectInd->status) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Leader_Select_Resp:FW Status %d"), - pRmcLeaderSelectInd->status);) - pMac->rmcContext.state = eRMC_LEADER_NOT_SELECTED; - return; - } - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, FL("RMC:Leader_Select_Resp:lock acquire failed")); - pMac->rmcContext.state = eRMC_LEADER_NOT_SELECTED; - return; - } - - /* Cache the current leader */ - vos_mem_copy(&pMac->rmcContext.leader, &pRmcLeaderSelectInd->leader[0], - sizeof(tSirMacAddr)); - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS - (vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, FL("RMC: Leader_Select_Resp: lock release failed")); - } - - RMC.dialogToken = 0; - RMC.action = SIR_MAC_RMC_LEADER_INFORM_SELECTED; - vos_mem_copy(&RMC.mcastLeader, &pRmcLeaderSelectInd->leader[0], - sizeof(tSirMacAddr)); - - PELOG1(limLog(pMac, LOG1, FL("RMC: Leader_Select :leader " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pRmcLeaderSelectInd->leader[0]));) - - /* - * Send Leader_Inform Action frame to the candidate leader. - * Candidate leader is at leader_index. - */ - status = limSendRMCActionFrame(pMac, - SIR_MAC_RMC_MCAST_ADDRESS, - &RMC, - psessionEntry); - - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Leader_Select_Resp: Action send failed"));) - } - - /* send LBP_UPDATE_IND */ - __limPostMsgUpdateInd(pMac, eRMC_LEADER_ACCEPTED, eRMC_TRANSMITTER_ROLE, - psessionEntry->selfMacAddr, pMac->rmcContext.leader); - - vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; - vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; - vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; - vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; - vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; - vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; - - /* Enable TL */ - pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); - vos_status = WLANTL_EnableReliableMcast(pvosGCtx, &vosMcastTransmitter); - - /* Set leader state to Active. */ - pMac->rmcContext.state = eRMC_LEADER_ACTIVE; - - /* Start timer to send periodic Leader_Select */ - if (tx_timer_activate(&pMac->rmcContext.gRmcLeaderSelectTimer)!= TX_SUCCESS) - { - limLog(pMac, LOGE, - FL("Leader_Select_Resp:Activate RMC Response timer failed")); - } -} - -/** - * __limProcessRMCLeaderPickNew() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_LEADER_PICK_NEW - * message from the firmware. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCLeaderPickNew(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tSirRmcUpdateInd *pRmcUpdateInd; - tpPESession psessionEntry; - tSirRetStatus status; - tSirRMCInfo RMC; - v_PVOID_t pvosGCtx; - VOS_STATUS vos_status; - v_MACADDR_t vosMcastTransmitter; - tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 }; - - if (NULL == pMsgBuf) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Pick_New:NULL message"));) - return; - } - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Pick_New:No active IBSS"));) - return; - } - - pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); - - pRmcUpdateInd = (tSirRmcUpdateInd *)pMsgBuf; - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, FL("RMC:Leader_Pick_New:lock acquire failed")); - return; - } - - - /* Fill out Action frame parameters */ - RMC.dialogToken = 0; - - /* - * Check the multicast Leader address sent by firmware. - * Prepare to send Leader_Inform_Cancel only if this address - * is valid. - */ - if (VOS_FALSE == vos_mem_compare(&zeroMacAddr, - &pRmcUpdateInd->mcastLeader, - sizeof(tSirMacAddr))) - { - - vos_mem_copy(&RMC.mcastLeader, &pRmcUpdateInd->mcastLeader, - sizeof(tSirMacAddr)); - - /* - * Send Leader_Inform_Cancelled Action frame to the current leader. - */ - RMC.action = SIR_MAC_RMC_LEADER_INFORM_CANCELLED; - status = limSendRMCActionFrame(pMac, - pRmcUpdateInd->mcastLeader, - &RMC, psessionEntry); - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:Leader_Pick_New: Inform_Cancel Action send failed"));) - goto done; - } - - vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; - vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; - vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; - vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; - vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; - vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; - - /* Disable RMC in TL */ - vos_status = WLANTL_DisableReliableMcast(pvosGCtx, &vosMcastTransmitter); - - if (VOS_STATUS_SUCCESS != vos_status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:Leader_Pick_New: TL disable failed"));) - } - } - - /* - * Cache the leader list for this multicast group - * If no leader list was given, this will essentially zero out - * the list. - */ - vos_mem_copy(pMac->rmcContext.leader, pRmcUpdateInd->leader[0], - sizeof(tSirMacAddr)); - - pMac->rmcContext.state = eRMC_LEADER_NOT_SELECTED; - - /* - * Verify that the Pick_New indication has any candidate leaders. - */ - if (VOS_TRUE == vos_mem_compare(&zeroMacAddr, - pMac->rmcContext.leader, - sizeof(tSirMacAddr))) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:Leader_Pick_New: No candidate leaders available"));) - goto done; - } - - /* - * Send Leader_Inform Action frame to the new candidate leader. - */ - - RMC.action = SIR_MAC_RMC_LEADER_INFORM_SELECTED; - vos_mem_copy(&RMC.mcastLeader, &pMac->rmcContext.leader, - sizeof(tSirMacAddr)); - status = limSendRMCActionFrame(pMac, SIR_MAC_RMC_MCAST_ADDRESS, - &RMC, psessionEntry); - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:Leader_Pick_New: Inform_Selected Action send failed"));) - goto done; - } - - /* send LBP_UPDATE_IND */ - __limPostMsgUpdateInd(pMac, eRMC_LEADER_ACCEPTED, eRMC_TRANSMITTER_ROLE, - psessionEntry->selfMacAddr, pMac->rmcContext.leader); - - vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; - vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; - vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; - vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; - vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; - vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; - - /* Enable TL */ - vos_status = WLANTL_EnableReliableMcast(pvosGCtx, &vosMcastTransmitter); - - if (VOS_STATUS_SUCCESS != vos_status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:Leader_Pick_New: TL enable failed"));) - goto done; - } - - /* Set leader state to Active. */ - pMac->rmcContext.state = eRMC_LEADER_ACTIVE; - - /* Start timer to send periodic Leader_Select */ - if (tx_timer_activate(&pMac->rmcContext.gRmcLeaderSelectTimer)!= TX_SUCCESS) - { - limLog(pMac, LOGE, - FL("Leader_Pick_New:Activate RMC Response timer failed")); - } - -done: - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: Leader_Pick_New: lock release failed")); - } -} - -/** - * __limProcessRMCLeaderInformSelected() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_OTA_LEADER_INFORM_SELECTED - * message from the "Leader Inform" Action frame from the - * multicast transmitter. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCLeaderInformSelected(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tpSirMacMgmtHdr pHdr; - tANI_U8 *pFrameData; - tANI_U32 frameLen; - tLimRmcGroupContext *entry; - tpPESession psessionEntry; - tSirRetStatus status; - - if (!pMsgBuf) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Inform:NULL msg"));) - return; - } - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Become_Leader_Resp:No active IBSS"));) - return; - } - - /* - * Get the frame header - */ - pHdr = WDA_GET_RX_MAC_HEADER((tANI_U8 *)pMsgBuf); - - frameLen = WDA_GET_RX_PAYLOAD_LEN((tANI_U8 *)pMsgBuf); - if (frameLen < sizeof(tSirMacOxygenNetworkFrameHdr)) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Leader_Inform:Bad length %d "), frameLen);) - return; - } - - pFrameData = WDA_GET_RX_MPDU_DATA((tANI_U8 *)pMsgBuf) + - sizeof(tSirMacOxygenNetworkFrameHdr); - - if (!pFrameData) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Inform:NULL data"));) - return; - } - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, FL("RMC:Become_Leader_Resp:lock acquire failed")); - return; - } - - /* - * Check if this transmitter exists in our database. - */ - entry = __rmcGroupLookupHashEntry(pMac, pHdr->sa); - - /* - * Check if we are being advertised as the leader. - * The leader address is from the Action frame payload. - */ - if (VOS_FALSE == vos_mem_compare(pFrameData, psessionEntry->selfMacAddr, - sizeof(tSirMacAddr))) - { - /* - * If we were the leader for this transmitter, tell the firmware - * that we are not any more. This is a implicit Leader_Cancel. - */ - if (entry) - { - PELOG1(limLog(pMac, LOG1, - FL("RMC: Leader_Inform: Leader Cancelled"));) - /* send LBP_UPDATE_IND */ - __limPostMsgUpdateInd(pMac, eRMC_LEADER_CANCELLED, - eRMC_LEADER_ROLE, pHdr->sa, psessionEntry->selfMacAddr); - - /* - * Delete hash entry for this Group address. - */ - status = __rmcGroupDeleteHashEntry(pMac, pHdr->sa); - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Leader_Inform:hash delete failed"));) - } - } - } - else - { - /* - * If we have been selected as the new leader for this transmitter, - * add it to your database. If we are already in the database, there - * is nothing to do. - */ - if (NULL == entry) - { - /* Add the transmitter address to the hash */ - entry = __rmcGroupInsertHashEntry(pMac, pHdr->sa); - if (entry) - { - if (entry->isLeader != eRMC_LEADER_PENDING) - { - /* Send LBP_LEADER_REQ to f/w */ - __limPostMsgLeaderReq(pMac, eRMC_BECOME_LEADER_CMD, - pHdr->sa); - entry->isLeader = eRMC_LEADER_PENDING; - } - } - else - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Leader_Inform:Hash insert failed"));) - } - - } - } - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: Leader_Inform: lock release failed")); - } - -} - -/** - * __limProcessRMCBecomeLeaderResp() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_BECOME_LEADER_RESP - * message from the firmware. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCBecomeLeaderResp(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tSirRmcBecomeLeaderInd *pRmcBecomeLeaderInd; - tLimRmcGroupContext *entry; - tSirRetStatus status = eSIR_SUCCESS; - - if (NULL == pMsgBuf) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Leader_Resp:NULL message"));) - return; - } - - pRmcBecomeLeaderInd = (tSirRmcBecomeLeaderInd *)pMsgBuf; - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, FL("RMC:Become_Leader_Resp:lock acquire failed")); - return; - } - - /* - * Find the entry for this Group Address. - */ - entry = __rmcGroupLookupHashEntry(pMac, - pRmcBecomeLeaderInd->mcastTransmitter); - if (NULL == entry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Leader_Resp: No entry"));) - goto done; - } - - if (pRmcBecomeLeaderInd->status) - { - PELOGE(limLog(pMac, LOGE, FL("RMC:Become_Leader_Resp:FW Status %d"), - pRmcBecomeLeaderInd->status);) - status = eSIR_FAILURE; - goto done; - } - - if (entry->isLeader != eRMC_LEADER_PENDING) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Leader_Resp:Bad state: %s"), - __limLeaderStateToString(entry->isLeader) );) - status = eSIR_FAILURE; - goto done; - } - - entry->isLeader = eRMC_IS_A_LEADER; - -done: - if (eSIR_FAILURE == status) - { - status = __rmcGroupDeleteHashEntry(pMac, - pRmcBecomeLeaderInd->mcastTransmitter); - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Become_Leader_Resp:hash delete failed"));) - } - } - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: Become_Leader_Resp: lock release failed")); - } - - return; -} - -/** - * __limProcessRMCLeaderInformCancelled() - * - *FUNCTION: - * This function is called to processes eLIM_RMC_OTA_LEADER_INFORM_CANCELLED - * message from the "Leader Inform Cancelled" Action frame from the - * multicast transmitter. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -static void -__limProcessRMCLeaderInformCancelled(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) -{ - tpSirMacMgmtHdr pHdr; - tANI_U8 *pFrameData; - tANI_U32 frameLen; - tSirRetStatus status; - tLimRmcGroupContext *entry; - tpPESession psessionEntry; - - if (!pMsgBuf) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Inform_Cancel:NULL msg"));) - return; - } - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC:Leader_Inform_Cancel:No active IBSS"));) - return; - } - - pHdr = WDA_GET_RX_MAC_HEADER((tANI_U8 *)pMsgBuf); - - frameLen = WDA_GET_RX_PAYLOAD_LEN((tANI_U8 *)pMsgBuf); - if (frameLen < sizeof(tSirMacOxygenNetworkFrameHdr)) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Leader_Inform:Bad length %d "), frameLen);) - return; - } - - pFrameData = WDA_GET_RX_MPDU_DATA((tANI_U8 *)pMsgBuf) + - sizeof(tSirMacOxygenNetworkFrameHdr); - - if (!pFrameData) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Inform_Cancel:NULL data"));) - return; - } - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, FL("RMC:Leader_Inform_Cancel lock acquire failed")); - return; - } - - /* - * Find the entry for this Group Address. - */ - entry = __rmcGroupLookupHashEntry(pMac, pHdr->sa); - if (NULL == entry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Leader_Inform_Cancel: No entry"));) - goto done; - } - - /* send LBP_UPDATE_END */ - __limPostMsgUpdateInd(pMac, eRMC_LEADER_CANCELLED, - eRMC_LEADER_ROLE, pHdr->sa, psessionEntry->selfMacAddr); - - /* - * Delete hash entry for this Group address. - */ - status = __rmcGroupDeleteHashEntry(pMac, pHdr->sa); - if (eSIR_FAILURE == status) - { - PELOGE(limLog(pMac, LOGE, - FL("RMC: Leader_Inform_Cancel:hash delete failed"));) - } - -done: - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: Leader_Inform_Cancel: lock release failed")); - } - return; -} - -/** - * limProcessRMCMessages() - * - *FUNCTION: - * This function is called to processes various RMC messages. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param msgType Indicates the RMC message type - * @param *pMsgBuf A pointer to the RMC message buffer - * - * @return None - */ -void -limProcessRMCMessages(tpAniSirGlobal pMac, eRmcMessageType msgType, - tANI_U32 *pMsgBuf) -{ - - if (pMsgBuf == NULL) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: Buffer is Pointing to NULL"));) - return; - } - - limLog(pMac, LOG1, FL("RMC: limProcessRMCMessages: %s"), - __limLeaderMessageToString(msgType)); - - switch (msgType) - { - /* - * Begin - messages processed by RMC multicast transmitter. - */ - case eLIM_RMC_ENABLE_REQ: - __limProcessRMCEnableRequest(pMac, pMsgBuf); - break; - - case eLIM_RMC_DISABLE_REQ: - __limProcessRMCDisableRequest(pMac, pMsgBuf); - break; - - case eLIM_RMC_LEADER_SELECT_RESP: - __limProcessRMCLeaderSelectResponse(pMac, pMsgBuf); - break; - - case eLIM_RMC_LEADER_PICK_NEW: - __limProcessRMCLeaderPickNew(pMac, pMsgBuf); - break; - - /* - * End - messages processed by RMC multicast transmitter. - */ - - /* - * Begin - messages processed by RMC Leader (receiver). - */ - case eLIM_RMC_OTA_LEADER_INFORM_SELECTED: - __limProcessRMCLeaderInformSelected(pMac, pMsgBuf); - break; - - case eLIM_RMC_BECOME_LEADER_RESP: - __limProcessRMCBecomeLeaderResp(pMac, pMsgBuf); - break; - - case eLIM_RMC_OTA_LEADER_INFORM_CANCELLED: - __limProcessRMCLeaderInformCancelled(pMac, pMsgBuf); - break; - - /* - * End - messages processed by RMC Leader (receiver). - */ - - default: - break; - } // switch (msgType) - return; -} /*** end limProcessRMCMessages() ***/ - -/** - * limRmcInit() - * - *FUNCTION: - * This function is called to initialize RMC module. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * - * @return None - */ -void -limRmcInit(tpAniSirGlobal pMac) -{ - tANI_U32 cfgValue; - - if (wlan_cfgGetInt(pMac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, - &cfgValue) != eSIR_SUCCESS) - { - /** - * Could not get Action Period Frequency value - * from CFG. Log error. - */ - limLog(pMac, LOGP, FL("could not retrieve ActionPeriodFrequency")); - } - - cfgValue = SYS_MS_TO_TICKS(cfgValue); - - vos_mem_zero(&pMac->rmcContext, sizeof(pMac->rmcContext)); - - if (!VOS_IS_STATUS_SUCCESS(vos_lock_init(&pMac->rmcContext.lkRmcLock))) - { - PELOGE(limLog(pMac, LOGE, FL("RMC lock init failed!"));) - } - - if (tx_timer_create(&pMac->rmcContext.gRmcLeaderSelectTimer, - "RMC RSP TIMEOUT", - __rmcLeaderSelectTimerHandler, - 0 /* param */, - cfgValue, 0, - TX_NO_ACTIVATE) != TX_SUCCESS) - { - /* Could not create RMC response timer. */ - limLog(pMac, LOGE, FL("could not create RMC response timer")); - } - - pMac->rmcContext.rmcTimerValInTicks = cfgValue; -} - -/** - * limRmcCleanup() - * - *FUNCTION: - * This function is called to clean up RMC module. - * - *LOGIC: - * - *ASSUMPTIONS: limRmcIbssDelete should have been called before this. - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * - * @return None - */ -void -limRmcCleanup(tpAniSirGlobal pMac) -{ - /* Delete all entries from Leader database. */ - limRmcIbssDelete(pMac); - - if (!VOS_IS_STATUS_SUCCESS(vos_lock_destroy(&pMac->rmcContext.lkRmcLock))) - { - PELOGE(limLog(pMac, LOGE, FL("RMC lock destroy failed!"));) - } - - tx_timer_delete(&pMac->rmcContext.gRmcLeaderSelectTimer); -} - -/** - * limRmcTransmitterDelete() - * - *FUNCTION: - * This function is called on a Leader to handle deletion of the transmitter. - * It is called when the IBSS module wants to delete a peer. If the peer - * exists in our database, we delete the entries associated with this peer. - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * transmitter Address of the transmitter - * @return None - */ -void -limRmcTransmitterDelete(tpAniSirGlobal pMac, tSirMacAddr transmitter) -{ - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: limRMCTransmitterDelete lock acquire failed")); - return; - } - - /* Delete this transmitter from Leader database. */ - __rmcGroupDeleteHashEntry(pMac, transmitter); - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: limRMCTransmitterDelete lock release failed")); - } - - limLog(pMac, LOG1, FL("RMC: limRmcTransmitterDelete complete")); -} - -/** - * limRmcIbssDelete() - * - *FUNCTION: - * This function is called when the IBSS is being deleted for either - * transmitter or leader STA. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * - * @return None - */ -void -limRmcIbssDelete(tpAniSirGlobal pMac) -{ - tpPESession psessionEntry; - tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 }; - - /* - * This API relies on a single active IBSS session. - */ - psessionEntry = limIsIBSSSessionActive(pMac); - if (NULL == psessionEntry) - { - PELOGE(limLog(pMac, LOGE, FL("RMC: limRmcIbssDelete:No active IBSS"));) - return; - } - - if (VOS_FALSE == vos_mem_compare(&zeroMacAddr, - &pMac->rmcContext.leader, sizeof(tSirMacAddr))) - { - /* send LBP_UPDATE_IND */ - __limPostMsgUpdateInd(pMac, eRMC_LEADER_CANCELLED, - eRMC_TRANSMITTER_ROLE, psessionEntry->selfMacAddr, - pMac->rmcContext.leader); - } - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: limRmcIbssDelete lock acquire failed")); - return; - } - - /* Cancel pending timer */ - tx_timer_deactivate(&pMac->rmcContext.gRmcLeaderSelectTimer); - - /* Delete all entries from Leader database. */ - __rmcGroupDeleteAllEntries(pMac); - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: limRmcIbssDelete lock release failed")); - } - - limLog(pMac, LOG1, FL("RMC: limRmcIbssDelete complete")); -} - -/** - * limRmcDumpStatus() - * - *FUNCTION: - * This function is called to display RMC status for transmitter and leader. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * - * @return char * Pointer to buffer with RMC information. - */ -void -limRmcDumpStatus(tpAniSirGlobal pMac) -{ - tLimRmcGroupContext *entry; - int index, count; - - /* Acquire RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: limRmcDumpStatus lock acquire failed")); - return; - } - - - limLog(pMac, LOGE, FL(" ----- RMC Transmitter Information ----- \n")); - limLog(pMac, LOGE, - FL(" Leader Address | RMC State \n")); - - if (pMac->rmcContext.state != eRMC_LEADER_NOT_SELECTED) - { - limLog(pMac,LOGE, FL( MAC_ADDRESS_STR " | %s\n"), - MAC_ADDR_ARRAY(pMac->rmcContext.leader), - __limMcastTxStateToString(pMac->rmcContext.state)); - } - - limLog( pMac,LOGE, FL(" ----- RMC Leader Information ----- \n")); - limLog( pMac,LOGE, FL(" Transmitter Address\n")); - - count = 0; - for (index = 0; index < RMC_MCAST_GROUPS_HASH_SIZE; index++) - { - entry = pMac->rmcContext.rmcGroupRxHashTable[index]; - - while (entry) - { - count++; - limLog( pMac,LOGE, FL("%d. " MAC_ADDRESS_STR " \n"), - count, MAC_ADDR_ARRAY(entry->transmitter)); - entry = entry->next; - } - } - - /* Release RMC lock */ - if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) - { - limLog(pMac, LOGE, - FL("RMC: limRmcDumpStatus lock release failed")); - } - - return; - -} - -/** - * limRmcTriggerLeaderSelection() - * - *FUNCTION: - * This function is called to RMC leader selection in FW - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * - * @param macAddr Input mac address - * - * @return : VOS_STATUS_SUCCESS if RMC state machine allows leader selection and - leader selection is triggered in FW - VOS_STATUS_E_FAILURE if RMC state machine does not allow leader - selection in its current state - */ -VOS_STATUS -limRmcTriggerLeaderSelection(tpAniSirGlobal pMac, tSirMacAddr macAddr) -{ - /*Trigger LBP leader selection in FW*/ - if ((TRUE == pMac->rmcContext.rmcEnabled) && - (eRMC_LEADER_NOT_SELECTED == pMac->rmcContext.state)) - { - limLog(pMac, LOG1, - FL("Leader selection trigerred in FW")); - - __limPostMsgLeaderReq(pMac, eRMC_SUGGEST_LEADER_CMD, macAddr); - - pMac->rmcContext.state = eRMC_LEADER_ENABLE_REQUESTED; - - return VOS_STATUS_SUCCESS; - } - else - { - limLog(pMac, LOG1, - FL("Could not trigger leader selection: RMC state %d rmcEnabled %d"), - pMac->rmcContext.state, pMac->rmcContext.rmcEnabled); - - return VOS_STATUS_E_FAILURE; - } -} - -#endif /* WLAN_FEATURE_RELIABLE_MCAST */ diff --git a/CORE/MAC/src/pe/lim/limRMC.h b/CORE/MAC/src/pe/lim/limRMC.h deleted file mode 100644 index ce156cef0916..000000000000 --- a/CORE/MAC/src/pe/lim/limRMC.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * All Rights Reserved. - * Qualcomm Atheros Confidential and Proprietary. - * - * Date: 08/15/13 - * History:- - * Date Modified by Modification Information - * -------------------------------------------------------------------- - */ -#ifndef __LIM_RMC_H -#define __LIM_RMC_H - -#if defined WLAN_FEATURE_RELIABLE_MCAST - -typedef enum { - eLIM_RMC_ENABLE_REQ = 0, - eLIM_RMC_DISABLE_REQ = 1, - eLIM_RMC_BECOME_LEADER_RESP = 2, - eLIM_RMC_LEADER_SELECT_RESP = 3, - eLIM_RMC_LEADER_PICK_NEW = 4, - eLIM_RMC_OTA_LEADER_INFORM_CANCELLED = 5, - eLIM_RMC_OTA_LEADER_INFORM_ACK = 6, - eLIM_RMC_OTA_LEADER_INFORM_SELECTED = 7, -} eRmcMessageType; - -typedef enum { - eRMC_LEADER_NOT_SELECTED = 0, - eRMC_LEADER_ENABLE_REQUESTED = 1, - eRMC_LEADER_OTA_REQUEST_SENT = 2, - eRMC_LEADER_ACTIVE = 3, -} eRmcMcastTxState; - -typedef enum { - eRMC_IS_NOT_A_LEADER = 0, - eRMC_LEADER_PENDING = 1, - eRMC_IS_A_LEADER = 2, -} eRmcLeaderState; - -enum { - eRMC_SUGGEST_LEADER_CMD = 0, - eRMC_BECOME_LEADER_CMD = 1, -}; - -/* tLbpUpdateIndType */ -enum { - eRMC_LEADER_ACCEPTED = 0, //Host-->FW - eRMC_LEADER_CANCELLED = 1, //Host-->FW - eRMC_LEADER_PICK_NEW = 2, //FW-->Host -}; - -/* tLbpRoleType; */ -typedef enum -{ - eRMC_LEADER_ROLE, - eRMC_TRANSMITTER_ROLE, -} eRmcRole; - -#define RMC_MCAST_GROUPS_HASH_SIZE 32 - -typedef struct sLimRmcGroupContext -{ - tSirMacAddr transmitter; - eRmcLeaderState isLeader; - struct sLimRmcGroupContext *next; -} tLimRmcGroupContext, *tpLimRmcGroupContext; - -typedef struct sLimRmcContext -{ - tANI_BOOLEAN rmcEnabled; - tSirMacAddr leader; - eRmcMcastTxState state; - TX_TIMER gRmcLeaderSelectTimer; - tANI_U32 rmcTimerValInTicks; - vos_lock_t lkRmcLock; - tLimRmcGroupContext *rmcGroupRxHashTable[RMC_MCAST_GROUPS_HASH_SIZE]; -} tLimRmcContext, *tpLimRmcContext; - - -void limRmcInit(tpAniSirGlobal pMac); -void limRmcCleanup(tpAniSirGlobal pMac); -void limRmcTransmitterDelete(tpAniSirGlobal pMac, tSirMacAddr transmitter); -void limRmcIbssDelete(tpAniSirGlobal pMac); -void limRmcDumpStatus(tpAniSirGlobal pMac); - -/** - * limRmcTriggerLeaderSelection() - * - *FUNCTION: - * This function is called to RMC leader selection in FW - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac Pointer to Global MAC structure - * - * @param macAddr Input MAC addres - * - * @return : VOS_STATUS_SUCCESS if RMC state machine allows leader selection and - leader selection is triggered in FW - VOS_STATUS_E_FAILURE if RMC state machine does not allow leader - selection in its current state - */ -VOS_STATUS -limRmcTriggerLeaderSelection(tpAniSirGlobal pMac, tSirMacAddr macAddr); - - -#endif /* WLAN_FEATURE_RELIABLE_MCAST */ - -#endif /* __LIM_RMC_H */ diff --git a/CORE/MAC/src/pe/lim/limSendMessages.c b/CORE/MAC/src/pe/lim/limSendMessages.c index 9b54b09b4e3a..5a946d24fd63 100644 --- a/CORE/MAC/src/pe/lim/limSendMessages.c +++ b/CORE/MAC/src/pe/lim/limSendMessages.c @@ -255,6 +255,12 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, #endif vos_mem_copy( pChnlParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr) ); pChnlParams->peSessionId = peSessionId; + + /*Set DFS flag for DFS channel*/ + if (vos_nv_getChannelEnabledState(chnlNumber) == NV_CHANNEL_DFS) + pChnlParams->isDfsChannel= VOS_TRUE; + else + pChnlParams->isDfsChannel = VOS_FALSE; //we need to defer the message until we get the response back from WDA. SET_LIM_PROCESS_DEFD_MESGS(pMac, false); diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c index d849d8a1ed41..960917d8aec9 100644 --- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c +++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -2916,6 +2916,7 @@ void limSendSmeMaxAssocExceededNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, return; } #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /** ----------------------------------------------------------------- \brief limSendSmeCandidateFoundInd() - sends eWNI_SME_CANDIDATE_FOUND_IND @@ -2957,3 +2958,174 @@ limSendSmeCandidateFoundInd(tpAniSirGlobal pMac, tANI_U8 sessionId) } /*** end limSendSmeCandidateFoundInd() ***/ #endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +/** ----------------------------------------------------------------- + \brief limSendSmeDfsEventNotify() - sends + eWNI_SME_DFS_RADAR_FOUND + After receiving WMI_PHYERR_EVENTID indication frame from FW, this + function sends a eWNI_SME_DFS_RADAR_FOUND to SME to notify + that a RADAR is found on current operating channel and SAP- + has to move to a new channel. + \param pMac - global mac structure + \param msgType - message type received from lower layer + \param event - event data received from lower layer + \return none + \sa +----------------------------------------------------------------- */ +void +limSendSmeDfsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, void *event) +{ + tSirMsgQ mmhMsg; + mmhMsg.type = eWNI_SME_DFS_RADAR_FOUND; + mmhMsg.bodyptr = event; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} + + +/*-------------------------------------------------------------------------- + \brief limSendDfsChanSwIEUpdate() + This timer handler updates the channel switch IE in beacon template + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + \sa + --------------------------------------------------------------------------*/ +static void +limSendDfsChanSwIEUpdate(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + limLog(pMac, LOG1, FL("DFS Channel Switch update timer expired")); + + /* Update the beacon template and send to FW */ + if (schSetFixedBeaconFields(pMac, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to set CSA IE in beacon"));) + return; + } + + /* Send update beacon template message */ + limSendBeaconInd(pMac, psessionEntry); + + return; +} + + +/** ----------------------------------------------------------------- + \brief limSendSmeAPChannelSwitchResp() - sends + eWNI_SME_CHANNEL_CHANGE_RSP + After receiving WDA_SWITCH_CHANNEL_RSP indication this + function sends a eWNI_SME_CHANNEL_CHANGE_RSP to SME to notify + that the Channel change has been done to the specified target + channel in the Channel change request + \param pMac - global mac structure + \param psessionEntry - session info + \param pChnlParams - Channel switch params +--------------------------------------------------------------------*/ +void +limSendSmeAPChannelSwitchResp(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSwitchChannelParams pChnlParams) +{ + tSirMsgQ mmhMsg; + tpSwitchChannelParams pSmeSwithChnlParams; + + pSmeSwithChnlParams = (tSwitchChannelParams *) + vos_mem_malloc(sizeof(tSwitchChannelParams)); + if (NULL == pSmeSwithChnlParams) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for pSmeSwithChnlParams\n")); + return; + } + + vos_mem_set((v_VOID_t*)pSmeSwithChnlParams, + sizeof(tSwitchChannelParams), 0); + + vos_mem_copy(pSmeSwithChnlParams, pChnlParams, + sizeof(tSwitchChannelParams)); + + mmhMsg.type = eWNI_SME_CHANNEL_CHANGE_RSP; + mmhMsg.bodyptr = (void *)pSmeSwithChnlParams; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} + +/** ----------------------------------------------------------------- + \brief limProcessBeaconTxSuccessInd() - This function is used + explicitely to handle successful beacon transmission indication + from the FW. This is a generic event generated by the FW afer the + first beacon is sent out after the beacon template update by the + host + \param pMac - global mac structure + \param psessionEntry - session info + \return none + \sa +----------------------------------------------------------------- */ +void +limProcessBeaconTxSuccessInd(tpAniSirGlobal pMac, tANI_U16 msgType, void *event) +{ + /* Currently, this event is used only for DFS channel switch announcement + * IE update in the template. If required to be used for other IE updates + * add appropriate code by introducing a state variable + */ + tpPESession psessionEntry; + tSirMsgQ mmhMsg; + tSirSmeCSAIeTxCompleteRsp *pChanSwTxResponse; + tANI_U8 length = sizeof(tSirSmeCSAIeTxCompleteRsp); + tpSirFirstBeaconTxCompleteInd pBcnTxInd = + (tSirFirstBeaconTxCompleteInd *)event; + + if((psessionEntry = + peFindSessionByBssIdx(pMac, pBcnTxInd->bssIdx))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if (eLIM_AP_ROLE == psessionEntry->limSystemRole && + VOS_TRUE == psessionEntry->dfsIncludeChanSwIe) + { + /* Start a timer to send next CSA IE update */ + if (--psessionEntry->gLimChannelSwitch.switchCount >= 0) + { + /* Start a timer of timeout less than 100ms, to give enough + * time for template update and transmission + */ + limSendDfsChanSwIEUpdate(pMac, psessionEntry); + } + else + { + /* Done with CSA IE update, send response back to SME */ + psessionEntry->gLimChannelSwitch.switchCount = 0; + psessionEntry->dfsIncludeChanSwIe = VOS_FALSE; + + /* Reset CSA IE parameters in beacon/probe responses */ + limSendDfsChanSwIEUpdate(pMac, psessionEntry); + + pChanSwTxResponse = (tSirSmeCSAIeTxCompleteRsp *) + vos_mem_malloc(length); + + if (NULL == pChanSwTxResponse) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp")); + return; + } + + vos_mem_set((void*)pChanSwTxResponse, length, 0); + pChanSwTxResponse->sessionId = psessionEntry->smeSessionId; + pChanSwTxResponse->chanSwIeTxStatus = VOS_STATUS_SUCCESS; + + mmhMsg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND; + mmhMsg.bodyptr = pChanSwTxResponse; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + } + } + + return; +} + diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h index 6e2602aa4598..958e28fb34f5 100644 --- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h +++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h @@ -123,5 +123,14 @@ void limSendSmeTdlsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, #endif #endif +void limSendSmeDfsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, + void *event); +void limSendSmeAPChannelSwitchResp(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSwitchChannelParams pChnlParams); +void +limProcessBeaconTxSuccessInd(tpAniSirGlobal pMac, tANI_U16 msgType, + void *event); + #endif /* __LIM_SEND_SME_RSP_H */ diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h index bbe0c71e0d1f..bb7e1d1c8cf9 100644 --- a/CORE/MAC/src/pe/lim/limTypes.h +++ b/CORE/MAC/src/pe/lim/limTypes.h @@ -161,6 +161,7 @@ enum eChannelChangeReasonCodes LIM_SWITCH_CHANNEL_REASSOC, LIM_SWITCH_CHANNEL_JOIN, LIM_SWITCH_CHANNEL_OPERATION, // Generic change channel + LIM_SWITCH_CHANNEL_SAP_DFS, // DFS channel change }; typedef struct sLimAuthRspTimeout diff --git a/CORE/MAC/src/pe/sch/schBeaconGen.c b/CORE/MAC/src/pe/sch/schBeaconGen.c index 50fa74e776c4..f015d7f39b80 100644 --- a/CORE/MAC/src/pe/sch/schBeaconGen.c +++ b/CORE/MAC/src/pe/sch/schBeaconGen.c @@ -64,7 +64,7 @@ const tANI_U8 P2pOui[] = {0x50, 0x6F, 0x9A, 0x9}; tSirRetStatus schGetP2pIeOffset(tANI_U8 *pExtraIe, tANI_U32 extraIeLen, tANI_U16 *pP2pIeOffset) { - tSirRetStatus status = eSIR_FAILURE; + tSirRetStatus status = eSIR_FAILURE; *pP2pIeOffset = 0; // Extra IE is not present @@ -87,7 +87,7 @@ tSirRetStatus schGetP2pIeOffset(tANI_U8 *pExtraIe, tANI_U32 extraIeLen, tANI_U16 (*pP2pIeOffset)++; pExtraIe++; - }while(--extraIeLen > 0); + }while(--extraIeLen > 0); return status; } @@ -99,7 +99,7 @@ tSirRetStatus schAppendAddnIE(tpAniSirGlobal pMac, tpPESession psessionEntry, tSirRetStatus status = eSIR_FAILURE; tANI_U32 present, len; tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN]; - + if((status = wlan_cfgGetInt(pMac, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, &present)) != eSIR_SUCCESS) { @@ -117,10 +117,10 @@ tSirRetStatus schAppendAddnIE(tpAniSirGlobal pMac, tpPESession psessionEntry, return status; } - if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len && + if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len && ((len + *nBytes) <= maxBeaconSize)) { - if((status = wlan_cfgGetStr(pMac, + if((status = wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &addIE[0], &len)) == eSIR_SUCCESS) { @@ -230,7 +230,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn for (i=0; i<6; i++) mac->da[i] = 0xff; - + /* Knocking out Global pMac update */ /* limGetMyMacAddr(pMac, mac->sa); */ /* limGetBssid(pMac, mac->bssId); */ @@ -271,7 +271,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn offset = sizeof( tAniBeaconStruct ); ptr = pMac->sch.schObject.gSchBeaconFrameBegin + offset; - if((psessionEntry->limSystemRole == eLIM_AP_ROLE) + if((psessionEntry->limSystemRole == eLIM_AP_ROLE) && (psessionEntry->proxyProbeRspEn)) { /* Initialize the default IE bitmap to zero */ @@ -312,7 +312,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn * Initialize the 'new' fields at the end of the beacon */ - + PopulateDot11fCountry( pMac, &pBcn2->Country, psessionEntry); if(pBcn1->Capabilities.qos) { @@ -323,6 +323,33 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn { PopulateDot11fPowerConstraints( pMac, &pBcn2->PowerConstraints ); PopulateDot11fTPCReport( pMac, &pBcn2->TPCReport, psessionEntry); + + /* Need to insert channel switch announcement here */ + if ((psessionEntry->limSystemRole == eLIM_AP_ROLE || + psessionEntry->limSystemRole == eLIM_P2P_DEVICE_GO) && + psessionEntry->dfsIncludeChanSwIe == VOS_TRUE) + { + /* Channel switch announcement only if radar is detected + * and SAP has instructed to announce channel switch IEs + * in beacon and probe responses + */ + PopulateDot11fChanSwitchAnn(pMac, &pBcn2->ChanSwitchAnn, + psessionEntry); + + /* TODO: depending the CB mode, extended channel switch announcement + * need to be called + */ + /*PopulateDot11fExtChanSwitchAnn(pMac, &pBcn2->ExtChanSwitchAnn, + psessionEntry);*/ +#ifdef WLAN_FEATURE_11AC + /* TODO: If in 11AC mode, wider bw channel switch announcement needs + * to be called + */ + /*PopulateDot11fWiderBWChanSwitchAnn(pMac, &pBcn2->WiderBWChanSwitchAnn, + psessionEntry);*/ +#endif + + } } @@ -336,7 +363,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn } #ifdef WLAN_FEATURE_11AC if(psessionEntry->vhtCapability) - { + { schLog( pMac, LOGW, FL("Populate VHT IEs in Beacon")); PopulateDot11fVHTCaps( pMac, psessionEntry, &pBcn2->VHTCaps ); PopulateDot11fVHTOperation( pMac, &pBcn2->VHTOperation); @@ -350,7 +377,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &pBcn2->ExtSuppRates, psessionEntry ); - + if( psessionEntry->pLimStartBssReq != NULL ) { PopulateDot11fWPA( pMac, &psessionEntry->pLimStartBssReq->rsnIE, @@ -367,7 +394,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn { if(psessionEntry->wps_state != SAP_WPS_DISABLED) { - PopulateDot11fBeaconWPSIEs( pMac, &pBcn2->WscBeacon, psessionEntry); + PopulateDot11fBeaconWPSIEs( pMac, &pBcn2->WscBeacon, psessionEntry); } } else @@ -395,7 +422,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn } } - if((psessionEntry->limSystemRole == eLIM_AP_ROLE) + if((psessionEntry->limSystemRole == eLIM_AP_ROLE) && (psessionEntry->proxyProbeRspEn)) { /* Can be efficiently updated whenever new IE added in Probe response in future */ @@ -447,7 +474,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn extraIeOffset = nBytes; //TODO: Append additional IE here. - schAppendAddnIE(pMac, psessionEntry, + schAppendAddnIE(pMac, psessionEntry, pMac->sch.schObject.gSchBeaconFrameEnd + nBytes, SCH_MAX_BEACON_SIZE, &nBytes); @@ -461,7 +488,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn if(eSIR_SUCCESS == status) { //Update the P2P Ie Offset - pMac->sch.schObject.p2pIeOffset = + pMac->sch.schObject.p2pIeOffset = pMac->sch.schObject.gSchBeaconOffsetBegin + TIM_IE_SIZE + extraIeOffset + p2pIeOffset; } @@ -696,7 +723,7 @@ void writeBeaconToMemory(tpAniSirGlobal pMac, tANI_U16 size, tANI_U16 length, tp for (i=0; i < pMac->sch.schObject.gSchBeaconOffsetEnd; i++) pMac->sch.schObject.gSchBeaconFrameBegin[size++] = pMac->sch.schObject.gSchBeaconFrameEnd[i]; } - + // Update the beacon length pBeacon = (tpAniBeaconStruct) pMac->sch.schObject.gSchBeaconFrameBegin; // Do not include the beaconLength indicator itself @@ -765,8 +792,8 @@ schProcessPreBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { PELOGE(schLog(pMac, LOGE, FL("session lookup fails"));) goto end; - } - + } + // If SME is not in normal mode, no need to generate beacon diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h index 13db475cebdd..ccbbcabcf157 100644 --- a/CORE/SAP/inc/sapApi.h +++ b/CORE/SAP/inc/sapApi.h @@ -192,6 +192,7 @@ typedef enum { eSAP_MAC_TRIG_STOP_BSS_EVENT, eSAP_UNKNOWN_STA_JOIN, /* Event send when a STA in neither white list or black list tries to associate in softap mode */ eSAP_MAX_ASSOC_EXCEEDED, /* Event send when a new STA is rejected association since softAP max assoc limit has reached */ + eSAP_CHANNEL_CHANGE_EVENT, } eSapHddEvent; typedef enum { @@ -363,9 +364,11 @@ typedef struct sap_MaxAssocExceededEvent_s { v_MACADDR_t macaddr; } tSap_MaxAssocExceededEvent; - -/* - This struct will be filled in and passed to tpWLAN_SAPEventCB that is provided during WLANSAP_StartBss call +typedef struct sap_OperatingChannelChangeEvent_s { + tANI_U8 operatingChannel; +} tSap_OperatingChannelChangeEvent; +/* + This struct will be filled in and passed to tpWLAN_SAPEventCB that is provided during WLANSAP_StartBss call The event id corresponding to structure in the union is defined in comment next to the structure */ @@ -387,6 +390,7 @@ typedef struct sap_Event_s { tSap_SendActionCnf sapActionCnf; /* eSAP_SEND_ACTION_CNF */ tSap_UnknownSTAJoinEvent sapUnknownSTAJoin; /* eSAP_UNKNOWN_STA_JOIN */ tSap_MaxAssocExceededEvent sapMaxAssocExceeded; /* eSAP_MAX_ASSOC_EXCEEDED */ + tSap_OperatingChannelChangeEvent sapChannelChange; /* eSAP_CHANNEL_CHANGE_EVENT */ } sapevt; } tSap_Event, *tpSap_Event; @@ -437,7 +441,7 @@ typedef struct sap_Config { v_U32_t ap_table_expiration_time; v_U32_t ht_op_mode_fixed; tVOS_CON_MODE persona; /*Tells us which persona it is GO or AP for now*/ - + v_U8_t disableDFSChSwitch; } tsap_Config_t; typedef enum { @@ -565,6 +569,7 @@ typedef struct sap_SoftapStats_s { int sapSetPreferredChannel(tANI_U8* ptr); void sapCleanupChannelList(void); +void sapCleanupAllChannelList(void); /*========================================================================== FUNCTION WLANSAP_Set_WpsIe @@ -1536,6 +1541,89 @@ VOS_STATUS WLANSAP_RegisterMgmtFrame( v_PVOID_t pvosGCtx, tANI_U16 frameType, VOS_STATUS WLANSAP_DeRegisterMgmtFrame( v_PVOID_t pvosGCtx, tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen ); +/*========================================================================== + + FUNCTION WLANSAP_ChannelChangeRequest + DESCRIPTION + This API is used to send an Indication to SME/PE to change the + current operating channel to a different target channel. + + The Channel change will be issued by SAP under the following + scenarios. + 1. A radar indication is received during SAP CAC WAIT STATE and + channel change is required. + 2. A radar indication is received during SAP STARTED STATE and + channel change is required. + + DEPENDENCIES + NA. + +PARAMETERS + +IN + pvosGCtx: Pointer to vos global context structure + TargetChannel: New target channel for channel change. + +RETURN VALUE + The VOS_STATUS code associated with performing the operation + +VOS_STATUS_SUCCESS: Success + +SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_ChannelChangeRequest(v_PVOID_t pvosGCtx, tANI_U8 tArgetChannel); + +/*========================================================================== + + FUNCTION WLANSAP_StartBeaconReq + DESCRIPTION + This API is used to send an Indication to SME/PE to start + beaconing on the current operating channel. + + Brief:When SAP is started on DFS channel and when ADD BSS RESP is received + LIM temporarily holds off Beaconing for SAP to do CAC WAIT. When + CAC WAIT is done SAP resumes the Beacon Tx by sending a start beacon + request to LIM. + + DEPENDENCIES + NA. + +PARAMETERS + +IN + pvosGCtx: Pointer to vos global context structure + +RETURN VALUE + The VOS_STATUS code associated with performing the operation + +VOS_STATUS_SUCCESS: Success + +SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_StartBeaconReq(v_PVOID_t pSapCtx); + +/*========================================================================== + FUNCTION WLANSAP_DfsSendCSAIeRequest + + DESCRIPTION + This API is used to send channel switch announcement request to PE + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DfsSendCSAIeRequest(v_PVOID_t pSapCtx); + #ifdef __cplusplus } diff --git a/CORE/SAP/src/sapApiLinkCntl.c b/CORE/SAP/src/sapApiLinkCntl.c index 2a87dbd22d69..7b4a18a91f62 100644 --- a/CORE/SAP/src/sapApiLinkCntl.c +++ b/CORE/SAP/src/sapApiLinkCntl.c @@ -409,7 +409,24 @@ WLANSAP_RoamCallback (v_PVOID_t) eSAP_STATUS_SUCCESS ); break; - default: + case eCSR_ROAM_DFS_RADAR_IND: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Received Radar Indication", __func__); + sapContext->SapDfsInfo.target_channel = + sapIndicateRadar(sapContext, &pCsrRoamInfo->dfs_event); + break; + + case eCSR_ROAM_DFS_CHAN_SW_NOTIFY: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Received Chan Sw Update Notification", __func__); + break; + + case eCSR_ROAM_SET_CHANNEL_RSP: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Received set channel response", __func__); + break; + + default: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, CSR roamStatus not handled roamStatus = %s (%d)\n", __func__, get_eRoamCmdStatus_str(roamStatus), roamStatus); break; @@ -559,13 +576,16 @@ WLANSAP_RoamCallback case eCSR_ROAM_RESULT_INFRA_STARTED: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, CSR roamResult = %s (%d)\n", __func__, "eCSR_ROAM_RESULT_INFRA_STARTED", roamResult); - /* Fill in the event structure */ + + /* In the current implementation, hostapd is not aware that + * drive will support DFS. Hence, driver should inform + * eSAP_MAC_START_BSS_SUCCESS to upper layers and then perform + * CAC underneath + */ sapEvent.event = eSAP_MAC_START_BSS_SUCCESS; sapEvent.params = pCsrRoamInfo; sapEvent.u1 = roamStatus; sapEvent.u2 = roamResult; - - /* Handle event */ vosStatus = sapFsm(sapContext, &sapEvent); if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { @@ -636,6 +656,193 @@ WLANSAP_RoamCallback } break; + + case eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND: + if (eSAP_DFS_CAC_WAIT == sapContext->sapsMachine) + { + if (VOS_TRUE == sapContext->SapDfsInfo.sap_radar_found_status) + { + /* + * If Radar is found, while in DFS CAC WAIT State then + * post stop and destroy the CAC timer and post a + * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND to sapFsm. + */ + vos_timer_stop(&sapContext->SapDfsInfo.sap_dfs_cac_timer); + vos_timer_destroy(&sapContext->SapDfsInfo.sap_dfs_cac_timer); + sapContext->SapDfsInfo.is_dfs_cac_timer_running = 0; + + sapEvent.event = eSAP_DFS_CHANNEL_CAC_RADAR_FOUND; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + } + else if(eSAP_STARTED == sapContext->sapsMachine) + { + /* Radar found on the operating channel in STARTED state, + * new operating channel has already been selected. Send + * request to SME-->PE for sending CSA IE + */ + sapEvent.event = eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + else + { + /* Further actions to be taken here */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "In %s, eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in" + "(%d) state\n", __func__, sapContext->sapsMachine); + } + break; + + case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS: + case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE: + { + eCsrPhyMode phyMode = + sapConvertSapPhyModeToCsrPhyMode(sapContext->csrRoamProfile.phyMode); + tHalHandle hHal = + (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, sapContext->pvosGCtx); + + /* Both success and failure cases are handled intentionally handled + * together. Irrespective of whether the channel switch IE was + * sent out successfully or not, SAP should still vacate the + * channel immediately + */ + if (eSAP_STARTED == sapContext->sapsMachine) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", + __func__, "eSAP_STARTED", "eSAP_DISCONNECTING"); + + /* SAP to be moved to DISCONNECTING state */ + sapContext->sapsMachine = eSAP_DISCONNECTING; + + /* The associated stations have been informed to move + * to a different channel. However, the AP may not always + * select the advertised channel for operation if the radar + * is seen. In that case, the stations will experience link-loss + * and return back through scanning if they wish to + */ + + /* Send channel change request + * From spec it is required that the AP should continue to + * operate in the same mode as it is operating currently. + * For e.g. 20/40/80 MHz operation + */ + if (sapContext->SapDfsInfo.target_channel) + { + sme_SelectCBMode(hHal, phyMode, + sapContext->SapDfsInfo.target_channel); + } + + /* Send channel switch request */ + sapEvent.event = eWNI_SME_CHANNEL_CHANGE_REQ; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + + /* Handle event */ + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + else + { + /* Further actions to be taken here */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "In %s, eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in" + "(%d) state\n", __func__, sapContext->sapsMachine); + } + break; + } + case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS: + { + /* Channel change is successful. If the new channel is a DFS + * channel, then we will to perform channel availability check + * for 60 seconds + */ + sapContext->channel = + sapContext->SapDfsInfo.target_channel; + + /* Identify if this is channel change in radar detected state */ + if (VOS_TRUE == sapContext->SapDfsInfo.sap_radar_found_status && + eSAP_DISCONNECTING == sapContext->sapsMachine) + { + /* check if currently selected channel is a DFS channel */ + if (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(sapContext->channel)) + { + sapContext->sapsMachine = eSAP_DISCONNECTED; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", __func__, + "eSAP_DISCONNECTING", "DISCONNECTED"); + + /* DFS Channel */ + sapEvent.event = eSAP_DFS_CHANNEL_CAC_START; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + } + else + { + /* non-DFS channel */ + sapContext->sapsMachine = eSAP_STARTING; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", __func__, + "eSAP_DISCONNECTING", "eSAP_STARTING"); + + sapContext->SapDfsInfo.sap_radar_found_status = VOS_FALSE; + sapEvent.event = eSAP_MAC_START_BSS_SUCCESS; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = eCSR_ROAM_INFRA_IND; + sapEvent.u2 = eCSR_ROAM_RESULT_INFRA_STARTED; + } + + /* Handle the event */ + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + + } + else + { + /* We may have a requirment in the future for SAP to perform + * channel change, hence leaving this here + */ + } + + break; + } + case eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE: + { + /* This is much more serious issue, we have to vacate the + * channel due to the presence of radar but our channel change + * failed, stop the BSS operation completely and inform hostapd + */ + sapContext->sapsMachine = eSAP_DISCONNECTED; + + /* Inform cfg80211 and hostapd that BSS is not alive anymore */ + } + break; + default: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, CSR roamResult = %s (%d) not handled\n", __func__,get_eCsrRoamResult_str(roamResult),roamResult); diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c index ddba2f0b2e69..7664e054c79e 100644 --- a/CORE/SAP/src/sapFsm.c +++ b/CORE/SAP/src/sapFsm.c @@ -93,6 +93,48 @@ static VOS_STATUS sapGetChannelList(ptSapContext sapContext, v_U8_t **channelList, v_U8_t *numberOfChannels); #endif + +/*========================================================================== + FUNCTION sapGet5GHzChannelList + + DESCRIPTION + Function for initializing list of 2.4/5 Ghz [NON-DFS/DFS] available + channels in the current regulatory domain. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext: SAP Context + + RETURN VALUE + NA + + SIDE EFFECTS +============================================================================*/ +static VOS_STATUS sapGet5GHzChannelList(ptSapContext sapContext); + +/*========================================================================== + FUNCTION sapStartDfsCacTimer + + DESCRIPTION + Function to start the DFS CAC timer when SAP is started on DFS Channel + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext: SAP Context + RETURN VALUE + DFS Timer start status + SIDE EFFECTS +============================================================================*/ + +int sapStartDfsCacTimer(ptSapContext sapContext); + /*---------------------------------------------------------------------------- * Externalized Function Definitions * -------------------------------------------------------------------------*/ @@ -727,6 +769,14 @@ sapSignalHDDevent (v_PVOID_t)pCsrRoamInfo->peerMac, sizeof(v_MACADDR_t)); break; + case eSAP_CHANNEL_CHANGE_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s", + __func__, "eSAP_CHANNEL_CHANGE_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_CHANNEL_CHANGE_EVENT; + sapApAppEvent.sapevt.sapChannelChange.operatingChannel = + sapContext->SapDfsInfo.target_channel; + default: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, SAP Unknown callback event = %d", __func__,sapHddevent); @@ -829,6 +879,18 @@ sapFsm VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", __func__, "eSAP_DISCONNECTED", "eSAP_CH_SELECT"); } + if (msg == eSAP_DFS_CHANNEL_CAC_START) + { + /* No need of state check here, caller is expected to perform + * the checks before sending the event + */ + sapContext->sapsMachine = eSAP_DFS_CAC_WAIT; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "ENTERTRED eSAP_DISCONNECTED-->eSAP_DFS_CAC_WAIT\n"); + + sapStartDfsCacTimer(sapContext); + } else { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, event msg %d", @@ -881,6 +943,90 @@ sapFsm } break; + case eSAP_DFS_CAC_WAIT: + if (msg == eSAP_DFS_CHANNEL_CAC_START) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_CH_SELECT", "eSAP_DFS_CAC_WAIT"); + sapStartDfsCacTimer(sapContext); + } + else if (msg == eSAP_DFS_CHANNEL_CAC_RADAR_FOUND) + { + /* Radar found while performing channel availability + * check, need to switch the channel again + */ + eCsrPhyMode phyMode = + sapConvertSapPhyModeToCsrPhyMode(sapContext->csrRoamProfile.phyMode); + tHalHandle hHal = + (tHalHandle)vos_get_context(VOS_MODULE_ID_SME, sapContext->pvosGCtx); + + /* SAP to be moved to DISCONNECTING state */ + sapContext->sapsMachine = eSAP_DISCONNECTING; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "ENTERTRED CAC WAIT STATE-->eSAP_DISCONNECTING\n"); + + if (sapContext->SapDfsInfo.target_channel) + { + sme_SelectCBMode(hHal, phyMode, + sapContext->SapDfsInfo.target_channel); + } + + /* + * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND: + * A Radar is found on current DFS Channel + * while in CAC WAIT period So, do a channel switch + * to randomly selected target channel. + * Send the Channel change message to SME/PE. + * sap_radar_found_status is set to 1 + */ + + WLANSAP_ChannelChangeRequest((v_PVOID_t)sapContext, + sapContext->SapDfsInfo.target_channel); + } + else if (msg == eSAP_DFS_CHANNEL_CAC_END) + { + /* + * eSAP_DFS_CHANNEL_CAC_END: + * CAC Period elapsed and there was no radar + * found so, SAP can continue beaconing. + * sap_radar_found_status is set to 0 + */ + sapContext->SapDfsInfo.sap_radar_found_status = VOS_FALSE; + + /* Start beaconing on the new channel */ + WLANSAP_StartBeaconReq((v_PVOID_t)sapContext); + + /* Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state channel = %d %s => %s", + __func__,sapContext->channel, "eSAP_STARTING", + "eSAP_STARTED"); + + sapContext->sapsMachine = eSAP_STARTED; + + /*Action code for transition */ + vosStatus = sapSignalHDDevent(sapContext, roamInfo, + eSAP_START_BSS_EVENT, + (v_PVOID_t)eSAP_STATUS_SUCCESS); + + /* Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", + __func__, "eSAP_DFS_CAC_WAIT", "eSAP_STARTED"); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, in state %s, invalid event msg %d", + __func__, "eSAP_DFS_CAC_WAIT", msg); + } + break; + case eSAP_STARTING: if (msg == eSAP_MAC_START_BSS_SUCCESS ) { @@ -889,12 +1035,30 @@ sapFsm __func__,sapContext->channel, "eSAP_STARTING", "eSAP_STARTED"); sapContext->sapsMachine = eSAP_STARTED; + /*Action code for transition */ vosStatus = sapSignalHDDevent( sapContext, roamInfo, eSAP_START_BSS_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); /* Transition from eSAP_STARTING to eSAP_STARTED (both without substates) */ VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", __func__, "eSAP_STARTING", "eSAP_STARTED"); + + /* The upper layers have been informed that AP is up and + * running, however, the AP is still not beaconing, until + * CAC is done if the operating channel is DFS + */ + if (vos_nv_getChannelEnabledState(sapContext->channel) == NV_CHANNEL_DFS) + { + /* Move the device in CAC_WAIT_STATE */ + sapContext->sapsMachine = eSAP_DFS_CAC_WAIT; + + /* TODO: Need to stop the OS transmit queues, so that no traffic + * can flow down the stack + */ + + /* Start CAC wait timer */ + sapStartDfsCacTimer(sapContext); + } } else if (msg == eSAP_MAC_START_FAILS) { @@ -938,6 +1102,23 @@ sapFsm } } } + else if (msg == eSAP_OPERATING_CHANNEL_CHANGED) + { + /* The operating channel has changed, update hostapd */ + sapContext->channel = + (tANI_U8)sapContext->SapDfsInfo.target_channel; + + sapContext->sapsMachine = eSAP_STARTED; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", + __func__, "eSAP_STARTING", "eSAP_STARTED"); + + /* Indicate change in the state to upper layers */ + vosStatus = sapSignalHDDevent(sapContext, roamInfo, + eSAP_START_BSS_EVENT, + (v_PVOID_t)eSAP_STATUS_SUCCESS); + } else { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, @@ -956,6 +1137,17 @@ sapFsm sapContext->sapsMachine = eSAP_DISCONNECTING; vosStatus = sapGotoDisconnecting(sapContext); } + else if (eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START == msg) + { + /* Radar is seen on the current operating channel + * send CSA IE for all associated stations + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Send CSA IE Request", __func__); + + /* Request for CSA IE transmission */ + WLANSAP_DfsSendCSAIeRequest(sapContext); + } else { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, invalid event msg %d", @@ -997,6 +1189,19 @@ sapFsm } } } + else if (msg == eWNI_SME_CHANNEL_CHANGE_REQ) + { + /* Most likely, radar has been detected and SAP wants to + * change the channel + */ + vosStatus = + WLANSAP_ChannelChangeRequest((v_PVOID_t)sapContext, + sapContext->SapDfsInfo.target_channel); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "In %s, Sending DFS eWNI_SME_CHANNEL_CHANGE_REQ", + __func__); + } else { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, @@ -1016,6 +1221,7 @@ sapconvertToCsrProfile(tsap_Config_t *pconfig_params, eCsrRoamBssType bssType, t profile->BSSType = eCSR_BSS_TYPE_INFRA_AP; profile->SSIDs.numOfSSIDs = 1; profile->csrPersona = pconfig_params->persona; + profile->disableDFSChSwitch = pconfig_params->disableDFSChSwitch; vos_mem_zero(profile->SSIDs.SSIDList[0].SSID.ssId, sizeof(profile->SSIDs.SSIDList[0].SSID.ssId)); @@ -1449,3 +1655,225 @@ static VOS_STATUS sapGetChannelList(ptSapContext sapContext, return VOS_STATUS_SUCCESS; } #endif + +/* + * Function for initializing list of 2.4/5 Ghz [NON-DFS/DFS] + * available channels in the current regulatory domain. + */ +static VOS_STATUS sapGet5GHzChannelList(ptSapContext sapContext) +{ + v_U8_t count = 0; + int i; + if (NULL == sapContext) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Invalid sapContext pointer on sapGetChannelList"); + return VOS_STATUS_E_FAULT; + } + + sapContext->SapAllChnlList.channelList = + (v_U8_t *)vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (NULL == sapContext->SapAllChnlList.channelList) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + " Memory Allocation failed sapGetChannelList"); + return VOS_STATUS_E_FAULT; + } + + for( i = RF_CHAN_36; i <= RF_CHAN_165; i++ ) + { + if( regChannels[i].enabled == NV_CHANNEL_ENABLE || + regChannels[i].enabled == NV_CHANNEL_DFS ) + { + sapContext->SapAllChnlList.channelList[count] = + rfChannels[i].channelNum; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s[%d] CHANNEL = %d",__func__, __LINE__, + sapContext->SapAllChnlList.channelList[count]); + count++; + } + } + + sapContext->SapAllChnlList.numChannel = count; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s[%d] NUMBER OF CHANNELS count = %d" + "sapContext->SapAllChnlList.numChannel = %d", + __func__,__LINE__,count,sapContext->SapAllChnlList.numChannel); + return VOS_STATUS_SUCCESS; +} + +/* + * This function randomly selects the channel to switch after the detection + * of radar + * param sapContext - sap context + * dfs_event - Dfs information from DFS + * return - channel to which AP wishes to switch + */ +v_U8_t sapIndicateRadar(ptSapContext sapContext,tSirSmeDfsEventInd *dfs_event) +{ + v_U8_t available_chan_idx[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + int available_chan_count, numGChannels = 0, numAChannels = 0; + v_U8_t total_num_channels = 0; + v_U8_t target_channel = 0; + int i; + + if (NULL == sapContext || NULL == dfs_event) + { + /* Invalid sap context of dfs event passed */ + return 0; + } + + if (!dfs_event->dfs_radar_status) + { + /*dfs status does not indicate a radar on the channel-- False Alarm*/ + return 0; + } + + /* set the Radar Found flag in SapDfsInfo */ + sapContext->SapDfsInfo.sap_radar_found_status = VOS_TRUE; + + /* We need to generate Channel Switch IE if the radar is found in the + * operating state + */ + if (eSAP_STARTED == sapContext->sapsMachine) + sapContext->SapDfsInfo.csaIERequired = VOS_TRUE; + + if (sapContext->csrRoamProfile.disableDFSChSwitch) + { + return sapContext->channel; + } + + sapGet5GHzChannelList(sapContext); + total_num_channels = sapContext->SapAllChnlList.numChannel; + + /* + * Find how many G channels are present in the channel list + */ + for(i = 0; i < RF_CHAN_14; i++ ) + { + if( regChannels[i].enabled ) + { + numGChannels++; + } + } + numAChannels = (total_num_channels - numGChannels); + + /* + * (1) skip static turbo channel as it will require STA to be in + * static turbo to work. + * (2) skip channel which's marked with radar detction + * (3) WAR: we allow user to config not to use any DFS channel + * (4) When we pick a channel, skip excluded 11D channels + * (5) Create the available channel list with the above rules + */ + + for(i = 0, available_chan_count = 0; i<= total_num_channels; i++) + { + if (sapContext->SapAllChnlList.channelList[i] == + dfs_event->ieee_chan_number) + { + continue;//skip the channel on which radar is found + } + available_chan_idx[available_chan_count++] = + sapContext->SapAllChnlList.channelList[i]; + } + + if(available_chan_count) + { + v_U32_t random_byte = 0; + + /* logic to generate a random index */ + get_random_bytes(&random_byte,1); + i = (random_byte + jiffies) % available_chan_count; + + /* + * Pick the channel from the random index + * in available_chan_idx list + */ + target_channel = (available_chan_idx[i]); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s[%d]: Target channel Index = %d target_channel = %d", + __func__,__LINE__, i, target_channel); + return target_channel; + } + + return 0; +} + +/* + * CAC timer callback function. + * Post eSAP_DFS_CHANNEL_CAC_END event to sapFsm(). + */ +void sapDfsCacTimerCallback(void *data) +{ + ptSapContext sapContext = (ptSapContext)data; + tWLAN_SAPEvent sapEvent; + + /* Check to ensure that SAP is in DFS WAIT state*/ + if (sapContext->sapsMachine == eSAP_DFS_CAC_WAIT) + { + vos_timer_destroy(&sapContext->SapDfsInfo.sap_dfs_cac_timer); + sapContext->SapDfsInfo.is_dfs_cac_timer_running = 0; + /* + * CAC Complete, post eSAP_DFS_CHANNEL_CAC_END to sapFsm + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: Sending eSAP_DFS_CHANNEL_CAC_END for target_channel = %d", + __func__,__LINE__, sapContext->SapDfsInfo.target_channel); + sapEvent.event = eSAP_DFS_CHANNEL_CAC_END; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + } + else if (sapContext->sapsMachine == eSAP_DFS_CAC_WAIT) + { + vos_timer_destroy(&sapContext->SapDfsInfo.sap_dfs_cac_timer); + sapContext->SapDfsInfo.is_dfs_cac_timer_running = 0; + + /* + * CAC Complete, post eSAP_DFS_CHANNEL_CAC_END to sapFsm + */ + sapEvent.event = eSAP_DFS_CHANNEL_CAC_END; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + } + + sapFsm(sapContext, &sapEvent); +} + +/* + * Function to start the DFS CAC Timer + * when SAP is started on a DFS channel + */ +int sapStartDfsCacTimer(ptSapContext sapContext) +{ + VOS_STATUS status; + if (sapContext == NULL) + { + return 0; + } + if (sapContext->SapDfsInfo.ignore_cac) + { + /* + * If User has set to ignore the CAC + * so, continue without CAC Timer. + */ + return 2; + } + vos_timer_init(&sapContext->SapDfsInfo.sap_dfs_cac_timer, + VOS_TIMER_TYPE_SW, + sapDfsCacTimerCallback, (v_PVOID_t)sapContext); + + /*Start the CAC timer for 60 Seconds*/ + status = vos_timer_start(&sapContext->SapDfsInfo.sap_dfs_cac_timer, 60000); + if (status == VOS_STATUS_SUCCESS) + { + sapContext->SapDfsInfo.is_dfs_cac_timer_running = VOS_TRUE; + return 1; + } + else + { + return 0; + } +} diff --git a/CORE/SAP/src/sapFsm_ext.h b/CORE/SAP/src/sapFsm_ext.h index 5535732b235c..315e0e91eea5 100644 --- a/CORE/SAP/src/sapFsm_ext.h +++ b/CORE/SAP/src/sapFsm_ext.h @@ -50,6 +50,11 @@ typedef enum eSAP_MAC_START_FAILS, eSAP_HDD_STOP_INFRA_BSS, eSAP_WRITE_REMOTE_AMP_ASSOC, + eSAP_DFS_CHANNEL_CAC_START, + eSAP_DFS_CHANNEL_CAC_RADAR_FOUND, + eSAP_DFS_CHANNEL_CAC_END, + eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START, + eSAP_OPERATING_CHANNEL_CHANGED, eSAP_NO_MSG }eSapMsg_t; diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h index aa23a9ba40aa..248614ac45b0 100644 --- a/CORE/SAP/src/sapInternal.h +++ b/CORE/SAP/src/sapInternal.h @@ -121,6 +121,7 @@ typedef struct sSapContext tSapContext; typedef enum { eSAP_DISCONNECTED, eSAP_CH_SELECT, + eSAP_DFS_CAC_WAIT, eSAP_STARTING, eSAP_STARTED, eSAP_DISCONNECTING @@ -137,6 +138,25 @@ typedef struct sSapQosCfg { v_U8_t WmmIsEnabled; } tSapQosCfg; +typedef struct sSapDfsInfo { + vos_timer_t sap_dfs_cac_timer; + v_U8_t sap_radar_found_status; + v_U8_t is_dfs_cac_timer_running; + + /* + * New channel to move to when a Radar is + * detected on current Channel + */ + v_U8_t target_channel; + v_U8_t last_radar_found_channel; + v_U8_t ignore_cac; + + /* Requests for Channel Switch Announcement IE + * generation and transmission + */ + v_U8_t csaIERequired; +}tSapDfsInfo; + typedef struct sSapContext { vos_lock_t SapGlobalLock; @@ -208,6 +228,18 @@ typedef struct sSapContext { // session to scan tANI_BOOLEAN isScanSessionOpen; + /* + * This list of channels will hold 5Ghz enabled,DFS in the + * Current RegDomain.This list will be used to select a channel, + * for SAP to start including any DFS channel and also to select + * any random channel[5Ghz-(NON-DFS/DFS)],if SAP is operating + * on a DFS channel and a RADAR is detected on the channel. + */ + tSapChannelListInfo SapAllChnlList; + + //Information Required for SAP DFS Master mode + tSapDfsInfo SapDfsInfo; + } *ptSapContext; @@ -772,6 +804,23 @@ eCsrPhyMode sapConvertSapPhyModeToCsrPhyMode( eSapPhyMode sapPhyMode ); void sapUpdateUnsafeChannelList(void); #endif /* FEATURE_WLAN_CH_AVOID */ +/*--------------------------------------------------------------------------- +FUNCTION sapIndicateRadar + +DESCRIPTION Function to implement actions on Radar Detection when SAP is on + DFS Channel + +DEPENDENCIES PARAMETERS +IN sapContext : Sap Context which hold SapDfsInfo + dfs_event : Event from DFS Module + +RETURN VALUE : Target Channel For SAP to Move on to when Radar is Detected. + +SIDE EFFECTS +---------------------------------------------------------------------------*/ +v_U8_t +sapIndicateRadar(ptSapContext sapContext,tSirSmeDfsEventInd *dfs_event); + #ifdef __cplusplus } #endif diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index b644747209af..e94f3eb53a54 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -2363,3 +2363,184 @@ VOS_STATUS WLANSAP_DeRegisterMgmtFrame( v_PVOID_t pvosGCtx, tANI_U16 frameType, return VOS_STATUS_E_FAULT; } + +/*========================================================================== + FUNCTION WLANSAP_ChannelChangeRequest + + DESCRIPTION + This API is used to send an Indication to SME/PE to change the + current operating channel to a different target channel. + + The Channel change will be issued by SAP under the following + scenarios. + 1. A radar indication is received during SAP CAC WAIT STATE and + channel change is required. + 2. A radar indication is received during SAP STARTED STATE and + channel change is required. + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_ChannelChangeRequest(v_PVOID_t pSapCtx, tANI_U8 tArgetChannel) +{ + ptSapContext sapContext = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + sapContext = (ptSapContext)pSapCtx; + + if ( NULL == sapContext ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_RoamChannelChangeReq( hHal, + sapContext->sessionId, tArgetChannel); + + if (halStatus == eHAL_STATUS_SUCCESS) + { + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION WLANSAP_StartBeaconReq + DESCRIPTION + This API is used to send an Indication to SME/PE to start + beaconing on the current operating channel. + + Brief:When SAP is started on DFS channel and when ADD BSS RESP is received + LIM temporarily holds off Beaconing for SAP to do CAC WAIT. When + CAC WAIT is done SAP resumes the Beacon Tx by sending a start beacon + request to LIM. + + DEPENDENCIES + NA. + +PARAMETERS + +IN + pvosGCtx: Pointer to vos global context structure + +RETURN VALUE + The VOS_STATUS code associated with performing the operation + +VOS_STATUS_SUCCESS: Success + +SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_StartBeaconReq(v_PVOID_t pSapCtx) +{ + ptSapContext sapContext = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + tANI_U8 dfsCacWaitStatus = 0; + sapContext = (ptSapContext)pSapCtx; + + if ( NULL == sapContext ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + /* No Radar was found during CAC WAIT, So start Beaconing */ + if (sapContext->SapDfsInfo.sap_radar_found_status == VOS_FALSE) + { + /* CAC Wait done without any Radar Detection */ + dfsCacWaitStatus = VOS_TRUE; + halStatus = sme_RoamStartBeaconReq( hHal, + sapContext->sessionId, dfsCacWaitStatus); + if (halStatus == eHAL_STATUS_SUCCESS) + { + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_E_FAULT; +} + + +/*========================================================================== + FUNCTION WLANSAP_DfsSendCSAIeRequest + + DESCRIPTION + This API is used to send channel switch announcement request to PE + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DfsSendCSAIeRequest(v_PVOID_t pSapCtx) +{ + ptSapContext sapContext = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + sapContext = (ptSapContext)pSapCtx; + + if ( NULL == sapContext ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_RoamCsaIeRequest(hHal, sapContext->sessionId, + sapContext->SapDfsInfo.target_channel, + sapContext->SapDfsInfo.csaIERequired); + if (halStatus == eHAL_STATUS_SUCCESS) + { + return VOS_STATUS_SUCCESS; + } + + return VOS_STATUS_E_FAULT; +} diff --git a/CORE/SERVICES/BMI/bmi.c b/CORE/SERVICES/BMI/bmi.c index 3835ff498b14..505bd0a17f25 100644 --- a/CORE/SERVICES/BMI/bmi.c +++ b/CORE/SERVICES/BMI/bmi.c @@ -24,26 +24,7 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//------------------------------------------------------------------------------ -// <copyright file="bmi.c" company="Atheros"> -// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ + //============================================================================== // // Author(s): ="Atheros" diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c index a22f2836d1b6..d3baacee8310 100644 --- a/CORE/SERVICES/BMI/ol_fw.c +++ b/CORE/SERVICES/BMI/ol_fw.c @@ -24,21 +24,7 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ + #include <linux/firmware.h> #include "ol_if_athvar.h" #include "ol_fw.h" @@ -495,6 +481,7 @@ u_int32_t host_interest_item_address(u_int32_t target_type, u_int32_t item_offse case TARGET_TYPE_AR9888: return (AR9888_HOST_INTEREST_ADDRESS + item_offset); case TARGET_TYPE_AR6320: + case TARGET_TYPE_AR6320V2: return (AR6320_HOST_INTEREST_ADDRESS + item_offset); } } @@ -507,6 +494,21 @@ static void ramdump_work_handler(struct work_struct *ramdump) void __iomem *ramdump_base; unsigned long address; unsigned long size; + u_int32_t host_interest_address; + + if (!ramdump_scn) { + printk("No RAM dump will be collected since ramdump_scn is NULL!\n"); + goto out; + } + + if (HIFDiagReadMem(ramdump_scn->hif_hdl, + host_interest_item_address(ramdump_scn->target_type, + offsetof(struct host_interest_s, hi_failure_state)), + (A_UCHAR*) &host_interest_address, sizeof(u_int32_t)) != A_OK) { + printk("HifDiagReadiMem FW Dump Area Pointer failed!\n"); + goto out; + } + printk("Host interest item address: 0x%08X\n", host_interest_address); /* Get RAM dump memory address and size */ if (cnss_get_ramdump_mem(&address, &size)) { @@ -521,16 +523,11 @@ static void ramdump_work_handler(struct work_struct *ramdump) goto out; } - if (ramdump_scn) { - ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE); + ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE); + iounmap(ramdump_base); - printk("%s: RAM dump collecting completed!\n", __func__); - msleep(500); - } else { - printk("No RAM dump will be collected since ramdump_scn is NULL!\n"); - } - - iounmap(ramdump_base); + printk("%s: RAM dump collecting completed!\n", __func__); + msleep(500); out: /* Notify SSR framework the target has crashed. */ @@ -552,7 +549,6 @@ void ol_target_failure(void *instance, A_STATUS status) A_UINT32 reg_dump_values[REGISTER_DUMP_LEN_MAX]; A_UINT32 reg_dump_cnt = 0; A_UINT32 i; -#endif A_UINT32 dbglog_hdr_address; struct dbglog_hdr_s dbglog_hdr; struct dbglog_buf_s dbglog_buf; @@ -561,6 +557,7 @@ void ol_target_failure(void *instance, A_STATUS status) A_UINT8 *dbglog_data; void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); +#endif if (OL_TRGET_STATUS_RESET == scn->target_status) { printk("Target is already asserted, ignore!\n"); @@ -597,7 +594,6 @@ void ol_target_failure(void *instance, A_STATUS status) for (i = 0; i < reg_dump_cnt; i++) { printk("[%02d] : 0x%08X\n", i, reg_dump_values[i]); } -#endif if (HIFDiagReadMem(scn->hif_hdl, host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_dbglog_hdr)), @@ -656,6 +652,7 @@ void ol_target_failure(void *instance, A_STATUS status) adf_os_mem_free(dbglog_data); } +#endif #if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC) && defined(CONFIG_CNSS) /* Collect the RAM dump through a workqueue */ @@ -972,49 +969,29 @@ void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength) struct ol_softc *scn = (struct ol_softc *)inst; char *bufferLoc = memoryBlock; int result = 0; - u_int32_t reg_dump_area = 0; u_int32_t amountRead = 0; u_int32_t sectionCount = 0; u_int32_t pos = 0; u_int32_t readLen = 0; /* - * SECTION = REGISTER - * START = Vary in target type - * LENGTH = 0x6c000 - * * SECTION = DRAM - * START = 0x400000 - * LENGTH = 0x50000 + * START = 0x00400000 + * LENGTH = 0x00070000 * * SECTION = IRAM - * START = 0x980000 - * LENGTH = 0x38000 - * + * START = 0x00980000 + * LENGTH = 0x00038000 */ - if (HIFDiagReadMem(scn->hif_hdl, - host_interest_item_address(scn->target_type, - offsetof(struct host_interest_s, hi_failure_state)), - (A_UCHAR*) ®_dump_area, sizeof(u_int32_t)) != A_OK) { - printk("HifDiagReadiMem FW Dump Area Pointer failed!\n"); - return; - } - printk("Host interest item address: 0x%08X\n", reg_dump_area); - - while ((sectionCount < 3) && (amountRead < blockLength)) { + while ((sectionCount < 2) && (amountRead < blockLength)) { switch (sectionCount) { case 0: - /* REGISTER SECTION */ - pos = reg_dump_area; - readLen = REGISTER_SIZE; - break; - case 1: /* DRAM SECTION */ pos = DRAM_LOCATION; readLen = DRAM_SIZE; break; - case 2: + case 1: /* IRAM SECTION */ pos = IRAM_LOCATION; readLen = IRAM_SIZE; @@ -1044,18 +1021,20 @@ u_int8_t ol_get_number_of_peers_supported(struct ol_softc *scn) u_int8_t max_no_of_peers = 0; switch (scn->target_version) { - case AR6320_REV1_3_VERSION: - if(scn->max_no_of_peers > MAX_SUPPORTED_PEERS_REV1_3) - max_no_of_peers = MAX_SUPPORTED_PEERS_REV1_3; + case AR6320_REV1_1_VERSION: + if(scn->max_no_of_peers > MAX_SUPPORTED_PEERS_REV1_1) + max_no_of_peers = MAX_SUPPORTED_PEERS_REV1_1; else max_no_of_peers = scn->max_no_of_peers; break; + default: - if(scn->max_no_of_peers > MAX_SUPPORTED_PEERS_REV1_1) - max_no_of_peers = MAX_SUPPORTED_PEERS_REV1_1; + if(scn->max_no_of_peers > MAX_SUPPORTED_PEERS_REV1_3) + max_no_of_peers = MAX_SUPPORTED_PEERS_REV1_3; else max_no_of_peers = scn->max_no_of_peers; break; + } return max_no_of_peers; } diff --git a/CORE/SERVICES/BMI/ol_fw.h b/CORE/SERVICES/BMI/ol_fw.h index 6a61db8634ac..8d25b9704596 100644 --- a/CORE/SERVICES/BMI/ol_fw.h +++ b/CORE/SERVICES/BMI/ol_fw.h @@ -24,21 +24,7 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ + #ifndef _OL_FW_H_ #define _OL_FW_H_ @@ -64,17 +50,17 @@ #define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 #if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC) -#define REGISTER_LOCATION 0x4000 -#define REGISTER_SIZE 0x6c000 +#define REGISTER_LOCATION 0x00000000 +#define REGISTER_SIZE 0x00000800 -#define DRAM_LOCATION 0x400000 -#define DRAM_SIZE 0x50000 +#define DRAM_LOCATION 0x00400000 +#define DRAM_SIZE 0x00070000 -#define IRAM_LOCATION 0x980000 -#define IRAM_SIZE 0x38000 +#define IRAM_LOCATION 0x00980000 +#define IRAM_SIZE 0x00038000 #define TOTAL_DUMP_SIZE REGISTER_SIZE + DRAM_SIZE + IRAM_SIZE -#define PCIE_READ_LIMIT 0x5000 +#define PCIE_READ_LIMIT 0x00005000 void ol_target_coredump(void *instance, void* memoryBlock, u_int32_t blockLength); diff --git a/CORE/SERVICES/COMMON/_ieee80211_common.h b/CORE/SERVICES/COMMON/_ieee80211_common.h index 3476ff53959a..df7ba5aecac4 100644 --- a/CORE/SERVICES/COMMON/_ieee80211_common.h +++ b/CORE/SERVICES/COMMON/_ieee80211_common.h @@ -194,7 +194,7 @@ enum ieee80211_scanmode { #define IEEE80211_CHAN_PASSIVE 0x00000200 /* Only passive scan allowed */ #define IEEE80211_CHAN_DYN 0x00000400 /* Dynamic CCK-OFDM channel */ #define IEEE80211_CHAN_GFSK 0x00000800 /* GFSK channel (FHSS PHY) */ -#define IEEE80211_CHAN_RADAR 0x00001000 /* Radar found on channel */ +#define IEEE80211_CHAN_RADAR_DFS 0x00001000 /* Radar found on channel */ #define IEEE80211_CHAN_STURBO 0x00002000 /* 11a static turbo channel only */ #define IEEE80211_CHAN_HALF 0x00004000 /* Half rate channel */ #define IEEE80211_CHAN_QUARTER 0x00008000 /* Quarter rate channel */ @@ -411,11 +411,11 @@ enum ieee80211_scanmode { (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == IEEE80211_CHAN_11AC_VHT80) #define IEEE80211_IS_CHAN_RADAR(_c) \ - (((_c)->ic_flags & IEEE80211_CHAN_RADAR) == IEEE80211_CHAN_RADAR) + (((_c)->ic_flags & IEEE80211_CHAN_RADAR_DFS) == IEEE80211_CHAN_RADAR_DFS) #define IEEE80211_CHAN_SET_RADAR(_c) \ - ((_c)->ic_flags |= IEEE80211_CHAN_RADAR) + ((_c)->ic_flags |= IEEE80211_CHAN_RADAR_DFS) #define IEEE80211_CHAN_CLR_RADAR(_c) \ - ((_c)->ic_flags &= ~IEEE80211_CHAN_RADAR) + ((_c)->ic_flags &= ~IEEE80211_CHAN_RADAR_DFS) #define IEEE80211_CHAN_SET_DISALLOW_ADHOC(_c) \ ((_c)->ic_flagext |= IEEE80211_CHAN_DISALLOW_ADHOC) #define IEEE80211_CHAN_SET_DISALLOW_HOSTAP(_c) \ diff --git a/CORE/SERVICES/COMMON/a_osapi.h b/CORE/SERVICES/COMMON/a_osapi.h index a345780b6bdc..7524243faad7 100644 --- a/CORE/SERVICES/COMMON/a_osapi.h +++ b/CORE/SERVICES/COMMON/a_osapi.h @@ -24,16 +24,7 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc.. - * All Rights Reserved. - * Qualcomm Atheros Confidential and Proprietary. - */ - //------------------------------------------------------------------------------ -// <copyright file="a_osapi.h" company="Atheros"> -// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ + //============================================================================== // This file contains the definitions of the basic atheros data types. // It is used to map the data types in atheros files to a platform specific diff --git a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h index 3998c534d839..d209ded62380 100644 --- a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h +++ b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h @@ -104,16 +104,9 @@ struct cvg_nbuf_cb { } extra_frags; uint32_t owner_id; __adf_nbuf_callback_fn adf_nbuf_callback_fn; -#ifdef IPA_OFFLOAD - unsigned long priv_data; -#endif }; #define NBUF_OWNER_ID(skb) \ (((struct cvg_nbuf_cb *)((skb)->cb))->owner_id) -#ifdef IPA_OFFLOAD -#define NBUF_OWNER_PRIV_DATA(skb) \ - (((struct cvg_nbuf_cb *)((skb)->cb))->priv_data) -#endif #define NBUF_CALLBACK_FN(skb) \ (((struct cvg_nbuf_cb *)((skb)->cb))->adf_nbuf_callback_fn) #define NBUF_CALLBACK_FN_EXEC(skb) \ diff --git a/CORE/SERVICES/COMMON/bmi_msg.h b/CORE/SERVICES/COMMON/bmi_msg.h index 169d21c43c46..0d125418bcb8 100644 --- a/CORE/SERVICES/COMMON/bmi_msg.h +++ b/CORE/SERVICES/COMMON/bmi_msg.h @@ -24,13 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -//------------------------------------------------------------------------------ -// Copyright (c) 2004-2012 Atheros Corporation. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ -//============================================================================== -// Author(s): ="Atheros" -//============================================================================== #ifndef __BMI_MSG_H__ #define __BMI_MSG_H__ @@ -256,6 +249,7 @@ PREPACK struct bmi_target_info { #define TARGET_TYPE_AR9888 7 #define TARGET_TYPE_AR6320 8 #define TARGET_TYPE_AR900B 9 +#define TARGET_TYPE_AR6320V2 10 /* For attach Peregrine 2.0 board target_reg_tbl only */ #define TARGET_TYPE_AR9888V2 10 diff --git a/CORE/SERVICES/COMMON/dbglog_id.h b/CORE/SERVICES/COMMON/dbglog_id.h index e3280e0baeb1..0cbfe9baf8b8 100644 --- a/CORE/SERVICES/COMMON/dbglog_id.h +++ b/CORE/SERVICES/COMMON/dbglog_id.h @@ -24,19 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2004-2010, 2013 Qualcomm Atheros, Inc.. - * All Rights Reserved. - * Qualcomm Atheros Confidential and Proprietary. - */ -//------------------------------------------------------------------------------ -// <copyright file="dbglog_id.h" company="Atheros"> -// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ -//============================================================================== -// Author(s): ="Atheros" -//============================================================================== #ifndef _DBGLOG_ID_H_ #define _DBGLOG_ID_H_ @@ -217,7 +204,8 @@ extern "C" { #define RESMGR_DYN_SCH_HOME_CH_QUOTA 57 #define RESMGR_OCS_REG_RECAL_QUOTA_NOTIF 58 #define RESMGR_OCS_DEREG_RECAL_QUOTA_NOTIF 59 -#define RESMGR_DEFINITION_END 60 +#define RESMGR_DYN_SCH_CH_STATS_END 60 +#define RESMGR_DEFINITION_END 61 /* RESMGR CHNMGR debug ids */ #define RESMGR_CHMGR_DEFINITION_START 0 @@ -250,7 +238,8 @@ extern "C" { #define VDEV_MGR_VDEV_PAUSE_DELAY_UPDATE 16 #define VDEV_MGR_VDEV_PAUSE_FAIL 17 #define VDEV_MGR_GEN_PERIODIC_NOA 18 -#define VDEV_MGR_DEFINITION_END 19 +#define VDEV_MGR_OFF_CHAN_GO_CH_REQ_SETUP 19 +#define VDEV_MGR_DEFINITION_END 20 /* WHAL debug identifier definitions */ #define WHAL_DBGID_DEFINITION_START 0 @@ -539,7 +528,24 @@ extern "C" { #define COEX_MWS_ERROR 236 #define COEX_MWS_ANT_DIVERSITY 237 -#define COEX_DEBUG_ID_END 238 +#define COEX_P2P_GO 238 +#define COEX_P2P_CLIENT 239 +#define COEX_SCC_1 240 +#define COEX_SCC_2 241 +#define COEX_MCC_1 242 +#define COEX_MCC_2 243 +#define COEX_TRF_SHAPE_NOA 244 +#define COEX_NOA_ONESHOT 245 +#define COEX_NOA_PERIODIC 246 +#define COEX_LE_1 247 +#define COEX_LE_2 248 +#define COEX_ANT_1 249 +#define COEX_ANT_2 250 +#define COEX_ENTER_NOA 251 +#define COEX_EXIT_NOA 252 +#define COEX_BT_SCAN_PROTECT 253 + +#define COEX_DEBUG_ID_END 254 #define SCAN_START_COMMAND_FAILED 0 #define SCAN_STOP_COMMAND_FAILED 1 @@ -684,7 +690,10 @@ extern "C" { #define OFFLOADMGR_NO_REG_DATA_HANDLERS 3 #define OFFLOADMGR_NO_REG_EVENT_HANDLERS 4 #define OFFLOADMGR_REG_OFFLOAD_FAILED 5 -#define OFFLOADMGR_DBGID_DEFINITION_END 6 +#define OFFLOADMGR_DEREG_OFFLOAD_FAILED 6 +#define OFFLOADMGR_ENTER_FAILED 7 +#define OFFLOADMGR_EXIT_FAILED 8 +#define OFFLOADMGR_DBGID_DEFINITION_END 9 /*Resource Debug IDs*/ #define RESOURCE_DBGID_DEFINITION_START 0 @@ -739,7 +748,8 @@ extern "C" { #define P2P_GO_GET_NOA_INFO 35 #define P2P_GO_ADD_ONE_SHOT_NOA 36 #define P2P_GO_GET_NOA_IE 37 -#define P2P_DBGID_DEFINITION_END 38 +#define P2P_GO_BCN_TX_COMP 38 +#define P2P_DBGID_DEFINITION_END 39 //CSA modules DBGIDs @@ -772,7 +782,9 @@ extern "C" { #define WLAN_CHATTER_MC_FILTER_DEL 10 #define WLAN_CHATTER_MC_FILTER_ALLOW 11 #define WLAN_CHATTER_MC_FILTER_DROP 12 -#define WLAN_CHATTER_DBGID_DEFINITION_END 13 +#define WLAN_CHATTER_COALESCING_FILTER_ADD 13 +#define WLAN_CHATTER_COALESCING_FILTER_DEL 14 +#define WLAN_CHATTER_DBGID_DEFINITION_END 15 #define WOW_DBGID_DEFINITION_START 0 #define WOW_ENABLE_CMDID 1 @@ -925,10 +937,37 @@ extern "C" { #define WLAN_HB_DBGID_TCP_TX 14 #define WLAN_HB_DBGID_DEFINITION_END 15 -/* Thermal Manager DBGIDs */ +/* Thermal Manager DBGIDs*/ #define THERMAL_MGR_NEW_THRESH 0 #define THERMAL_MGR_THRESH_CROSSED 1 +/* WLAN PHYERR DFS(parse/filter) DBGIDs */ +#define WLAN_PHYERR_DFS_DBGID_DEFINITION_START 0 +#define WLAN_PHYERR_DFS_PHYERR_INFO_CHAN_BUFLEN 1 +#define WLAN_PHYERR_DFS_PHYERR_INFO_PPDU 2 +#define WLAN_PHYERR_DFS_DBDID_RADAR_SUMMARY 3 +#define WLAN_PHYERR_DFS_DBDID_SEARCH_FFT 4 +#define WLAN_PHTERR_DFS_DBDID_FILTER_STATUS 5 + +/* RMC DBGIDs */ +#define RMC_DBGID_DEFINITION_START 0 +#define RMC_SM_INIT_ERR 1 +#define RMC_VDEV_ALLOC_ERR 2 +#define RMC_CREATE_INSTANCE 3 +#define RMC_DELETE_INSTANCE 4 +#define RMC_NEW_PRI_LEADER 5 +#define RMC_NEW_SEC_LEADER 6 +#define RMC_NO_LDR_CHANGE 7 +#define RMC_LDR_INFORM_SENT 8 +#define RMC_PEER_ADD 9 +#define RMC_PEER_DELETE 10 +#define RMC_PEER_UNKNOWN 11 +#define RMC_PRI_LDR_RSSI_UPDATE 12 +#define RMC_SEC_LDR_RSSI_UPDATE 13 +#define RMC_SET_MODE 14 +#define RMC_SET_ACTION_PERIOD 15 +#define RMC_DBGID_DEFINITION_END 16 + #ifdef __cplusplus } #endif diff --git a/CORE/SERVICES/COMMON/hif.h b/CORE/SERVICES/COMMON/hif.h index 4de405463595..4a6142bb5073 100644 --- a/CORE/SERVICES/COMMON/hif.h +++ b/CORE/SERVICES/COMMON/hif.h @@ -24,11 +24,7 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -//------------------------------------------------------------------------------ -// <copyright file="hif.h" company="Atheros"> -// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ + //============================================================================== // HIF specific declarations and prototypes // @@ -59,6 +55,7 @@ typedef void __iomem *A_target_id_t; #define HIF_TYPE_AR6004 5 #define HIF_TYPE_AR9888 6 #define HIF_TYPE_AR6320 7 +#define HIF_TYPE_AR6320V2 8 /* For attaching Peregrine 2.0 board host_reg_tbl only */ #define HIF_TYPE_AR9888V2 8 @@ -645,6 +642,8 @@ extern void HIFTargetSleepStateAdjust(A_target_id_t targid, A_BOOL sleep_ok, A_B extern void HIFSetTargetSleep(HIF_DEVICE *hif_device, A_BOOL sleep_ok, A_BOOL wait_for_it); extern A_BOOL HIFTargetForcedAwake(A_target_id_t targid); +extern void +HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device); #define A_TARGET_ID(hifDevice) HIFGetTargetId(hifDevice) diff --git a/CORE/SERVICES/COMMON/htc_api.h b/CORE/SERVICES/COMMON/htc_api.h index 1770f6c06b0d..d3f4b79bd8b3 100644 --- a/CORE/SERVICES/COMMON/htc_api.h +++ b/CORE/SERVICES/COMMON/htc_api.h @@ -685,4 +685,5 @@ struct s_htc_msg{ void *htc_get_targetdef(HTC_HANDLE htc_handle); void HTCSetTargetToSleep(void *context); +void HTCCancelDeferredTargetSleep(void *context); #endif /* _HTC_API_H_ */ diff --git a/CORE/SERVICES/COMMON/ieee80211_common.h b/CORE/SERVICES/COMMON/ieee80211_common.h index c8c6c244461e..8927feb11753 100644 --- a/CORE/SERVICES/COMMON/ieee80211_common.h +++ b/CORE/SERVICES/COMMON/ieee80211_common.h @@ -1862,6 +1862,9 @@ enum { #define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */ #define IEEE80211_WEP_MICLEN 8 /* trailing MIC */ +#define IEEE80211_CCMP_HEADERLEN 8 +#define IEEE80211_CCMP_MICLEN 8 + #define IEEE80211_CRC_LEN 4 #define IEEE80211_8021Q_HEADER_LEN 4 diff --git a/CORE/SERVICES/COMMON/ol_if_athvar.h b/CORE/SERVICES/COMMON/ol_if_athvar.h index ab76392231c8..55ad6e469135 100644 --- a/CORE/SERVICES/COMMON/ol_if_athvar.h +++ b/CORE/SERVICES/COMMON/ol_if_athvar.h @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2010-2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ /* * Defintions for the Atheros Wireless LAN controller driver. diff --git a/CORE/SERVICES/COMMON/pktlog.h b/CORE/SERVICES/COMMON/pktlog.h index fdd1fe68416c..f4dd030bca56 100644 --- a/CORE/SERVICES/COMMON/pktlog.h +++ b/CORE/SERVICES/COMMON/pktlog.h @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2012-2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ #ifndef _PKTLOG_ #define _PKTLOG_ diff --git a/CORE/SERVICES/COMMON/targaddrs.h b/CORE/SERVICES/COMMON/targaddrs.h index a91787530b6a..4c2b032c3cab 100644 --- a/CORE/SERVICES/COMMON/targaddrs.h +++ b/CORE/SERVICES/COMMON/targaddrs.h @@ -24,14 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -//------------------------------------------------------------------------------ -// <copyright file="targaddrs.h" company="Atheros"> -// Copyright (c) 2010 Atheros Corporation. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ -//============================================================================== -// Author(s): ="Atheros" -//============================================================================== #ifndef __TARGADDRS_H__ #define __TARGADDRS_H__ @@ -608,8 +600,9 @@ PREPACK64 struct host_interest_s { (((TargetType) == TARGET_TYPE_AR6006) ? AR6006_HOST_INTEREST_ITEM_ADDRESS(item) : \ (((TargetType) == TARGET_TYPE_AR9888) ? AR9888_HOST_INTEREST_ITEM_ADDRESS(item) : \ (((TargetType) == TARGET_TYPE_AR6320) ? AR6320_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR6320V2) ? AR6320_HOST_INTEREST_ITEM_ADDRESS(item) : \ (((TargetType) == TARGET_TYPE_AR900B) ? AR900B_HOST_INTEREST_ITEM_ADDRESS(item) : \ - 0))))))) + 0)))))))) #define AR6002_BOARD_DATA_SZ 768 #define AR6002_BOARD_EXT_DATA_SZ 0 diff --git a/CORE/SERVICES/COMMON/targcfg.h b/CORE/SERVICES/COMMON/targcfg.h index 7b51511d4774..5d930c99a880 100644 --- a/CORE/SERVICES/COMMON/targcfg.h +++ b/CORE/SERVICES/COMMON/targcfg.h @@ -24,14 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -//------------------------------------------------------------------------------ -// <copyright file="wmi_unified.h" company="Atheros"> -// Copyright (c) 2004-2010 Qualcomm Atheros Inc. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ -//============================================================================== -// Author(s): ="Atheros" -//============================================================================== #ifndef __TARGCFG_H__ #define __TARGCFG_H__ diff --git a/CORE/SERVICES/COMMON/wdi_event.h b/CORE/SERVICES/COMMON/wdi_event.h index 690bbe4417c6..b1d0d600e3f0 100644 --- a/CORE/SERVICES/COMMON/wdi_event.h +++ b/CORE/SERVICES/COMMON/wdi_event.h @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2012-2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ #ifndef _WDI_EVENT_H_ #define _WDI_EVENT_H_ diff --git a/CORE/SERVICES/COMMON/wlan_module_ids.h b/CORE/SERVICES/COMMON/wlan_module_ids.h index f4973fb0aa15..ee1b102a2c96 100644 --- a/CORE/SERVICES/COMMON/wlan_module_ids.h +++ b/CORE/SERVICES/COMMON/wlan_module_ids.h @@ -78,6 +78,8 @@ typedef enum { WLAN_MODULE_TXBF, WLAN_MODULE_BATCH_SCAN, WLAN_MODULE_THERMAL_MGR, + WLAN_MODULE_PHYERR_DFS, + WLAN_MODULE_RMC, WLAN_MODULE_ID_MAX, WLAN_MODULE_ID_INVALID = WLAN_MODULE_ID_MAX, } WLAN_MODULE_ID; diff --git a/CORE/SERVICES/COMMON/wma_api.h b/CORE/SERVICES/COMMON/wma_api.h index 9675af9adfe6..e6b12588e10c 100644 --- a/CORE/SERVICES/COMMON/wma_api.h +++ b/CORE/SERVICES/COMMON/wma_api.h @@ -81,6 +81,7 @@ typedef enum { #define GEN_CMD 3 #define DBG_CMD 4 #define PPS_CMD 5 +#define QPOWER_CMD 6 #ifdef QCA_WIFI_ISOC VOS_STATUS wma_nv_download_start(v_VOID_t *vos_context); @@ -115,6 +116,8 @@ eHalStatus wma_set_htconfig(tANI_U8 vdev_id, tANI_U16 ht_capab, int value); eHalStatus WMA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, tAniBool sendRegHint); +VOS_STATUS WMA_GetWcnssSoftwareVersion(v_PVOID_t pvosGCtx, tANI_U8 *pVersion, + tANI_U32 versionBufferSize); #ifndef QCA_WIFI_ISOC int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); void wma_target_suspend_complete(void *context); diff --git a/CORE/SERVICES/COMMON/wma_dfs_interface.h b/CORE/SERVICES/COMMON/wma_dfs_interface.h new file mode 100644 index 000000000000..6d3d6da91839 --- /dev/null +++ b/CORE/SERVICES/COMMON/wma_dfs_interface.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "ath_dfs_structs.h" +#include "_ieee80211_common.h" + +#define IEEE80211_CHAN_MAX 255 + +/* channel attributes */ + +/* Turbo channel */ +#define IEEE80211_CHAN_TURBO 0x00000010 +/* CCK channel */ +#define IEEE80211_CHAN_CCK 0x00000020 +/* OFDM channel */ +#define IEEE80211_CHAN_OFDM 0x00000040 +/* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_2GHZ 0x00000080 +/* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_5GHZ 0x00000100 +/* Only passive scan allowed */ +#define IEEE80211_CHAN_PASSIVE 0x00000200 +/* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_DYN 0x00000400 +/* GFSK channel (FHSS PHY) */ +#define IEEE80211_CHAN_GFSK 0x00000800 +/* Radar found on channel */ +#define IEEE80211_CHAN_RADAR 0x00001000 +/* 11a static turbo channel only */ +#define IEEE80211_CHAN_STURBO 0x00002000 +/* Half rate channel */ +#define IEEE80211_CHAN_HALF 0x00004000 +/* Quarter rate channel */ +#define IEEE80211_CHAN_QUARTER 0x00008000 +/* HT 20 channel */ +#define IEEE80211_CHAN_HT20 0x00010000 +/* HT 40 with extension channel above */ +#define IEEE80211_CHAN_HT40PLUS 0x00020000 +/* HT 40 with extension channel below */ +#define IEEE80211_CHAN_HT40MINUS 0x00040000 +/* HT 40 Intolerant */ +#define IEEE80211_CHAN_HT40INTOL 0x00080000 +/* VHT 20 channel */ +#define IEEE80211_CHAN_VHT20 0x00100000 +/* VHT 40 with extension channel above */ +#define IEEE80211_CHAN_VHT40PLUS 0x00200000 +/* VHT 40 with extension channel below */ +#define IEEE80211_CHAN_VHT40MINUS 0x00400000 +/* VHT 80 channel */ +#define IEEE80211_CHAN_VHT80 0x00800000 + +/* token for ``any channel'' */ +#define IEEE80211_CHAN_ANY (-1) +#define IEEE80211_CHAN_ANYC \ + ((struct ieee80211_channel *) IEEE80211_CHAN_ANY) + + +#define IEEE80211_IS_CHAN_11N_HT40MINUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) != 0) +#define IEEE80211_IS_CHAN_11N_HT40PLUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) != 0) +#define IEEE80211_CHAN_11AC_VHT80 \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT80) + + +#define IEEE80211_IS_CHAN_11AC_VHT80(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == \ + IEEE80211_CHAN_11AC_VHT80) +#define CHANNEL_108G \ + (IEEE80211_CHAN_2GHZ|IEEE80211_CHAN_OFDM|IEEE80211_CHAN_TURBO) + +/* + * Software use: channel interference + * used for as AR as well as RADAR + * interference detection +*/ +#define CHANNEL_INTERFERENCE 0x01 +/* In case of VHT160, we can have 8 20Mhz channels */ +#define IEE80211_MAX_20M_SUB_CH 8 + +struct ieee80211_channel +{ + u_int32_t ic_freq; /* setting in Mhz */ + u_int32_t ic_flags; /* see below */ + u_int8_t ic_flagext; /* see below */ + u_int8_t ic_ieee; /* IEEE channel number */ + + /* maximum regulatory tx power in dBm */ + int8_t ic_maxregpower; + + int8_t ic_maxpower; /* maximum tx power in dBm */ + int8_t ic_minpower; /* minimum tx power in dBm */ + u_int8_t ic_regClassId; /* regClassId of this channel */ + u_int8_t ic_antennamax; /* antenna gain max from regulatory */ + u_int32_t ic_vhtop_ch_freq_seg1; /* Channel Center frequency */ + + /* Channel Center frequency applicable*/ + u_int32_t ic_vhtop_ch_freq_seg2; +}; + +struct ieee80211_channel_list +{ + int cl_nchans; + struct ieee80211_channel *cl_channels[IEE80211_MAX_20M_SUB_CH]; +}; + +struct ieee80211_dfs_state +{ + int nol_event[IEEE80211_CHAN_MAX]; + os_timer_t nol_timer; /* NOL list processing */ + os_timer_t cac_timer; /* CAC timer */ + int cureps; /* current events/second */ + const struct ieee80211_channel *lastchan; /* chan w/ last radar event */ + struct ieee80211_channel *newchan; /* chan selected next */ + /* overridden cac timeout */ + int cac_timeout_override; + int8_t enable:1, + cac_timer_running:1, + ignore_dfs:1, + ignore_cac:1; +}; + +typedef struct ieee80211com +{ + void (*ic_start_csa)(struct ieee80211com *ic,u_int8_t ieeeChan); + void (*ic_get_ext_chan_info)(struct ieee80211com *ic, + struct ieee80211_channel_list *chan); + enum ieee80211_opmode ic_opmode; /* operation mode */ + struct ieee80211_channel *(*ic_find_channel)(struct ieee80211com *ic, + int freq, u_int32_t flags); + u_int64_t (*ic_get_TSF64)(struct ieee80211com *ic); + unsigned int (*ic_ieee2mhz)(u_int chan, u_int flags); + struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1]; + /* Number of Channels according to the Regulatory domain channels */ + int ic_nchans; + struct ieee80211_channel *ic_curchan; /* current channel */ + u_int8_t ic_isdfsregdomain; /* operating in DFS domain ? */ + int (*ic_get_dfsdomain)(struct ieee80211com *); + u_int16_t (*ic_dfs_usenol)(struct ieee80211com *ic); + u_int16_t (*ic_dfs_isdfsregdomain)(struct ieee80211com *ic); + int (*ic_dfs_attached)(struct ieee80211com *ic); + void *ic_dfs; + struct ieee80211_dfs_state ic_dfs_state; + int (*ic_dfs_attach)(struct ieee80211com *ic, + void *pCap, void *radar_info); + int (*ic_dfs_detach)(struct ieee80211com *ic); + int (*ic_dfs_enable)(struct ieee80211com *ic, int *is_fastclk, void *); + int (*ic_dfs_disable)(struct ieee80211com *ic); + int (*ic_get_ext_busy)(struct ieee80211com *ic); + int (*ic_get_mib_cycle_counts_pct)(struct ieee80211com *ic, + u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt); + int (*ic_dfs_get_thresholds)(struct ieee80211com *ic,void *pe); + + int (*ic_dfs_debug)(struct ieee80211com *ic, int type, void *data); + /* + * Update the channel list with the current set of DFS + * NOL entries. + * + * + 'cmd' indicates what to do; for now it should just + * be DFS_NOL_CLIST_CMD_UPDATE which will update all + * channels, given the _entire_ NOL. (Rather than + * the earlier behaviour with clist_update, which + * was to either add or remove a set of channel + * entries.) + */ + void (*ic_dfs_clist_update)(struct ieee80211com *ic, int cmd, + struct dfs_nol_chan_entry *, int nentries); + void (*ic_dfs_notify_radar)(struct ieee80211com *ic, + struct ieee80211_channel *chan); + void (*ic_dfs_unmark_radar)(struct ieee80211com *ic, + struct ieee80211_channel *chan); + int (*ic_dfs_control)(struct ieee80211com *ic, + u_int id, void *indata, u_int32_t insize, + void *outdata, u_int32_t *outsize); + HAL_DFS_DOMAIN current_dfs_regdomain; + u_int8_t vdev_id; + u_int8_t last_radar_found_chan; +} IEEE80211COM, *PIEEE80211COM; + +/* + * Convert channel to frequency value. + */ +static INLINE u_int +ieee80211_chan2freq(struct ieee80211com *ic, + const struct ieee80211_channel *c) +{ + if (c == NULL) + { + return 0; + } + return (c == IEEE80211_CHAN_ANYC ? IEEE80211_CHAN_ANY : c->ic_freq); +} diff --git a/CORE/SERVICES/COMMON/wmi_unified.h b/CORE/SERVICES/COMMON/wmi_unified.h index 27f578c36dfc..594d6679dabe 100644 --- a/CORE/SERVICES/COMMON/wmi_unified.h +++ b/CORE/SERVICES/COMMON/wmi_unified.h @@ -331,7 +331,10 @@ typedef enum { WMI_PDEV_DFS_ENABLE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_DFS), /** disable DFS (radar detection)*/ WMI_PDEV_DFS_DISABLE_CMDID, - + /** enable DFS phyerr/parse filter offload */ + WMI_DFS_PHYERR_FILTER_ENA_CMDID, + /** enable DFS phyerr/parse filter offload */ + WMI_DFS_PHYERR_FILTER_DIS_CMDID, /* Roaming specific commands */ /** set roam scan mode */ @@ -572,10 +575,6 @@ typedef enum { /** Plumb routing table for multihop forwarding offload */ WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID, - /** enable DFS phyerr/parse filter offload */ - WMI_DFS_PHYERR_FILTER_ENA_CMDID, - /** enable DFS phyerr/parse filter offload */ - WMI_DFS_PHYERR_FILTER_DIS_CMDID, /*location scan commands*/ /*start batch scan*/ WMI_BATCH_SCAN_ENABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_LOCATION_SCAN), @@ -611,6 +610,9 @@ typedef enum { /** traffic pause event */ WMI_TX_PAUSE_EVENTID, + /** DFS radar event */ + WMI_DFS_RADAR_EVENTID, + /* VDEV specific events */ /** VDEV started event in response to VDEV_START request */ WMI_VDEV_START_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_VDEV), @@ -757,9 +759,6 @@ typedef enum { /* TDLS Event */ WMI_TDLS_PEER_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_TDLS), - /** DFS radar event */ - WMI_DFS_RADAR_EVENTID, - /*location scan event*/ /*report the firmware's capability of batch scan*/ WMI_BATCH_SCAN_ENABLED_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_LOCATION_SCAN), @@ -916,7 +915,7 @@ WMI_CHANNEL_CHANGE_CAUSE_CSA, #define WMI_VHT_CAP_SU_BFORMER 0x00000800 #define WMI_VHT_CAP_SU_BFORMEE 0x00001000 #define WMI_VHT_CAP_MU_BFORMER 0x00080000 -#define WMI_VHT_CAP MU_BFORMEE 0x00100000 +#define WMI_VHT_CAP_MU_BFORMEE 0x00100000 /* These macros should be used when we wish to advertise STBC support for * only 1SS or 2SS or 3SS. */ @@ -959,6 +958,13 @@ typedef struct _wmi_abi_version { * maximum number of memroy requests allowed from FW. */ #define WMI_MAX_MEM_REQS 16 + +/* !!NOTE!!: + * This HW_BD_INFO_SIZE cannot be changed without breaking compatibility. + * Please don't change it. + */ +#define HW_BD_INFO_SIZE 5 + /** * The following struct holds optional payload for * wmi_service_ready_event_fixed_param,e.g., 11ac pass some of the @@ -995,6 +1001,13 @@ typedef struct { * setup. */ A_UINT32 max_num_scan_channels; + + /* Hardware board specific ID. Values defined in enum WMI_HWBOARD_ID. + * Default 0 means tha hw_bd_info[] is invalid(legacy board). + */ + A_UINT32 hw_bd_id; + A_UINT32 hw_bd_info[HW_BD_INFO_SIZE]; /* Board specific information. Invalid if hw_hd_id is zero. */ + /* The TLVs for hal_reg_capabilities, wmi_service_bitmap and mem_reqs[] will follow this TLV. * HAL_REG_CAPABILITIES hal_reg_capabilities; * A_UINT32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; @@ -1002,6 +1015,48 @@ typedef struct { */ } wmi_service_ready_event_fixed_param; +typedef enum { + WMI_HWBD_NONE = 0, /* No hw board information is given */ + WMI_HWBD_QCA6174 = 1, /* Rome(AR6320) */ + WMI_HWBD_QCA2582 = 2, /* Killer 1525*/ +} WMI_HWBD_ID; + +#define ATH_BD_DATA_REV_MASK 0x000000FF +#define ATH_BD_DATA_REV_SHIFT 0 + +#define ATH_BD_DATA_PROJ_ID_MASK 0x0000FF00 +#define ATH_BD_DATA_PROJ_ID_SHIFT 8 + +#define ATH_BD_DATA_CUST_ID_MASK 0x00FF0000 +#define ATH_BD_DATA_CUST_ID_SHIFT 16 + +#define ATH_BD_DATA_REF_DESIGN_ID_MASK 0xFF000000 +#define ATH_BD_DATA_REF_DESIGN_ID_SHIFT 24 + +#define SET_BD_DATA_REV(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_REV_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_REV_SHIFT)) + +#define GET_BD_DATA_REV(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_REV_MASK) >> ATH_BD_DATA_REV_SHIFT) + +#define SET_BD_DATA_PROJ_ID(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_PROJ_ID_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_PROJ_ID_SHIFT)) + +#define GET_BD_DATA_PROJ_ID(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_PROJ_ID_MASK) >> ATH_BD_DATA_PROJ_ID_SHIFT) + +#define SET_BD_DATA_CUST_ID(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_CUST_ID_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_CUST_ID_SHIFT)) + +#define GET_BD_DATA_CUST_ID(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_CUST_ID_MASK) >> ATH_BD_DATA_CUST_ID_SHIFT) + +#define SET_BD_DATA_REF_DESIGN_ID(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_REF_DESIGN_ID_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_REF_DESIGN_ID_SHIFT)) + +#define GET_BD_DATA_REF_DESIGN_ID(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_REF_DESIGN_ID_MASK) >> ATH_BD_DATA_REF_DESIGN_ID_SHIFT) + #ifdef ROME_LTE_COEX_FREQ_AVOID typedef struct { A_UINT32 start_freq; //start frequency, not channel center freq @@ -3205,6 +3260,17 @@ typedef struct { * Number of TX frames before the entering the Active state */ WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE = 7, + + /** + * QPower SPEC PSPOLL interval + */ + WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL = 8, + + /** + * Max SPEC PSPOLL to be sent when the PSPOLL response has + * no-data bit set + */ + WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL = 9, }; typedef struct { @@ -3782,6 +3848,7 @@ typedef struct { #define WMI_PEER_PMF 0x08000000 /* Robust Management Frame Protection enabled */ /** CAUTION TODO: Place holder for WLAN_PEER_F_PS_PRESEND_REQUIRED = 0x10000000. Need to be clean up */ #define WMI_PEER_IS_P2P_CAPABLE 0x20000000 /* P2P capable peer */ +#define WMI_PEER_SAFEMODE_EN 0x80000000 /* Fips Mode Enabled */ /** * Peer rate capabilities. @@ -5410,7 +5477,9 @@ typedef struct { A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_gtk_rekey_fail_event_fixed_param */ /** Reserved for future use */ A_UINT32 reserved0; + A_UINT32 vdev_id; } wmi_gtk_rekey_fail_event_fixed_param; + enum wmm_ac_downgrade_policy { WMM_AC_DOWNGRADE_DEPRIO, WMM_AC_DOWNGRADE_DROP, @@ -5685,7 +5754,6 @@ typedef struct { typedef struct { /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param */ A_UINT32 tlv_header; - A_UINT32 reserved0; /** 1: enable fw based adaptive ocs, * 0: disable fw based adaptive ocs */ diff --git a/CORE/SERVICES/COMMON/wmi_version.h b/CORE/SERVICES/COMMON/wmi_version.h index 628dee99277a..04d63e61281d 100644 --- a/CORE/SERVICES/COMMON/wmi_version.h +++ b/CORE/SERVICES/COMMON/wmi_version.h @@ -35,7 +35,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 30 +#define __WMI_REVISION_ 31 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work diff --git a/CORE/SERVICES/DFS/inc/ath_dfs_structs.h b/CORE/SERVICES/DFS/inc/ath_dfs_structs.h new file mode 100644 index 000000000000..d85ba50fcd54 --- /dev/null +++ b/CORE/SERVICES/DFS/inc/ath_dfs_structs.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + ath_dfs_structs.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + + +#ifndef _DFS__STRUCTS_H_ +#define _DFS__STRUCTS_H_ +#include <adf_os_mem.h> + +#ifdef ANDROID +#include <linux/string.h> +#endif + +/* + * For the dfs_nol_clist_update() method - this is the + * update command. + */ +enum { + DFS_NOL_CLIST_CMD_NONE = 0x0, + DFS_NOL_CLIST_CMD_UPDATE = 0x1, +}; + +struct ath_dfs_caps { + u_int32_t + ath_dfs_ext_chan_ok:1, /* Can radar be detected on the extension chan? */ + ath_dfs_combined_rssi_ok:1, /* Can use combined radar RSSI? */ + /* the following flag is used to indicate if radar detection scheme */ + /* should use enhanced chirping detection algorithm. This flag also */ + /* determines if certain radar data should be discarded to minimize */ + /* false detection of radar. */ + ath_dfs_use_enhancement:1, + ath_strong_signal_diversiry:1, + ath_chip_is_bb_tlv:1; + + /* + * goes with ath_strong_signal_diversiry: + * If we have fast diversity capability, read off + * Strong Signal fast diversity count set in the ini + * file, and store so we can restore the value when + * radar is disabled + */ + u_int32_t ath_fastdiv_val; +}; + +/* + * These are defined in the HAL for now, and must be migrated outside + * of there in order to be used by the new partial offload data path. + */ + +struct dfs_pulse { + u_int32_t rp_numpulses; /* Num of pulses in radar burst */ + u_int32_t rp_pulsedur; /* Duration of each pulse in usecs */ + u_int32_t rp_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_patterntype; /* fixed or variable pattern type*/ + u_int32_t rp_pulsevar; /* Time variation of pulse duration for + matched filter (single-sided) in usecs */ + u_int32_t rp_threshold; /* Threshold for MF output to indicateC + radar match */ + u_int32_t rp_mindur; /* Min pulse duration to be considered for + this pulse type */ + u_int32_t rp_maxdur; /* Max pusle duration to be considered for + this pulse type */ + u_int32_t rp_rssithresh; /* Minimum rssi to be considered a radar pulse */ + u_int32_t rp_meanoffset; /* Offset for timing adjustment */ + int32_t rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm */ + /* lower than in non TURBO mode. This will be used to offset that diff.*/ + u_int32_t rp_ignore_pri_window; + u_int32_t rp_pulseid; /* Unique ID for identifying filter */ +}; + +struct dfs_staggered_pulse { + u_int32_t rp_numpulses; /* Num of pulses in radar burst */ + u_int32_t rp_pulsedur; /* Duration of each pulse in usecs */ + u_int32_t rp_min_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_patterntype; /* fixed or variable pattern type*/ + u_int32_t rp_pulsevar; /* Time variation of pulse duration for + matched filter (single-sided) in usecs */ + u_int32_t rp_threshold; /* Thershold for MF output to indicateC + radar match */ + u_int32_t rp_mindur; /* Min pulse duration to be considered for + this pulse type */ + u_int32_t rp_maxdur; /* Max pusle duration to be considered for + this pulse type */ + u_int32_t rp_rssithresh; /* Minimum rssi to be considered a radar pulse */ + u_int32_t rp_meanoffset; /* Offset for timing adjustment */ + int32_t rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm */ + /* lower than in non TURBO mode. This will be used to offset that diff.*/ + u_int32_t rp_pulseid; /* Unique ID for identifying filter */ +}; + +struct dfs_bin5pulse { + u_int32_t b5_threshold; /* Number of bin5 pulses to indicate detection */ + u_int32_t b5_mindur; /* Min duration for a bin5 pulse */ + u_int32_t b5_maxdur; /* Max duration for a bin5 pulse */ + u_int32_t b5_timewindow; /* Window over which to count bin5 pulses */ + u_int32_t b5_rssithresh; /* Min rssi to be considered a pulse */ + u_int32_t b5_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dB */ +}; + +/* + * DFS NOL representation. + * + * This is used to represent the DFS NOL information between the + * NOL code in lmac/dfs/dfs_nol.c and any driver layer wishing + * to use it. + */ +struct dfs_nol_chan_entry { + u_int32_t nol_chfreq; /* Centre frequency, MHz */ + u_int32_t nol_chwidth; /* Width, MHz */ + unsigned long nol_start_ticks; /* start ticks, OS specific */ + u_int32_t nol_timeout_ms; /* timeout, mS */ +}; + +//HAL_PHYERR_PARAM; + +/* + * This represents the general case of the radar PHY configuration, + * across all chips. + * + * It's then up to each chip layer to translate to/from this + * (eg to HAL_PHYERR_PARAM for the HAL case.) + */ + +#define ATH_DFS_PHYERR_PARAM_NOVAL 0xFFFF +#define ATH_DFS_PHYERR_PARAM_ENABLE 0x8000 + +struct ath_dfs_phyerr_param { + int32_t pe_firpwr; /* FIR pwr out threshold */ + int32_t pe_rrssi; /* Radar rssi thresh */ + int32_t pe_height; /* Pulse height thresh */ + int32_t pe_prssi; /* Pulse rssi thresh */ + int32_t pe_inband; /* Inband thresh */ + + /* The following params are only for AR5413 and later */ + /* + * Relative power threshold in 0.5dB steps + */ + u_int32_t pe_relpwr; + + /* + * Pulse Relative step threshold in 0.5dB steps + */ + u_int32_t pe_relstep; + + /* + * Max length of radar sign in 0.8us units + */ + u_int32_t pe_maxlen; + + /* + * Use the average in-band power measured over 128 cycles + */ + bool pe_usefir128; + + /* + * Enable to block radar check if pkt detect is done via OFDM + * weak signal detect or pkt is detected immediately after tx + * to rx transition + */ + bool pe_blockradar; + + /* + * Enable to use the max rssi instead of the last rssi during + * fine gain changes for radar detection + */ + bool pe_enmaxrssi; +}; + +static inline void ath_dfs_phyerr_param_copy(struct ath_dfs_phyerr_param *dst, + struct ath_dfs_phyerr_param *src) +{ + adf_os_mem_copy(dst, src, sizeof(*dst)); +} + +static inline void ath_dfs_phyerr_init_noval(struct ath_dfs_phyerr_param *pe) +{ + pe->pe_firpwr = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_rrssi = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_height = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_prssi = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_inband = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_relpwr = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_relstep = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_maxlen = ATH_DFS_PHYERR_PARAM_NOVAL; + + /* XXX what about usefir128, blockradar, enmaxrssi? */ +} + +struct ath_dfs_radar_tab_info { + u_int32_t dfsdomain; + int numradars; + struct dfs_pulse *dfs_radars; + int numb5radars; + struct dfs_bin5pulse *b5pulses; + struct ath_dfs_phyerr_param dfs_defaultparams; +}; +#endif /* _DFS__STRUCTS_H_ */ diff --git a/CORE/SERVICES/DFS/inc/dfs_interface.h b/CORE/SERVICES/DFS/inc/dfs_interface.h new file mode 100644 index 000000000000..bd13f9eaec45 --- /dev/null +++ b/CORE/SERVICES/DFS/inc/dfs_interface.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_interface.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#ifndef _DFS__INTERFACE_H_ +#define _DFS__INTERFACE_H_ + +/* + * These are the only functions exported to the upper (device) layer. + */ + +/* + * EXPORT_SYMBOL(dfs_attach); + * EXPORT_SYMBOL(dfs_detach); + * EXPORT_SYMBOL(dfs_radar_enable); + * EXPORT_SYMBOL(dfs_process_phyerr); + * EXPORT_SYMBOL(dfs_control); + * EXPORT_SYMBOL(dfs_clear_stats); + * EXPORT_SYMBOL(dfs_usenol); + * EXPORT_SYMBOL(dfs_isdfsregdomain); + */ + +/* + * These are exported but not currently defined here; these should be + * evaluated. + * + * EXPORT_SYMBOL(dfs_process_ar_event); -- legacy adaptive radio processing + * EXPORT_SYMBOL(ath_ar_disable); + * EXPORT_SYMBOL(ath_ar_enable); + * EXPORT_SYMBOL(dfs_get_thresholds); + * EXPORT_SYMBOL(dfs_init_radar_filters); + * EXPORT_SYMBOL(dfs_getchanstate); + */ + + +u_int16_t dfs_isdfsregdomain(struct ieee80211com *ic); +int dfs_attach(struct ieee80211com *ic); +void dfs_detach(struct ieee80211com *ic); +int dfs_radar_enable(struct ieee80211com *ic, + struct ath_dfs_radar_tab_info *ri); +int dfs_radar_disable(struct ieee80211com *ic); +extern void dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen, u_int8_t rssi, + u_int8_t ext_rssi, u_int32_t rs_tstamp, u_int64_t fulltsf); +int dfs_control(struct ieee80211com *ic, u_int id, void *indata, u_int32_t insize, + void *outdata, u_int32_t *outsize); +void dfs_clear_stats(struct ieee80211com *ic); +#if 0 +/* The following are for FCC Bin 1-4 pulses */ +struct dfs_pulse dfs_fcc_radars[] = { + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_pulse dfs_mkk4_radars[] = { + /* following two filters are specific to Japan/MKK4 */ +// {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 17}, // 1389 +/- 6 us +// {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 18}, // 4000 +/- 6 us +// {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 19}, // 3846 +/- 7 us + {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us + {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us + {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, // 3846 +/- 7 us + + /* following filters are common to both FCC and JAPAN */ + + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_bin5pulse dfs_fcc_bin5pulses[] = { + {4, 28, 105, 12, 22, 5}, +}; + +struct dfs_bin5pulse dfs_jpn_bin5pulses[] = { + {5, 28, 105, 12, 22, 5}, +}; +struct dfs_pulse dfs_etsi_radars[] = { + + /* TYPE staggered pulse */ + /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ + {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31}, /* Type 5*/ + /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */ + {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32}, /* Type 6 */ + + /* constant PRF based */ + /* 0.8-5us, 200 300 PRF, 10 pulses */ + {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ + {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ + {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ + {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ +// {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, + + /* 0.8-15us, 200-1600 PRF, 15 pulses */ + {15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34}, /* Type 2 */ + + /* 0.8-15us, 2300-4000 PRF, 25 pulses*/ + {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35}, /* Type 3 */ + + /* 20-30us, 2000-4000 PRF, 20 pulses*/ + {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ +}; +#endif +#endif /* _DFS__INTERFACE_H_ */ diff --git a/CORE/SERVICES/DFS/inc/radar_filters.h b/CORE/SERVICES/DFS/inc/radar_filters.h new file mode 100644 index 000000000000..33ca999f47fe --- /dev/null +++ b/CORE/SERVICES/DFS/inc/radar_filters.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + radar_filters.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + + + + +struct dfs_pulse dfs_fcc_radars[] = { + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_pulse dfs_mkk4_radars[] = { + /* following two filters are specific to Japan/MKK4 */ +// {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 17}, // 1389 +/- 6 us +// {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 18}, // 4000 +/- 6 us +// {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 19}, // 3846 +/- 7 us + {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us + {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us + {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, // 3846 +/- 7 us + + /* following filters are common to both FCC and JAPAN */ + + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_bin5pulse dfs_fcc_bin5pulses[] = { + {4, 28, 105, 12, 22, 5}, +}; + +struct dfs_bin5pulse dfs_jpn_bin5pulses[] = { + {5, 28, 105, 12, 22, 5}, +}; +struct dfs_pulse dfs_etsi_radars[] = { + + /* TYPE staggered pulse */ + /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ + {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31}, /* Type 5*/ + /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */ + {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32}, /* Type 6 */ + + /* constant PRF based */ + /* 0.8-5us, 200 300 PRF, 10 pulses */ + {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ + {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ + {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ + {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ +// {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, + + /* 0.8-15us, 200-1600 PRF, 15 pulses */ + {15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34}, /* Type 2 */ + + /* 0.8-15us, 2300-4000 PRF, 25 pulses*/ + {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35}, /* Type 3 */ + + /* 20-30us, 2000-4000 PRF, 20 pulses*/ + {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ +}; diff --git a/CORE/SERVICES/DFS/sources b/CORE/SERVICES/DFS/sources new file mode 100644 index 000000000000..cf81004d198a --- /dev/null +++ b/CORE/SERVICES/DFS/sources @@ -0,0 +1,64 @@ +# +# sources file for DFS module +# +LMAC=.. +TOP=$(LMAC)\.. +INC=$(TOP)\include +HAL=$(TOP)\hal +ATH=$(LMAC)\ath_dev + +!IFDEF BUILD_UMAC +MP=$(TOP)\os\win_nwf +INC_MP=$(MP)\include +IF_ATH=$(TOP)\umac\if_lmac +!ELSE +MP=$(TOP)\winvista +INC_MP=$(INC)\winvista +IF_ATH=$(TOP)\if_ath_net80211 +!ENDIF + +!include $(INC_MP)\sources.inc + +TARGETNAME=ath_dfs +TARGETPATH=$(TOP)\lib +TARGETTYPE=LIBRARY + +!IFDEF BUILD_HTC +# Put htc include dirs at the head of the list. +# This ensures that the htc/adf header files will preempt any +# header files of the same names from the regular adf directories. +INCLUDES= $(INCLUDES) \ + $(TOP)\htc\inc; \ + $(TOP)\htc\adf\include; \ + $(TOP)\htc\adf\winvista\nbuf; \ + $(TOP)\htc\adf\winvista\include; +!ENDIF + +INCLUDES= $(INCLUDES) \ + $(TOP); \ + $(ATH); \ + $(ATH_DFS); \ + $(TOP)\ath\winvista; \ + $(TOP)\ath\winvista; \ + $(HAL); \ + $(HAL)\winvista; \ + $(IF_ATH); \ + $(INC); \ + $(INC_MP); \ + $(SDXROOT)\net\inc; \ + $(DDK_INC_PATH) + +SOURCES=$(SOURCES) \ + dfs_staggered.c \ + dfs_bindetects.c \ + dfs_misc.c \ + dfs_debug.c \ + dfs_process_radarevent.c \ + dfs_process_phyerr.c \ + dfs_nol.c \ + dfs_ar.c \ + dfs_fcc_bin5.c \ + dfs_init.c \ + dfs.c + + diff --git a/CORE/SERVICES/DFS/src/dfs.c b/CORE/SERVICES/DFS/src/dfs.c new file mode 100644 index 000000000000..9e2cf985ec35 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs.c @@ -0,0 +1,976 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include <osdep.h> + +#ifndef ATH_SUPPORT_DFS +#define ATH_SUPPORT_DFS 1 +#include "sys/queue.h" + +//#include "if_athioctl.h" +//#include "if_athvar.h" +#include "dfs_ioctl.h" +#include "dfs.h" + +int domainoverride=DFS_UNINIT_DOMAIN; + +/* + ** channel switch announcement (CSA) + ** usenol=1 (default) make CSA and switch to a new channel on radar detect + ** usenol=0, make CSA with next channel same as current on radar detect + ** usenol=2, no CSA and stay on the same channel on radar detect + **/ + +int usenol=1; +u_int32_t dfs_debug_level=ATH_DEBUG_DFS; + +/* + * Mark a channel as having interference detected upon it. + * + * This adds the interference marker to both the primary and + * extension channel. + * + * XXX TODO: make the NOL and channel interference logic a bit smarter + * so only the channel with the radar event is marked, rather than + * both the primary and extension. + */ +static void +dfs_channel_mark_radar(struct ath_dfs *dfs, struct ieee80211_channel *chan) +{ + struct ieee80211_channel_list chan_info; + int i; + + //chan->ic_flagext |= CHANNEL_INTERFERENCE; + + /* + * If radar is detected in 40MHz mode, add both the primary and the + * extension channels to the NOL. chan is the channel data we return + * to the ath_dev layer which passes it on to the 80211 layer. + * As we want the AP to change channels and send out a CSA, + * we always pass back the primary channel data to the ath_dev layer. + */ + if ((dfs->dfs_rinfo.rn_use_nol == 1) && + (dfs->ic->ic_opmode == IEEE80211_M_HOSTAP || + dfs->ic->ic_opmode == IEEE80211_M_IBSS)) { + chan_info.cl_nchans= 0; + dfs->ic->ic_get_ext_chan_info (dfs->ic, &chan_info); + + for (i = 0; i < chan_info.cl_nchans; i++) + { + if (chan_info.cl_channels[i] == NULL) { + DFS_PRINTK("%s: NULL channel\n", __func__); + } else { + chan_info.cl_channels[i]->ic_flagext |= CHANNEL_INTERFERENCE; + dfs_nol_addchan(dfs, chan_info.cl_channels[i], dfs->ath_dfs_nol_timeout); + } + } + + + /* + * Update the umac/driver channels with the new NOL information. + */ + dfs_nol_update(dfs); + } +} + + +static OS_TIMER_FUNC(dfs_task) +{ + struct ieee80211com *ic; + struct ath_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + dfs = (struct ath_dfs *)ic->ic_dfs; + /* + * XXX no locking?! + */ + if (dfs_process_radarevent(dfs, ic->ic_curchan)) { +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + + /* + * This marks the channel (and the extension channel, if HT40) as + * having seen a radar event. It marks CHAN_INTERFERENCE and + * will add it to the local NOL implementation. + * + * This is only done for 'usenol=1', as the other two modes + * don't do radar notification or CAC/CSA/NOL; it just notes + * there was a radar. + */ + + if (dfs->dfs_rinfo.rn_use_nol == 1) { + //dfs_channel_mark_radar(dfs, ic->ic_curchan); + } +#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ + + /* + * This calls into the umac DFS code, which sets the umac related + * radar flags and begins the channel change machinery. + * + * XXX TODO: the umac NOL code isn't used, but IEEE80211_CHAN_RADAR + * still gets set. Since the umac NOL code isn't used, that flag + * is never cleared. This needs to be fixed. See EV 105776. + */ + if (dfs->dfs_rinfo.rn_use_nol == 1) { + ic->ic_dfs_notify_radar(ic, ic->ic_curchan); + } else if (dfs->dfs_rinfo.rn_use_nol == 0) { + /* + * For the test mode, don't do a CSA here; but setup the + * test timer so we get a CSA _back_ to the original channel. + */ + OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); + dfs->ath_dfstest = 1; + dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee; + dfs->ath_dfstesttime = 1; /* 1ms */ + OS_SET_TIMER(&dfs->ath_dfstesttimer, dfs->ath_dfstesttime); + } + } + dfs->ath_radar_tasksched = 0; +} + +static +OS_TIMER_FUNC(dfs_testtimer_task) +{ + struct ieee80211com *ic; + struct ath_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + dfs = (struct ath_dfs *)ic->ic_dfs; + + /* XXX no locking? */ + dfs->ath_dfstest = 0; + + /* + * Flip the channel back to the original channel. + * Make sure this is done properly with a CSA. + */ + DFS_PRINTK("%s: go back to channel %d\n", + __func__, + dfs->ath_dfstest_ieeechan); + + /* + * XXX The mere existence of this method indirection + * to a umac function means this code belongs in + * the driver, _not_ here. Please fix this! + */ + ic->ic_start_csa(ic, dfs->ath_dfstest_ieeechan); +} + + +static int dfs_get_debug_info(struct ieee80211com *ic, int type, void *data) +{ + struct ath_dfs *dfs=(struct ath_dfs *)ic->ic_dfs; + if (data) { + *(u_int32_t *)data = dfs->dfs_proc_phyerr; + } + return (int)dfs->dfs_proc_phyerr; +} + + +int +dfs_attach(struct ieee80211com *ic) +{ + int i, n; + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct ath_dfs_radar_tab_info radar_info; +#define N(a) (sizeof(a)/sizeof(a[0])) + + if (dfs != NULL) { + /*DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: ic_dfs was not NULL\n", + __func__); + */ + return 1; + } + + dfs = (struct ath_dfs *)OS_MALLOC(NULL, sizeof(struct ath_dfs), GFP_ATOMIC); + + + if (dfs == NULL) { + /*DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: ath_dfs allocation failed\n", __func__);*/ + return 1; + } + + OS_MEMZERO(dfs, sizeof (struct ath_dfs)); + + ic->ic_dfs = (void *)dfs; + + dfs->ic = ic; + + ic->ic_dfs_debug = dfs_get_debug_info; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->dfs_nol = NULL; +#endif + + /* + * Zero out radar_info. It's possible that the attach function won't + * fetch an initial regulatory configuration; you really do want to + * ensure that the contents indicates there aren't any filters. + */ + OS_MEMZERO(&radar_info, sizeof(radar_info)); + ic->ic_dfs_attach(ic, &dfs->dfs_caps, &radar_info); + dfs_clear_stats(ic); + dfs->dfs_event_log_on = 0; + OS_INIT_TIMER(NULL, &(dfs->ath_dfs_task_timer), dfs_task, (void *) (ic)); +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + OS_INIT_TIMER(NULL, &(dfs->ath_dfstesttimer), dfs_testtimer_task, + (void *) ic); + dfs->ath_dfs_cac_time = ATH_DFS_WAIT_MS; + dfs->ath_dfstesttime = ATH_DFS_TEST_RETURN_PERIOD_MS; +#endif + ATH_DFSQ_LOCK_INIT(dfs); + STAILQ_INIT(&dfs->dfs_radarq); + ATH_ARQ_LOCK_INIT(dfs); + STAILQ_INIT(&dfs->dfs_arq); + STAILQ_INIT(&(dfs->dfs_eventq)); + ATH_DFSEVENTQ_LOCK_INIT(dfs); + dfs->events = (struct dfs_event *)OS_MALLOC(NULL, + sizeof(struct dfs_event)*DFS_MAX_EVENTS, + GFP_ATOMIC); + if (dfs->events == NULL) { + OS_FREE(dfs); + ic->ic_dfs = NULL; + DFS_PRINTK("%s: events allocation failed\n", __func__); + return 1; + } + for (i = 0; i < DFS_MAX_EVENTS; i++) { + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], re_list); + } + + dfs->pulses = (struct dfs_pulseline *)OS_MALLOC(NULL, sizeof(struct dfs_pulseline), GFP_ATOMIC); + if (dfs->pulses == NULL) { + OS_FREE(dfs->events); + dfs->events = NULL; + OS_FREE(dfs); + ic->ic_dfs = NULL; + DFS_PRINTK("%s: pulse buffer allocation failed\n", __func__); + return 1; + } + + dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; + + /* 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) { + DFS_PRINTK("%s: cannot allocate memory for radar filter types\n", + __func__); + goto bad1; + } + OS_MEMZERO(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype)); + } + /* 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", + __func__); + goto bad1; + } + for (n=0; n<256; n++) { + dfs->dfs_radartable[n] = OS_MALLOC(NULL, DFS_MAX_RADAR_OVERLAP*sizeof(int8_t), + GFP_ATOMIC); + if (dfs->dfs_radartable[n] == NULL) { + DFS_PRINTK("%s: cannot allocate memory for radar table entry\n", + __func__); + goto bad2; + } + } + + if (usenol == 0) + DFS_PRINTK("%s: NOL disabled\n", __func__); + else if (usenol == 2) + DFS_PRINTK("%s: NOL disabled; no CSA\n", __func__); + + dfs->dfs_rinfo.rn_use_nol = usenol; + + /* Init the cached extension channel busy for false alarm reduction */ + dfs->dfs_rinfo.ext_chan_busy_ts = ic->ic_get_TSF64(ic); + dfs->dfs_rinfo.dfs_ext_chan_busy = 0; + /* Init the Bin5 chirping related data */ + dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; + dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; + dfs->dfs_b5radars = NULL; + + /* + * If dfs_init_radar_filters() fails, we can abort here and + * reconfigure when the first valid channel + radar config + * is available. + */ + if ( dfs_init_radar_filters( ic, &radar_info) ) { + DFS_PRINTK(" %s: Radar Filter Intialization Failed \n", + __func__); + return 1; + } + + dfs->ath_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; + dfs->ath_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_queued_count = 0; + dfs->dfs_phyerr_w53_counter = 0; + dfs->dfs_pri_multiplier = 2; + + dfs->ath_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; + return 0; + +bad2: + OS_FREE(dfs->dfs_radartable); + dfs->dfs_radartable = NULL; +bad1: + for (n=0; n<DFS_MAX_RADAR_TYPES; n++) { + if (dfs->dfs_radarf[n] != NULL) { + OS_FREE(dfs->dfs_radarf[n]); + dfs->dfs_radarf[n] = NULL; + } + } + if (dfs->pulses) { + OS_FREE(dfs->pulses); + dfs->pulses = NULL; + } + if (dfs->events) { + OS_FREE(dfs->events); + dfs->events = NULL; + } + + if (ic->ic_dfs) { + OS_FREE(ic->ic_dfs); + ic->ic_dfs = NULL; + } + return 1; +#undef N +} + +void +dfs_detach(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + int n, empty; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: ic_dfs is NULL\n", __func__); + return; + } + + /* Bug 29099 make sure all outstanding timers are cancelled*/ + + if (dfs->ath_radar_tasksched) { + OS_CANCEL_TIMER(&dfs->ath_dfs_task_timer); + dfs->ath_radar_tasksched = 0; + } + + if (dfs->ath_dfstest) { + OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); + dfs->ath_dfstest = 0; + } + +#if 0 +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + if (dfs->ic_dfswait) { + OS_CANCEL_TIMER(&dfs->ic_dfswaittimer); + dfs->ath_dfswait = 0; + } + + OS_CANCEL_TIMER(&dfs->sc_dfs_war_timer); + if (dfs->dfs_nol != NULL) { + struct dfs_nolelem *nol, *next; + nol = dfs->dfs_nol; + /* Bug 29099 - each NOL element has its own timer, cancel it and + free the element*/ + while (nol != NULL) { + OS_CANCEL_TIMER(&nol->nol_timer); + next = nol->nol_next; + OS_FREE(nol); + nol = next; + } + dfs->dfs_nol = NULL; + } +#endif +#endif + /* Return radar events to free q*/ + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + + /* Free up pulse log*/ + if (dfs->pulses != NULL) { + OS_FREE(dfs->pulses); + dfs->pulses = NULL; + } + + for (n=0; n<DFS_MAX_RADAR_TYPES;n++) { + if (dfs->dfs_radarf[n] != NULL) { + OS_FREE(dfs->dfs_radarf[n]); + dfs->dfs_radarf[n] = NULL; + } + } + + + if (dfs->dfs_radartable != NULL) { + for (n=0; n<256; n++) { + if (dfs->dfs_radartable[n] != NULL) { + OS_FREE(dfs->dfs_radartable[n]); + dfs->dfs_radartable[n] = NULL; + } + } + OS_FREE(dfs->dfs_radartable); + dfs->dfs_radartable = NULL; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->ath_dfs_isdfsregdomain = 0; +#endif + } + + if (dfs->dfs_b5radars != NULL) { + OS_FREE(dfs->dfs_b5radars); + dfs->dfs_b5radars=NULL; + } + +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * dfs_reset_ar(dfs); + */ + ATH_ARQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_arq)); + ATH_ARQ_UNLOCK(dfs); + if (!empty) { +/* + * Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * + * dfs_reset_arq(dfs); + */ + } + if (dfs->events != NULL) { + OS_FREE(dfs->events); + dfs->events = NULL; + } + dfs_nol_timer_cleanup(dfs); + OS_FREE(dfs); + + /* XXX? */ + ic->ic_dfs = NULL; +} +/* + * This is called each time a channel change occurs, to (potentially) enable + * the radar code. + */ +int dfs_radar_disable(struct ieee80211com *ic) +{ + struct ath_dfs *dfs=(struct ath_dfs *)ic->ic_dfs; +#ifdef ATH_ENABLE_AR + dfs->dfs_proc_phyerr &= ~DFS_AR_EN; +#endif + dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; + return 0; +} +/* + * This is called each time a channel change occurs, to (potentially) enable + * the radar code. + */ +int dfs_radar_enable(struct ieee80211com *ic, + struct ath_dfs_radar_tab_info *radar_info) +{ + int is_ext_ch; + int is_fastclk = 0; + //u_int32_t rfilt; + struct ath_dfs *dfs; + struct dfs_state *rs_pri, *rs_ext; + struct ieee80211_channel *chan=ic->ic_curchan, *ext_ch = NULL; + is_ext_ch=IEEE80211_IS_CHAN_11N_HT40(ic->ic_curchan); + dfs=(struct ath_dfs *)ic->ic_dfs; + rs_pri = NULL; + rs_ext = NULL; +#if 0 + int i; +#endif + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: ic_dfs is NULL\n", + __func__); + + return -EIO; + } + ic->ic_dfs_disable(ic); + + /* + * Setting country code might change the DFS domain + * so initialize the DFS Radar filters + */ + dfs_init_radar_filters(ic, radar_info); + + if ((ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS)) { + + if (IEEE80211_IS_CHAN_DFS(chan)) { + + u_int8_t index_pri, index_ext; +#ifdef ATH_ENABLE_AR + dfs->dfs_proc_phyerr |= DFS_AR_EN; +#endif + dfs->dfs_proc_phyerr |= DFS_RADAR_EN; + + + + if (is_ext_ch) { + ext_ch = ieee80211_get_extchan(ic); + } + dfs_reset_alldelaylines(dfs); + + rs_pri = dfs_getchanstate(dfs, &index_pri, 0); + if (ext_ch) { + rs_ext = dfs_getchanstate(dfs, &index_ext, 1); + } + if (rs_pri != NULL && ((ext_ch==NULL)||(rs_ext != NULL))) { + struct ath_dfs_phyerr_param pe; + + OS_MEMSET(&pe, '\0', sizeof(pe)); + + if (index_pri != dfs->dfs_curchan_radindex) + dfs_reset_alldelaylines(dfs); + + dfs->dfs_curchan_radindex = (int16_t) index_pri; + + if (rs_ext) + dfs->dfs_extchan_radindex = (int16_t) index_ext; + + ath_dfs_phyerr_param_copy(&pe, + &rs_pri->rs_param); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "%s: firpwr=%d, rssi=%d, height=%d, " + "prssi=%d, inband=%d, relpwr=%d, " + "relstep=%d, maxlen=%d\n", + __func__, + pe.pe_firpwr, + pe.pe_rrssi, + pe.pe_height, + pe.pe_prssi, + pe.pe_inband, + pe.pe_relpwr, + pe.pe_relstep, + pe.pe_maxlen + ); + +#if 0 //Not needed + /* Disable strong signal fast antenna diversity */ + ath_hal_setcapability(ah, HAL_CAP_DIVERSITY, + HAL_CAP_STRONG_DIV, 1, NULL); +#endif + ic->ic_dfs_enable(ic, &is_fastclk, &pe); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "Enabled radar detection on channel %d\n", + chan->ic_freq); + dfs->dur_multiplier = + is_fastclk ? DFS_FAST_CLOCK_MULTIPLIER : DFS_NO_FAST_CLOCK_MULTIPLIER; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "%s: duration multiplier is %d\n", __func__, dfs->dur_multiplier); + } else + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: No more radar states left\n", + __func__); + } + } + + return 0; +} + +int +dfs_control(struct ieee80211com *ic, u_int id, + void *indata, u_int32_t insize, + void *outdata, u_int32_t *outsize) +{ + int error = 0; + struct ath_dfs_phyerr_param peout; + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct dfs_ioctl_params *dfsparams; + u_int32_t val=0; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + struct dfsreq_nolinfo *nol; + u_int32_t *data = NULL; +#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ + int i; + + if (dfs == NULL) { + error = -EINVAL; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s DFS is null\n", __func__); + goto bad; + } + + + switch (id) { + case DFS_SET_THRESH: + if (insize < sizeof(struct dfs_ioctl_params) || !indata) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: insize=%d, expected=%d bytes, indata=%p\n", + __func__, insize, sizeof(struct dfs_ioctl_params), + indata); + error = -EINVAL; + break; + } + dfsparams = (struct dfs_ioctl_params *) indata; + if (!dfs_set_thresholds(ic, DFS_PARAM_FIRPWR, dfsparams->dfs_firpwr)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_RRSSI, dfsparams->dfs_rrssi)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_HEIGHT, dfsparams->dfs_height)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_PRSSI, dfsparams->dfs_prssi)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_INBAND, dfsparams->dfs_inband)) + error = -EINVAL; + /* 5413 speicfic */ + if (!dfs_set_thresholds(ic, DFS_PARAM_RELPWR, dfsparams->dfs_relpwr)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_RELSTEP, dfsparams->dfs_relstep)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_MAXLEN, dfsparams->dfs_maxlen)) + error = -EINVAL; + break; + case DFS_GET_THRESH: + if (!outdata || !outsize || *outsize <sizeof(struct dfs_ioctl_params)) { + error = -EINVAL; + break; + } + *outsize = sizeof(struct dfs_ioctl_params); + dfsparams = (struct dfs_ioctl_params *) outdata; + + /* + * Fetch the DFS thresholds using the internal representation. + */ + (void) dfs_get_thresholds(ic, &peout); + + /* + * Convert them to the dfs IOCTL representation. + */ + ath_dfs_dfsparam_to_ioctlparam(&peout, dfsparams); + break; + case DFS_RADARDETECTS: + if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) { + error = -EINVAL; + break; + } + *outsize = sizeof (u_int32_t); + *((u_int32_t *)outdata) = dfs->ath_dfs_stats.num_radar_detects; + break; + case DFS_DISABLE_DETECT: + dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; + dfs->ic->ic_dfs_state.ignore_dfs = 1; + DFS_PRINTK("%s enable detects, ignore_dfs %d\n", + __func__, + dfs->ic->ic_dfs_state.ignore_dfs); + break; + case DFS_ENABLE_DETECT: + dfs->dfs_proc_phyerr |= DFS_RADAR_EN; + dfs->ic->ic_dfs_state.ignore_dfs = 0; + DFS_PRINTK("%s enable detects, ignore_dfs %d\n", + __func__, + dfs->ic->ic_dfs_state.ignore_dfs); + break; + case DFS_DISABLE_FFT: + //UMACDFS: TODO: val = ath_hal_dfs_config_fft(sc->sc_ah, false); + DFS_PRINTK("%s TODO disable FFT val=0x%x \n", __func__, val); + break; + case DFS_ENABLE_FFT: + //UMACDFS TODO: val = ath_hal_dfs_config_fft(sc->sc_ah, true); + DFS_PRINTK("%s TODO enable FFT val=0x%x \n", __func__, val); + break; + case DFS_SET_DEBUG_LEVEL: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->dfs_debug_mask= *(u_int32_t *)indata; + DFS_PRINTK("%s debug level now = 0x%x \n", + __func__, + dfs->dfs_debug_mask); + if (dfs->dfs_debug_mask & ATH_DEBUG_DFS3) { + /* Enable debug Radar Event */ + dfs->dfs_event_log_on = 1; + } else { + dfs->dfs_event_log_on = 0; + } + break; + case DFS_SET_FALSE_RSSI_THRES: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->ath_dfs_false_rssi_thres= *(u_int32_t *)indata; + DFS_PRINTK("%s false RSSI threshold now = 0x%x \n", + __func__, + dfs->ath_dfs_false_rssi_thres); + break; + case DFS_SET_PEAK_MAG: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->ath_dfs_peak_mag= *(u_int32_t *)indata; + DFS_PRINTK("%s peak_mag now = 0x%x \n", + __func__, + dfs->ath_dfs_peak_mag); + break; + case DFS_IGNORE_CAC: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + if (*(u_int32_t *)indata) { + dfs->ic->ic_dfs_state.ignore_cac= 1; + } else { + dfs->ic->ic_dfs_state.ignore_cac= 0; + } + DFS_PRINTK("%s ignore cac = 0x%x \n", + __func__, + dfs->ic->ic_dfs_state.ignore_cac); + break; + case DFS_SET_NOL_TIMEOUT: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + if (*(int *)indata) { + dfs->ath_dfs_nol_timeout= *(int *)indata; + } else { + dfs->ath_dfs_nol_timeout= DFS_NOL_TIMEOUT_S; + } + DFS_PRINTK("%s nol timeout = %d sec \n", + __func__, + dfs->ath_dfs_nol_timeout); + break; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + case DFS_MUTE_TIME: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + data = (u_int32_t *) indata; + dfs->ath_dfstesttime = *data; + dfs->ath_dfstesttime *= (1000); //convert sec into ms + break; + case DFS_GET_USENOL: + if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) { + error = -EINVAL; + break; + } + *outsize = sizeof(u_int32_t); + *((u_int32_t *)outdata) = dfs->dfs_rinfo.rn_use_nol; + + + + for (i = 0; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count); i++) { + //DFS_DPRINTK(sc, ATH_DEBUG_DFS,"ts=%llu diff_ts=%u rssi=%u dur=%u\n", dfs->radar_log[i].ts, dfs->radar_log[i].diff_ts, dfs->radar_log[i].rssi, dfs->radar_log[i].dur); + + } + dfs->dfs_event_log_count = 0; + dfs->dfs_phyerr_count = 0; + dfs->dfs_phyerr_reject_count = 0; + dfs->dfs_phyerr_queued_count = 0; + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + break; + case DFS_SET_USENOL: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->dfs_rinfo.rn_use_nol = *(u_int32_t *)indata; + /* iwpriv markdfs in linux can do the same thing... */ + break; + case DFS_GET_NOL: + if (!outdata || !outsize || *outsize < sizeof(struct dfsreq_nolinfo)) { + error = -EINVAL; + break; + } + *outsize = sizeof(struct dfsreq_nolinfo); + nol = (struct dfsreq_nolinfo *)outdata; + dfs_get_nol(dfs, (struct dfsreq_nolelem *)nol->dfs_nol, &nol->ic_nchans); + dfs_print_nol(dfs); + break; + case DFS_SET_NOL: + if (insize < sizeof(struct dfsreq_nolinfo) || !indata) { + error = -EINVAL; + break; + } + nol = (struct dfsreq_nolinfo *) indata; + dfs_set_nol(dfs, (struct dfsreq_nolelem *)nol->dfs_nol, nol->ic_nchans); + break; + + case DFS_SHOW_NOL: + dfs_print_nol(dfs); + break; + case DFS_BANGRADAR: + #if 0 //MERGE_TBD + if(sc->sc_nostabeacons) + { + printk("No radar detection Enabled \n"); + break; + } +#endif + dfs->dfs_bangradar = 1; + dfs->ath_radar_tasksched = 1; + OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0); + break; +#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ + default: + error = -EINVAL; + } +bad: + return error; +} +int +dfs_set_thresholds(struct ieee80211com *ic, const u_int32_t threshtype, + const u_int32_t value) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + int16_t chanindex; + struct dfs_state *rs; + struct ath_dfs_phyerr_param pe; + int is_fastclk = 0; /* XXX throw-away */ + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: ic_dfs is NULL\n", + __func__); + return 0; + } + + chanindex = dfs->dfs_curchan_radindex; + if ((chanindex <0) || (chanindex >= DFS_NUM_RADAR_STATES)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: chanindex = %d, DFS_NUM_RADAR_STATES=%d\n", + __func__, + chanindex, + DFS_NUM_RADAR_STATES); + return 0; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: threshtype=%d, value=%d\n", __func__, threshtype, value); + + ath_dfs_phyerr_init_noval(&pe); + + rs = &(dfs->dfs_radar[chanindex]); + switch (threshtype) { + case DFS_PARAM_FIRPWR: + rs->rs_param.pe_firpwr = (int32_t) value; + pe.pe_firpwr = value; + break; + case DFS_PARAM_RRSSI: + rs->rs_param.pe_rrssi = value; + pe.pe_rrssi = value; + break; + case DFS_PARAM_HEIGHT: + rs->rs_param.pe_height = value; + pe.pe_height = value; + break; + case DFS_PARAM_PRSSI: + rs->rs_param.pe_prssi = value; + pe.pe_prssi = value; + break; + case DFS_PARAM_INBAND: + rs->rs_param.pe_inband = value; + pe.pe_inband = value; + break; + /* 5413 specific */ + case DFS_PARAM_RELPWR: + rs->rs_param.pe_relpwr = value; + pe.pe_relpwr = value; + break; + case DFS_PARAM_RELSTEP: + rs->rs_param.pe_relstep = value; + pe.pe_relstep = value; + break; + case DFS_PARAM_MAXLEN: + rs->rs_param.pe_maxlen = value; + pe.pe_maxlen = value; + break; + default: + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: unknown threshtype (%d)\n", + __func__, + threshtype); + break; + } + + /* + * The driver layer dfs_enable routine is tasked with translating + * values from the global format to the per-device (HAL, offload) + * format. + */ + ic->ic_dfs_enable(ic, &is_fastclk, &pe); + return 1; +} + +int +dfs_get_thresholds(struct ieee80211com *ic, struct ath_dfs_phyerr_param *param) +{ + //UMACDFS : TODO:ath_hal_getdfsthresh(sc->sc_ah, param); + + OS_MEMZERO(param, sizeof(*param)); + + (void) ic->ic_dfs_get_thresholds(ic, param); + + return 1; +} + +u_int16_t dfs_usenol(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + return dfs ? (u_int16_t) dfs->dfs_rinfo.rn_use_nol : 0; +} + +u_int16_t dfs_isdfsregdomain(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + return dfs ? dfs->dfsdomain : 0; +} + +#endif /* ATH_UPPORT_DFS */ + diff --git a/CORE/SERVICES/DFS/src/dfs.h b/CORE/SERVICES/DFS/src/dfs.h new file mode 100644 index 000000000000..a65db7c9813c --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs.h @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#ifndef _DFS_H_ +#define _DFS_H_ + +/* +*TO DO DFS- Need to include this file later on +*#include "ath_internal.h" +*/ +/*DFS New Include Start*/ + +#include <adf_net_types.h> /* ADF_NBUF_EXEMPT_NO_EXEMPTION, etc. */ +#include <adf_nbuf.h> /* adf_nbuf_t, etc. */ +#include <adf_os_util.h> /* adf_os_assert */ +#include <adf_os_lock.h> /* adf_os_spinlock */ +#include <queue.h> /* TAILQ */ +#include <adf_os_time.h> +#include <adf_os_timer.h> +#include <adf_os_mem.h> +#include <osdep.h> +/*DFS Utility Include END*/ + +/* From wlan_modules/include/ */ +#include "ath_dfs_structs.h" +/*DFS - Newly added File to interface cld UMAC and dfs data structures*/ +#include <wma_dfs_interface.h> +/* +*TO DO DFS- Need to include this file later on +#include "ah.h" +*/ +//#include "ah_desc.h" +#include "dfs_ioctl.h" +#include "dfs_ioctl_private.h" +#include "dfs_interface.h" +#include "_ieee80211_common.h" + +#define ATH_SUPPORT_DFS 1 +#define CHANNEL_TURBO 0x00010 +#define DFS_PRINTK(_fmt, ...) printk((_fmt), __VA_ARGS__) +#define DFS_DPRINTK(dfs, _m, _fmt, ...) do { \ + if (((dfs) == NULL) || \ + ((dfs) != NULL && \ + ((_m) & (dfs)->dfs_debug_mask))) { \ + printk(_fmt, __VA_ARGS__); \ + } \ +} while (0) + +#define DFS_MIN(a,b) ((a)<(b)?(a):(b)) +#define DFS_MAX(a,b) ((a)>(b)?(a):(b)) +#define DFS_DIFF(a,b) (DFS_MAX(a,b) - DFS_MIN(a,b)) +/* + * Maximum number of radar events to be processed in a single iteration. + * Allows soft watchdog to run. + */ +#define MAX_EVENTS 100 + +/* + * Constants to use for chirping detection. + * + * All are unconverted as HW reports them. + * + * XXX Are these constants with or without fast clock 5GHz operation? + * XXX Peregrine reports pulses in microseconds, not hardware clocks! + */ +#define MIN_BIN5_DUR 63 /* 50 * 1.25*/ +#define MIN_BIN5_DUR_MICROSEC 50 +#define MAYBE_BIN5_DUR 35 /* 28 * 1.25*/ +#define MAYBE_BIN5_DUR_MICROSEC 28 +//#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 DFS_MARGIN_EQUAL(a, b, margin) ((DFS_DIFF(a,b)) <= margin) +#define DFS_MAX_STAGGERED_BURSTS 3 + +/* All filter thresholds in the radar filter tables are effective at a 50% channel loading */ +#define DFS_CHAN_LOADING_THRESH 50 +#define DFS_EXT_CHAN_LOADING_THRESH 30 +#define DFS_DEFAULT_PRI_MARGIN 6 +#define DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN 4 +#define ATH_DFSQ_LOCK(_dfs) spin_lock_dpc((&(_dfs)->dfs_radarqlock)) +#define ATH_DFSQ_UNLOCK(_dfs) spin_unlock_dpc((&(_dfs)->dfs_radarqlock)) +#define ATH_DFSQ_LOCK_INIT(_dfs) adf_os_spinlock_init(&(_dfs)->dfs_radarqlock) + +#define ATH_ARQ_LOCK(_dfs) spin_lock_dpc((&(_dfs)->dfs_arqlock)) +#define ATH_ARQ_UNLOCK(_dfs) spin_unlock_dpc((&(_dfs)->dfs_arqlock)) +#define ATH_ARQ_LOCK_INIT(_dfs) adf_os_spinlock_init(&(_dfs)->dfs_arqlock) + +#define ATH_DFSEVENTQ_LOCK(_dfs) spin_lock_dpc((&(_dfs)->dfs_eventqlock)) +#define ATH_DFSEVENTQ_UNLOCK(_dfs) spin_unlock_dpc((&(_dfs)->dfs_eventqlock)) +#define ATH_DFSEVENTQ_LOCK_INIT(_dfs) adf_os_spinlock_init((&(_dfs)->dfs_eventqlock)); + + + + + +#define DFS_TSMASK 0xFFFFFFFF /* Mask for time stamp from descriptor */ +#define DFS_TSSHIFT 32 /* Shift for time stamp from descriptor */ +#define DFS_TSF_WRAP 0xFFFFFFFFFFFFFFFFULL /* 64 bit TSF wrap value */ +#define DFS_64BIT_TSFMASK 0x0000000000007FFFULL /* TS mask for 64 bit value */ + + +#define DFS_AR_RADAR_RSSI_THR 5 /* in dB */ +#define DFS_AR_RADAR_RESET_INT 1 /* in secs */ +#define DFS_AR_RADAR_MAX_HISTORY 500 +#define DFS_AR_REGION_WIDTH 128 +#define DFS_AR_RSSI_THRESH_STRONG_PKTS 17 /* in dB */ +#define DFS_AR_RSSI_DOUBLE_THRESHOLD 15 /* in dB */ +#define DFS_AR_MAX_NUM_ACK_REGIONS 9 +#define DFS_AR_ACK_DETECT_PAR_THRESH 20 +#define DFS_AR_PKT_COUNT_THRESH 20 + +#define DFS_MAX_DL_SIZE 64 +#define DFS_MAX_DL_MASK 0x3F + +#define DFS_NOL_TIME DFS_NOL_TIMEOUT_US + /* 30 minutes in usecs */ + +#define DFS_WAIT_TIME 60*1000000 /* 1 minute in usecs */ + +#define DFS_DISABLE_TIME 3*60*1000000 /* 3 minutes in usecs */ + +#define DFS_MAX_B5_SIZE 128 +#define DFS_MAX_B5_MASK 0x0000007F /* 128 */ + +#define DFS_MAX_RADAR_OVERLAP 16 /* Max number of overlapping filters */ + +#define DFS_MAX_EVENTS 1024 /* Max number of dfs events which can be q'd */ + +#define DFS_RADAR_EN 0x80000000 /* Radar detect is capable */ +#define DFS_AR_EN 0x40000000 /* AR detect is capable */ +#define DFS_MAX_RSSI_VALUE 0x7fffffff /* Max rssi value */ + +#define DFS_BIN_MAX_PULSES 60 /* max num of pulses in a burst */ +#define DFS_BIN5_PRI_LOWER_LIMIT 990 /* us */ + +/* to cover the single pusle burst case, change from 2010 us to 2010000 us */ + +/* + * this is reverted back to 2010 as larger value causes false + * bin5 detect (EV76432, EV76320) + */ +#define DFS_BIN5_PRI_HIGHER_LIMIT 2010 /* us */ + +#define DFS_BIN5_WIDTH_MARGIN 4 /* us */ +#define DFS_BIN5_RSSI_MARGIN 5 /* dBm */ +/*Following threshold is not specified but should be okay statistically*/ +#define DFS_BIN5_BRI_LOWER_LIMIT 300000 /* us */ +#define DFS_BIN5_BRI_UPPER_LIMIT 12000000 /* us */ + +#define DFS_MAX_PULSE_BUFFER_SIZE 1024 /* Max number of pulses kept in buffer */ +#define DFS_MAX_PULSE_BUFFER_MASK 0x3ff + +#define DFS_FAST_CLOCK_MULTIPLIER (800/11) +#define DFS_NO_FAST_CLOCK_MULTIPLIER (80) + +typedef adf_os_spinlock_t dfsq_lock_t; + +#ifdef WIN32 +#pragma pack(push, dfs_pulseparams, 1) +#endif +struct dfs_pulseparams { + u_int64_t p_time; /* time for start of pulse in usecs*/ + u_int8_t p_dur; /* Duration of pulse in usecs*/ + u_int8_t p_rssi; /* Duration of pulse in usecs*/ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_pulseparams) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_pulseline, 1) +#endif +struct dfs_pulseline { + /* pl_elems - array of pulses in delay line */ + struct dfs_pulseparams pl_elems[DFS_MAX_PULSE_BUFFER_SIZE]; + u_int32_t pl_firstelem; /* Index of the first element */ + u_int32_t pl_lastelem; /* Index of the last element */ + u_int32_t pl_numelems; /* Number of elements in the delay line */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_pulseline) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_event, 1) +#endif + +#define DFS_EVENT_CHECKCHIRP 0x01 /* Whether to check the chirp flag */ +#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. + */ +#define DFS_EVENT_ISCHIRP(e) \ + ((e)->re_flags & (DFS_EVENT_HW_CHIRP | DFS_EVENT_SW_CHIRP)) + +/* + * Check if the given event is to be rejected as not possibly + * a chirp. This means: + * (a) it's a hardware or software checked chirp, and + * (b) the HW/SW chirp bits are both 0. + */ +#define DFS_EVENT_NOTCHIRP(e) \ + (((e)->re_flags & (DFS_EVENT_CHECKCHIRP)) && \ + (! DFS_EVENT_ISCHIRP((e)))) + +struct dfs_event { + u_int64_t re_full_ts; /* 64-bit full timestamp from interrupt time */ + u_int32_t re_ts; /* Original 15 bit recv timestamp */ + u_int8_t re_rssi; /* rssi of radar event */ + u_int8_t re_dur; /* duration of radar pulse */ + u_int8_t re_chanindex; /* Channel of event */ + u_int8_t re_flags; /* Event flags */ + u_int32_t re_freq; /* Centre frequency of event, KHz */ + u_int32_t re_freq_lo; /* Lower bounds of frequency, KHz */ + u_int32_t re_freq_hi; /* Upper bounds of frequency, KHz */ + STAILQ_ENTRY(dfs_event) re_list; /* List of radar events */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_event) +#endif + +#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 */ +#define DFS_AR_ARQ_SEQSIZE 2049 /* Sequence counter wrap for AR */ + +#define DFS_RADARQ_SIZE 512 /* 1K radar events for buffer size */ +#define DFS_RADARQ_SEQSIZE 513 /* Sequence counter wrap for radar */ +#define DFS_NUM_RADAR_STATES 64 /* Number of radar channels we keep state for */ +#define DFS_MAX_NUM_RADAR_FILTERS 10 /* Max number radar filters for each type */ +#define DFS_MAX_RADAR_TYPES 32 /* Number of different radar types */ + +struct dfs_ar_state { + u_int32_t ar_prevwidth; + u_int32_t ar_phyerrcount[DFS_AR_MAX_ACK_RADAR_DUR]; + u_int32_t ar_acksum; + u_int32_t ar_packetthreshold; /* Thresh to determine traffic load */ + u_int32_t ar_parthreshold; /* Thresh to determine peak */ + u_int32_t ar_radarrssi; /* Rssi threshold for AR event */ + u_int16_t ar_prevtimestamp; + u_int16_t ar_peaklist[DFS_AR_MAX_NUM_PEAKS]; +}; + +#ifdef WIN32 +#pragma pack(push, dfs_delayelem, 1) +#endif +struct dfs_delayelem { + u_int32_t de_time; /* Current "filter" time for start of pulse in usecs*/ + u_int8_t de_dur; /* Duration of pulse in usecs*/ + u_int8_t de_rssi; /* rssi of pulse in dB*/ + u_int64_t de_ts; /* time stamp for this delay element */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_delayelem) +#endif + +/* NB: The first element in the circular buffer is the oldest element */ + +#ifdef WIN32 +#pragma pack(push, dfs_delayline, 1) +#endif +struct dfs_delayline { + struct dfs_delayelem dl_elems[DFS_MAX_DL_SIZE]; /* Array of pulses in delay line */ + u_int64_t dl_last_ts; /* Last timestamp the delay line was used (in usecs) */ + u_int32_t dl_firstelem; /* Index of the first element */ + u_int32_t dl_lastelem; /* Index of the last element */ + u_int32_t dl_numelems; /* Number of elements in the delay line */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_delayline) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_filter, 1) +#endif +struct dfs_filter { + struct dfs_delayline rf_dl; /* Delay line of pulses for this filter */ + u_int32_t rf_numpulses; /* Number of pulses in the filter */ + u_int32_t rf_minpri; /* min pri to be considered for this filter*/ + u_int32_t rf_maxpri; /* max pri to be considered for this filter*/ + u_int32_t rf_threshold; /* match filter output threshold for radar detect */ + u_int32_t rf_filterlen; /* Length (in usecs) of the filter */ + u_int32_t rf_patterntype; /* fixed or variable pattern type */ + u_int32_t rf_fixed_pri_radar_pulse; /* indicates if it is a fixed pri pulse */ + u_int32_t rf_mindur; /* Min duration for this radar filter */ + u_int32_t rf_maxdur; /* Max duration for this radar filter */ + u_int32_t rf_ignore_pri_window; + u_int32_t rf_pulseid; /* Unique ID corresponding to the original filter ID */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_filter) +#endif + +struct dfs_filtertype { + struct dfs_filter ft_filters[DFS_MAX_NUM_RADAR_FILTERS]; + u_int32_t ft_filterdur; /* Duration of pulse which specifies filter type*/ + u_int32_t ft_numfilters; /* Num filters of this type */ + u_int64_t ft_last_ts; /* Last timestamp this filtertype was used + * (in usecs) */ + u_int32_t ft_mindur; /* min pulse duration to be considered + * for this filter type */ + u_int32_t ft_maxdur; /* max pulse duration to be considered + * for this filter type */ + u_int32_t ft_rssithresh; /* min rssi to be considered + * for this filter type */ + u_int32_t ft_numpulses; /* Num pulses in each filter of this type */ + u_int32_t ft_patterntype; /* fixed or variable pattern type */ + u_int32_t ft_minpri; /* min pri to be considered for this type */ + u_int32_t ft_rssimargin; /* rssi threshold margin. In Turbo Mode HW + * reports rssi 3dB lower than in non TURBO + * mode. This will offset that diff. */ +}; + +struct dfs_state { + struct ieee80211_channel rs_chan; /* Channel info */ + u_int8_t rs_chanindex; /* Channel index in radar structure */ + u_int32_t rs_numradarevents; /* Number of radar events */ + + struct ath_dfs_phyerr_param rs_param; +}; + +#define DFS_NOL_TIMEOUT_S (30*60) /* 30 minutes in seconds */ +//#define DFS_NOL_TIMEOUT_S (5*60) /* 5 minutes in seconds - debugging */ +#define DFS_NOL_TIMEOUT_MS (DFS_NOL_TIMEOUT_S * 1000) +#define DFS_NOL_TIMEOUT_US (DFS_NOL_TIMEOUT_MS * 1000) + +#ifdef WIN32 +#pragma pack(push, dfs_nolelem, 1) +#endif +struct dfs_nolelem { + u_int32_t nol_freq; /* centre frequency */ + u_int32_t nol_chwidth; /* event width (MHz) */ + unsigned long nol_start_ticks; /* NOL start time in OS ticks */ + u_int32_t nol_timeout_ms; /* NOL timeout value in msec */ + os_timer_t nol_timer; /* per element NOL timer */ + struct dfs_nolelem *nol_next; /* next element pointer */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_nolelem) +#endif + +/* Pass structure to DFS NOL timer */ +struct dfs_nol_timer_arg { + struct ath_dfs *dfs; + u_int16_t delfreq; + u_int16_t delchwidth; +}; + +#ifdef WIN32 +#pragma pack(push, dfs_info, 1) +#endif +struct dfs_info { + int rn_use_nol; /* Use the NOL when radar found (default: TRUE) */ + u_int32_t rn_numradars; /* Number of different types of radars */ + u_int64_t rn_lastfull_ts; /* Last 64 bit timstamp from recv interrupt */ + u_int16_t rn_last_ts; /* last 15 bit ts from recv descriptor */ + u_int32_t rn_last_unique_ts; /* last unique 32 bit ts from recv descriptor */ + + u_int64_t rn_ts_prefix; /* Prefix to prepend to 15 bit recv ts */ + u_int32_t rn_numbin5radars; /* Number of bin5 radar pulses to search for */ + u_int32_t rn_fastdivGCval; /* Value of fast diversity gc limit from init file */ + int32_t rn_minrssithresh; /* Min rssi for all radar types */ + u_int32_t rn_maxpulsedur; /* Max pulse width in TSF ticks */ + + u_int8_t dfs_ext_chan_busy; + u_int64_t ext_chan_busy_ts; + + u_int64_t dfs_bin5_chirp_ts; + u_int8_t dfs_last_bin5_dur; +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_info) +#endif + +struct dfs_bin5elem { + u_int64_t be_ts; /* Timestamp for the bin5 element */ + u_int32_t be_rssi; /* Rssi for the bin5 element */ + u_int32_t be_dur; /* Duration of bin5 element */ +}; + +struct dfs_bin5radars { + struct dfs_bin5elem br_elems[DFS_MAX_B5_SIZE]; /* List of bin5 elems that fall + * within the time window */ + u_int32_t br_firstelem; /* Index of the first element */ + u_int32_t br_lastelem; /* Index of the last element */ + u_int32_t br_numelems; /* Number of elements in the delay line */ + struct dfs_bin5pulse br_pulse; /* Original info about bin5 pulse */ +}; + +struct dfs_stats { + u_int32_t num_radar_detects; /* total num. of radar detects */ + u_int32_t total_phy_errors; + u_int32_t owl_phy_errors; + u_int32_t pri_phy_errors; + u_int32_t ext_phy_errors; + u_int32_t dc_phy_errors; + u_int32_t early_ext_phy_errors; + u_int32_t bwinfo_errors; + u_int32_t datalen_discards; + u_int32_t rssi_discards; + u_int64_t last_reset_tstamp; +}; + +/* + * This is for debuggin DFS as console log interferes with (helps) + * radar detection +*/ + +#define DFS_EVENT_LOG_SIZE 256 +struct dfs_event_log { + u_int64_t ts; /* 64-bit full timestamp from interrupt time */ + u_int32_t diff_ts; /* diff timestamp */ + u_int8_t rssi; /* rssi of radar event */ + u_int8_t dur; /* duration of radar pulse */ +}; + + +#define ATH_DFS_RESET_TIME_S 7 +#define ATH_DFS_WAIT (60 + ATH_DFS_RESET_TIME_S) /* 60 seconds */ +#define ATH_DFS_WAIT_MS ((ATH_DFS_WAIT) * 1000) /*in MS*/ + +#define ATH_DFS_WEATHER_CHANNEL_WAIT_MIN 10 /*10 minutes*/ +#define ATH_DFS_WEATHER_CHANNEL_WAIT_S (ATH_DFS_WEATHER_CHANNEL_WAIT_MIN * 60) +#define ATH_DFS_WEATHER_CHANNEL_WAIT_MS ((ATH_DFS_WEATHER_CHANNEL_WAIT_S) * 1000) /*in MS*/ + +#define ATH_DFS_WAIT_POLL_PERIOD 2 /* 2 seconds */ +#define ATH_DFS_WAIT_POLL_PERIOD_MS ((ATH_DFS_WAIT_POLL_PERIOD) * 1000) /*in MS*/ +#define ATH_DFS_TEST_RETURN_PERIOD 2 /* 2 seconds */ +#define ATH_DFS_TEST_RETURN_PERIOD_MS ((ATH_DFS_TEST_RETURN_PERIOD) * 1000)/* n MS*/ +#define IS_CHANNEL_WEATHER_RADAR(chan) ((chan->ic_freq >= 5600) && (chan->ic_freq <= 5650)) + +#define DFS_DEBUG_TIMEOUT_S 30 // debug timeout is 30 seconds +#define DFS_DEBUG_TIMEOUT_MS (DFS_DEBUG_TIMEOUT_S * 1000) + + +#define RSSI_POSSIBLY_FALSE 50 +#define SEARCH_FFT_REPORT_PEAK_MAG_THRSH 40 + + + +#if 0 +struct ath_dfs_caps { + u_int32_t + ath_dfs_ext_chan_ok:1, /* Can radar be detected on the extension chan? */ + ath_dfs_combined_rssi_ok:1, /* Can use combined radar RSSI? */ + /* the following flag is used to indicate if radar detection scheme */ + /* should use enhanced chirping detection algorithm. This flag also */ + /* determines if certain radar data should be discarded to minimize */ + /* false detection of radar. */ + ath_dfs_use_enhancement:1, + ath_strong_signal_diversiry:1; + + /* + * goes with ath_strong_signal_diversiry: + * If we have fast diversity capability, read off + * Strong Signal fast diversity count set in the ini + * file, and store so we can restore the value when + * radar is disabled + */ + u_int32_t ath_fastdiv_val; +}; + +struct ath_dfs_radar_tab_info { + u_int32_t dfsdomain; + int numradars; + struct dfs_pulse *dfs_radars; + int numb5radars; + struct dfs_bin5pulse *b5pulses; + HAL_PHYERR_PARAM dfs_defaultparams; +}; +#endif +struct ath_dfs { + uint32_t dfs_debug_mask; /* current debug bitmask */ + int16_t dfs_curchan_radindex; /* cur. channel radar index */ + int16_t dfs_extchan_radindex; /* extension channel radar index */ + u_int32_t dfsdomain; /* cur. DFS domain */ + u_int32_t dfs_proc_phyerr; /* Flags for Phy Errs to process */ + struct ieee80211com *ic; + STAILQ_HEAD(,dfs_event) dfs_eventq; /* Q of free dfs event objects */ + dfsq_lock_t dfs_eventqlock; /* Lock for free dfs event list */ + STAILQ_HEAD(,dfs_event) dfs_radarq; /* Q of radar events */ + dfsq_lock_t dfs_radarqlock; /* Lock for dfs q */ + STAILQ_HEAD(,dfs_event) dfs_arq; /* Q of AR events */ + dfsq_lock_t dfs_arqlock; /* Lock for AR q */ + + struct dfs_ar_state dfs_ar_state; /* AR state */ + + /* dfs_radar - Per-Channel Radar detector state */ + struct dfs_state dfs_radar[DFS_NUM_RADAR_STATES]; + + /* dfs_radarf - One filter for each radar pulse type */ + struct dfs_filtertype *dfs_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 */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + struct dfs_nolelem *dfs_nol; /* Non occupancy list for radar */ + int dfs_nol_count; /* How many items? */ +#endif + + struct ath_dfs_phyerr_param dfs_defaultparams; /* Default phy params per radar state */ + struct dfs_stats ath_dfs_stats; /* DFS related stats */ + struct dfs_pulseline *pulses; /* pulse history */ + struct dfs_event *events; /* Events structure */ + + u_int32_t + ath_radar_tasksched:1, /* radar task is scheduled */ + ath_dfswait:1, /* waiting on channel for radar detect */ + ath_dfstest:1; /* Test timer in progress */ + struct ath_dfs_caps dfs_caps; + u_int8_t ath_dfstest_ieeechan; /* IEEE chan num to return to after + * a dfs mute test */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + u_int32_t ath_dfs_cac_time; /* CAC period */ + u_int32_t ath_dfstesttime; /* Time to stay off chan during dfs test */ + os_timer_t ath_dfswaittimer; /* dfs wait timer */ + os_timer_t ath_dfstesttimer; /* dfs mute test timer */ + os_timer_t ath_dfs_debug_timer; /* dfs debug timer */ + u_int8_t dfs_bangradar; +#endif + os_timer_t ath_dfs_task_timer; /* dfs wait timer */ + int dur_multiplier; + + u_int16_t ath_dfs_isdfsregdomain; /* true when we are DFS domain */ + int ath_dfs_false_rssi_thres; + int ath_dfs_peak_mag; + + struct dfs_event_log radar_log[DFS_EVENT_LOG_SIZE]; + int dfs_event_log_count; + int dfs_event_log_on; + int dfs_phyerr_count; /* same as number of PHY radar interrupts */ + int dfs_phyerr_reject_count; /* when TLV is supported, # of radar events ignored after TLV is parsed */ + int dfs_phyerr_queued_count; /* number of radar events queued for matching the filters */ + int dfs_phyerr_freq_min; + int dfs_phyerr_freq_max; + int dfs_phyerr_w53_counter; + int dfs_pri_multiplier; /* allow pulse if they are within multiple of PRI for the radar type */ + int ath_dfs_nol_timeout; +}; + +/* This should match the table from if_ath.c */ +enum { + ATH_DEBUG_DFS = 0x00000100, /* Minimal DFS debug */ + ATH_DEBUG_DFS1 = 0x00000200, /* Normal DFS debug */ + ATH_DEBUG_DFS2 = 0x00000400, /* Maximal DFS debug */ + ATH_DEBUG_DFS3 = 0x00000800, /* matched filterID display */ + + ATH_DEBUG_DFS_PHYERR = 0x00001000, /* phy error parsing */ + ATH_DEBUG_DFS_NOL = 0x00002000, /* NOL related entries */ + ATH_DEBUG_DFS_PHYERR_SUM = 0x00004000, /* PHY error summary */ + ATH_DEBUG_DFS_PHYERR_PKT = 0x00008000, /* PHY error payload */ + + ATH_DEBUG_DFS_BIN5 = 0x00010000, /* bin5 checks */ + ATH_DEBUG_DFS_BIN5_FFT = 0x00020000, /* bin5 FFT check */ + ATH_DEBUG_DFS_BIN5_PULSE = 0x00040000, /* bin5 pulse check */ +}; + +#define IS_CHAN_HT40(_c) IEEE80211_IS_CHAN_11N_HT40(_c) +#define IS_CHAN_HT40_PLUS(_c) IEEE80211_IS_CHAN_11N_HT40PLUS(_c) +#define IS_CHAN_HT40_MINUS(_c) IEEE80211_IS_CHAN_11N_HT40MINUS(_c) + +/* + * chirp notes! + * + * Pre-Sowl chips don't do FFT reports, so chirp pulses simply show up + * as long duration pulses. + * + * The bin5 checking code would simply look for a chirp pulse of the correct + * duration (within MIN_BIN5_DUR and MAX_BIN5_DUR) and add it to the "chirp" + * pattern. + * + * For Sowl and later, an FFT was done on longer duration frames. If those + * frames looked like a chirp, their duration was adjusted to fall within + * the chirp duration limits. If the pulse failed the chirp test (it had + * no FFT data or the FFT didn't meet the chirping requirements) then the + * pulse duration was adjusted to be greater than MAX_BIN5_DUR, so it + * would always fail chirp detection. + * + * This is pretty horrible. + * + * The eventual goal for chirp handling is thus: + * + * + In case someone ever wants to do chirp detection with this code on + * chips that don't support chirp detection, you can still do it based + * on pulse duration. That's your problem to solve. + * + * + For chips that do hardware chirp detection or FFT, the "do_check_chirp" + * bit should be set. + * + * + Then, either is_hw_chirp or is_sw_chirp is set, indicating that + * the hardware or software post-processing of the chirp event found + * that indeed it was a chirp. + * + * + Finally, the bin5 code should just check whether the chirp bits are + * set and behave appropriately, falling back onto the duration checks + * if someone wishes to use this on older hardware (or with disabled + * FFTs, for whatever reason.) + */ +/* + * XXX TODO: + * + * + add duration in uS and raw duration, so the PHY error parsing + * code is responsible for doing the duration calculation; + * + add ts in raw and corrected, so the PHY error parsing + * code is responsible for doing the offsetting, not the radar + * event code. + */ +struct dfs_phy_err { + u_int64_t fulltsf; /* 64-bit TSF as read from MAC */ + + uint32_t is_pri:1, /* detected on primary channel */ + is_ext:1, /* detected on extension channel */ + is_dc:1, /* detected at DC */ + is_early:1, /* early detect */ + do_check_chirp:1, /* whether to check hw_chirp/sw_chirp */ + is_hw_chirp:1, /* hardware-detected chirp */ + is_sw_chirp:1; /* software detected chirp */ + + u_int32_t rs_tstamp; /* 32 bit TSF from RX descriptor (event) */ + u_int32_t freq; /* Centre frequency of event - KHz */ + u_int32_t freq_lo; /* Lower bounds of frequency - KHz */ + u_int32_t freq_hi; /* Upper bounds of frequency - KHz */ + + u_int8_t rssi; /* pulse RSSI */ + u_int8_t dur; /* pulse duration, raw (not uS) */ +}; + +/* Attach, detach, handle ioctl prototypes */ + +int dfs_get_thresholds(struct ieee80211com *ic, + struct ath_dfs_phyerr_param *param); +int dfs_set_thresholds(struct ieee80211com *ic, + const u_int32_t threshtype, const u_int32_t value); + +/* PHY error and radar event handling */ +int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan); + +/* Non occupancy (NOL) handling prototypes */ +void dfs_nol_addchan(struct ath_dfs *dfs, struct ieee80211_channel *chan, u_int32_t dfs_nol_timeout); +void dfs_get_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int *nchan); +void dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan); +void dfs_nol_update(struct ath_dfs *dfs); +void dfs_nol_timer_cleanup(struct ath_dfs *dfs); + +/* FCC Bin5 detection prototypes */ +int dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re, + struct dfs_bin5radars *br); +int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, + struct dfs_event *re, u_int64_t thists); +int dfs_bin5_check(struct ath_dfs *dfs); +int dfs_check_chirping(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, int is_ctl, + int is_ext, int *slope, int *is_dc); +u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, u_int32_t diff_ts, u_int8_t old_dur); +u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, u_int32_t diff_ts, u_int8_t old_dur); +int dfs_get_random_bin5_dur(struct ath_dfs *dfs, u_int64_t tstamp); + +/* Debug prototypes */ +void dfs_print_delayline(struct ath_dfs *dfs, struct dfs_delayline *dl); +void dfs_print_nol(struct ath_dfs *dfs); +void dfs_print_filters(struct ath_dfs *dfs); +void dfs_print_activity(struct ath_dfs *dfs); +OS_TIMER_FUNC(dfs_debug_timeout); +void dfs_print_filter(struct ath_dfs *dfs, struct dfs_filter *rf); + +/* Misc prototypes */ +u_int32_t dfs_round(int32_t val); +struct dfs_state* dfs_getchanstate(struct ath_dfs *dfs, u_int8_t *index, int ext_ch_flag); + +/* Reset and init data structures */ + +int dfs_init_radar_filters( struct ieee80211com *ic, struct ath_dfs_radar_tab_info *radar_info); +void dfs_reset_alldelaylines(struct ath_dfs *dfs); +void dfs_reset_delayline(struct dfs_delayline *dl); +void dfs_reset_filter_delaylines(struct dfs_filtertype *dft); +void dfs_reset_radarq(struct ath_dfs *dfs); + +/* Detection algorithm prototypes */ +void dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_event *re, u_int32_t deltaT, u_int64_t this_ts); + +int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t dur, int ext_chan_flag); +int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t deltaT, u_int32_t dur, int ext_chan_flag); + +int dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_delayline *dl, u_int32_t score, + u_int32_t refpri, u_int32_t refdur, int ext_chan_flag, int fundamentalpri); +int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t deltaT, u_int32_t width); +/* False detection reduction */ +int dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, + int is_fixed_pattern); +int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, + int is_extchan_detect); + +/* AR related prototypes */ + +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void dfs_process_ar_event(struct ath_dfs *dfs, struct ieee80211_channel *chan); + */ +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void ath_ar_disable(struct ath_dfs *dfs); + */ +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void ath_ar_enable(struct ath_dfs *dfs); + */ +void dfs_reset_ar(struct ath_dfs *dfs); +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void dfs_reset_arq(struct ath_dfs *dfs); + */ + + +struct ieee80211_channel *ieee80211_get_extchan(struct ieee80211com *ic); + +#endif /* _DFS_H_ */ diff --git a/CORE/SERVICES/DFS/src/dfs_bindetects.c b/CORE/SERVICES/DFS/src/dfs_bindetects.c new file mode 100644 index 000000000000..a01285e6207b --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_bindetects.c @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_bindetects.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/*TO DO DFS removing +#include <ieee80211_var.h> +*/ +#ifdef ATH_SUPPORT_DFS + +int +dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, u_int32_t dur, int ext_chan_flag) +{ + struct dfs_pulseline *pl = dfs->pulses; + int i, n, refpri, primargin, numpulses=0; + u_int64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, window_start, window_end; + u_int32_t index, next_index, deltadur; + + /* For fixed pattern types, rf->rf_patterntype=1*/ + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype==1)); + + refpri = (rf->rf_minpri + rf->rf_maxpri)/2; + index = pl->pl_lastelem; + end_ts = pl->pl_elems[index].p_time; + start_ts = end_ts - (refpri*rf->rf_numpulses); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "lastelem ts=%llu start_ts=%llu, end_ts=%llu\n", + (unsigned long long) pl->pl_elems[index].p_time, + (unsigned long long) start_ts, + (unsigned long long) end_ts); + + /* find the index of first element in our window of interest */ + for(i=0;i<pl->pl_numelems;i++) { + index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; + if(pl->pl_elems[index].p_time >= start_ts ) + continue; + else { + index = (index) & DFS_MAX_PULSE_BUFFER_MASK; + break; + } + } + for (n=0;n<=rf->rf_numpulses; n++) { + window_start = (start_ts + (refpri*n))-(primargin+n); + window_end = window_start + 2*(primargin+n); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "window_start %u window_end %u \n", + (u_int32_t)window_start, (u_int32_t)window_end); + for(i=0;i<pl->pl_numelems;i++) { + prev_event_ts = pl->pl_elems[index].p_time; + index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; + event_ts = pl->pl_elems[index].p_time; + next_index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; + next_event_ts = pl->pl_elems[next_index].p_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "ts %u \n", (u_int32_t)event_ts); + if( (event_ts <= window_end) && (event_ts >= window_start)){ + deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur); + if( (pl->pl_elems[index].p_dur == 1) || + ((dur != 1) && (deltadur <= 2))) { + numpulses++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numpulses %u \n", numpulses); + break; + } + } + else if( event_ts > window_end) { + index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; + break; + } + else if( event_ts == prev_event_ts) { + if( ((next_event_ts - event_ts) > refpri) || + ((next_event_ts - event_ts) == 0)) { + deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur); + if( (pl->pl_elems[index].p_dur == 1) || + ((pl->pl_elems[index].p_dur != 1) && (deltadur <= 2))) { + numpulses++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "zero PRI: numpulses %u \n", numpulses); + break; + } + } + } + } + } + if (numpulses >= dfs_get_filter_threshold(dfs, rf, ext_chan_flag)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s FOUND filterID=%u numpulses=%d unadj thresh=%d\n", __func__, rf->rf_pulseid, numpulses, rf->rf_threshold); + return 1; + } + else + return 0; +} + +void +dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, + u_int32_t deltaT, u_int64_t this_ts) +{ + u_int32_t index,n, window; + struct dfs_delayline *dl; + + dl = &rf->rf_dl; + /* Circular buffer of size 2^n */ + index = (dl->dl_lastelem + 1) & DFS_MAX_DL_MASK; + //if ((dl->dl_numelems+1) == DFS_MAX_DL_SIZE) + if ((dl->dl_numelems) == DFS_MAX_DL_SIZE) + dl->dl_firstelem = (dl->dl_firstelem + 1) & DFS_MAX_DL_MASK; + else + dl->dl_numelems++; + dl->dl_lastelem = index; + dl->dl_elems[index].de_time = deltaT; + dl->dl_elems[index].de_ts = this_ts; + window = deltaT; + dl->dl_elems[index].de_dur = re->re_dur; + dl->dl_elems[index].de_rssi = re->re_rssi; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s: adding: filter id %d, dur=%d, rssi=%d, ts=%llu\n", + __func__, + rf->rf_pulseid, + re->re_dur, + re->re_rssi, + (unsigned long long int) this_ts); + + for (n=0;n<dl->dl_numelems-1; n++) { + index = (index-1) & DFS_MAX_DL_MASK; + /* + * calculate window based on full time stamp instead of deltaT + * deltaT (de_time) may result in incorrect window value + */ + window = (u_int32_t) (this_ts - dl->dl_elems[index].de_ts); + + if (window > rf->rf_filterlen) { + dl->dl_firstelem = (index+1) & DFS_MAX_DL_MASK; + dl->dl_numelems = n+1; + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "dl firstElem = %d lastElem = %d\n",dl->dl_firstelem, + dl->dl_lastelem); +} + + +int +dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, u_int32_t deltaT, + u_int32_t width, int ext_chan_flag) +{ + u_int32_t refpri, refdur, searchpri, deltapri,deltapri_2,deltapri_3, averagerefpri; + u_int32_t n, i, primargin, durmargin, highscore, highscoreindex; + int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0; + struct dfs_delayline *dl; + u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff; + int numpulses=0; + int lowprichk=3, pri_match=0; + + dl = &rf->rf_dl; + if( dl->dl_numelems < (rf->rf_threshold-1)) { + return 0; + } + if( deltaT > rf->rf_filterlen) + return 0; + + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype==1)); + + + if(rf->rf_maxdur < 10) { + durmargin = 4; + } + else { + durmargin = 6; + } + + if( rf->rf_patterntype == 1 ){ + found = dfs_bin_fixedpattern_check(dfs, rf, width, ext_chan_flag); + if(found) { + dl->dl_numelems = 0; + } + return found; + } + + OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE); + /* find out the lowest pri */ + for (n=0;n<dl->dl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) + continue; + else if(refpri < lowpri) { + lowpri = dl->dl_elems[delayindex].de_time; + lowpriindex = n; + } + } + /* find out the each delay element's pri score */ + for (n=0;n<dl->dl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) + continue; + if (refpri < rf->rf_maxpri) { // use only valid PRI range for high score + for (i=0;i<dl->dl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + deltapri_2 = DFS_DIFF(searchpri, 2*refpri); + deltapri_3 = DFS_DIFF(searchpri, 3*refpri); + if (rf->rf_ignore_pri_window==2) { + pri_match = ((deltapri < primargin) || (deltapri_2 < primargin) || (deltapri_3 < primargin)); + } else { + pri_match = (deltapri < primargin); + } + + if (pri_match) + score[n]++; + } + } else { + score[n] = 0; + } + if( score[n] > rf->rf_threshold) { + /* we got the most possible candidate, + * no need to continue further */ + break; + } + } + /* find out the high scorer */ + highscore = 0; + highscoreindex = 0; + for (n=0;n<dl->dl_numelems; n++) { + if( score[n] > highscore) { + highscore = score[n]; + highscoreindex = n; + } + else if( score[n] == highscore ) { + /*more than one pri has highscore take the least pri */ + delayindex = (dl->dl_firstelem + highscoreindex) & DFS_MAX_DL_MASK; + dindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + if( dl->dl_elems[dindex].de_time <= + dl->dl_elems[delayindex].de_time ) { + highscoreindex = n; + } + } + } + /* find the average pri of pulses around the pri of highscore or + * the pulses around the lowest pri */ + if (rf->rf_ignore_pri_window > 0) { + lowprichk = (rf->rf_threshold >> 1)+1; + } else { + lowprichk = 3; + } + + if( highscore < lowprichk) { + scoreindex = lowpriindex; + } + else { + scoreindex = highscoreindex; + } + /* We got the possible pri, save its parameters as reference */ + delayindex = (dl->dl_firstelem + scoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + averagerefpri = 0; + + if (rf->rf_fixed_pri_radar_pulse) { + refpri = (rf->rf_minpri + rf->rf_maxpri)/2; + } + + numpulses = dfs_bin_pri_check(dfs, rf, dl, score[scoreindex], refpri, + refdur, ext_chan_flag, refpri); + if (numpulses >= dfs_get_filter_threshold(dfs, rf, ext_chan_flag)) { + found = 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "ext_flag=%d MATCH filter=%u numpulses=%u thresh=%u refdur=%d refpri=%d primargin=%d\n", ext_chan_flag, rf->rf_pulseid, numpulses,rf->rf_threshold, refdur, refpri, primargin); + dfs_print_delayline(dfs, &rf->rf_dl); + dfs_print_filter(dfs, rf); + } + return found; +} + +int +dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_delayline *dl, u_int32_t score, u_int32_t refpri, + u_int32_t refdur, int ext_chan_flag, int fundamentalpri) +{ + u_int32_t searchpri, searchdur, searchrssi, deltapri = 0,deltapri1 = 0, deltapri2 = 0, deltadur, averagerefpri=0,MatchCount = 0; + u_int32_t delta_ts_variance, delta_time_stamps, prev_good_timestamp=0; + int delayindex, dindex; + u_int32_t i, j=0, primargin, durmargin, highscore=score, highscoreindex=0; + int numpulses=1; //first pulse in the burst is most likely being filtered out based on maxfilterlen + int priscorechk=1,numpulsetochk=2,primatch=0; + + //Use the adjusted PRI margin to reduce false alarms + /* For non fixed pattern types, rf->rf_patterntype=0*/ + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype==1)); + + if ( (refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri) ) { + numpulses = 0; + return numpulses; + } + + + if(rf->rf_maxdur < 10) { + durmargin = 4; + } else { + durmargin = 6; + } + + if ((!rf->rf_fixed_pri_radar_pulse)) { + if (rf->rf_ignore_pri_window==1) { + priscorechk = (rf->rf_threshold >> 1); + } else { + priscorechk = 1; + } + + MatchCount = 0; + if( score > priscorechk) { + for (i=0;i<dl->dl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + if( deltapri < primargin) { + averagerefpri += searchpri; + MatchCount++; + } + } + if (rf->rf_patterntype != 2) { + if (MatchCount > 0) + refpri = (averagerefpri/MatchCount); //average + } else { + refpri = (averagerefpri/score); + } + } + } + /* Note: Following primultiple calculation should be done once per filter + * during initialization stage (dfs_attach) and stored in its array + * atleast for fixed frequency types like FCC Bin1 to save some CPU cycles. + * multiplication, devide operators in the following code are left as it is + * for readability hoping the complier will use left/right shifts wherever possible + */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "refpri = %d high score = %d index = %d numpulses = %d\n", + refpri, highscore, highscoreindex, numpulses); + /* Count the other delay elements that have pri and dur with in the + * acceptable range from the reference one */ + for (i=0; i<dl->dl_numelems; i++) { + delayindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[delayindex].de_time; + if( searchpri == 0) { + /* This events PRI is zero, take it as a + * valid pulse but decrement next event's PRI by refpri + */ + dindex = (delayindex+1)& DFS_MAX_DL_MASK; + dl->dl_elems[dindex].de_time -= refpri; + searchpri = refpri; + } + searchdur = dl->dl_elems[delayindex].de_dur; + searchrssi = dl->dl_elems[delayindex].de_rssi; + deltadur = DFS_DIFF(searchdur, refdur); + deltapri = DFS_DIFF(searchpri, refpri); + + //deltapri3 = DFS_DIFF(searchpri, 3 * refpri); + primatch=0; + + if ((rf->rf_ignore_pri_window>0) && (rf->rf_patterntype!=2)) { + for (j=0;j<rf->rf_numpulses;j++){ + deltapri1 = DFS_DIFF(searchpri, (j+1)*refpri); + if (deltapri1 < (2*primargin)) { + primatch = 1; + break; + } + } + } else { + if (( deltapri1 < primargin) || ( deltapri2 < primargin)) { + primatch = 1; + } + } + + if ( primatch && ( deltadur < durmargin) ) { + if ( (numpulses == 1) ) { + numpulses++; + } else { + delta_time_stamps = dl->dl_elems[delayindex].de_ts - prev_good_timestamp; + if ((rf->rf_ignore_pri_window>0)) { + numpulsetochk = rf->rf_numpulses; + + if ((rf->rf_patterntype==2) && (fundamentalpri<refpri+100)) { + numpulsetochk = 4; + } + } else { + numpulsetochk = 4; + } + for (j = 0; j < numpulsetochk; j++){ + delta_ts_variance = DFS_DIFF(delta_time_stamps, ((j+1)*fundamentalpri)); + if ( delta_ts_variance < (2*(j+1)*primargin) ) { + numpulses++; + if (rf->rf_ignore_pri_window>0) { + break; + } + } + } + } + prev_good_timestamp = dl->dl_elems[delayindex].de_ts; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "rf->minpri=%d rf->maxpri=%d searchpri = %d index = %d numpulses = %d deltapri=%d j=%d\n", + rf->rf_minpri, rf->rf_maxpri, searchpri, i, numpulses, deltapri, j); + } + + } + return numpulses; +} +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/DFS/src/dfs_debug.c b/CORE/SERVICES/DFS/src/dfs_debug.c new file mode 100644 index 000000000000..5164f737d22b --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_debug.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_debug.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifdef ATH_SUPPORT_DFS + +void +dfs_print_delayline(struct ath_dfs *dfs, struct dfs_delayline *dl) +{ + int i=0,index; + struct dfs_delayelem *de; + + index = dl->dl_lastelem; + for (i=0; i<dl->dl_numelems; i++) { + de = &dl->dl_elems[index]; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "Elem %d: ts = %u (0x%x) dur=%u\n",i, + de->de_time, de->de_time, de->de_dur); + index = (index - 1)& DFS_MAX_DL_MASK; + } +} +void +dfs_print_filter(struct ath_dfs *dfs, struct dfs_filter *rf) +{ + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "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", + 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_filters(struct ath_dfs *dfs) +{ + struct dfs_filtertype *ft = NULL; + struct dfs_filter *rf; + int i,j; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); + return; + } + for (i=0; i<DFS_MAX_RADAR_TYPES; i++) { + if (dfs->dfs_radarf[i] != NULL) { + 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); + 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, + 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) +{ + int chan_busy=0, ext_chan_busy=0; + u_int32_t rxclear=0, rxframe=0, txframe=0, cycles=0; + + cycles = dfs->ic->ic_get_mib_cycle_counts_pct(dfs->ic, &rxclear, &rxframe, &txframe); + chan_busy = cycles; + + ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS,"cycles=%d rxclear=%d rxframe=%d" + " txframe=%d extchanbusy=%d\n", cycles, rxclear, + rxframe, txframe, ext_chan_busy); + return; +} + +/* + * XXX migrate this to use ath_dfs as the arg, not ieee80211com! + */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY +OS_TIMER_FUNC(dfs_debug_timeout) +{ + struct ieee80211com *ic; + struct ath_dfs* dfs; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + + dfs = (struct ath_dfs *)ic->ic_dfs; + + dfs_print_activity(dfs); + + OS_SET_TIMER(&dfs->ath_dfs_debug_timer, DFS_DEBUG_TIMEOUT_MS); +} +#endif + +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c b/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c new file mode 100644 index 000000000000..983905b73740 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_fcc_bin5.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifdef ATH_SUPPORT_DFS + +/* + * Reject the pulse if: + * + It's outside the RSSI threshold; + * + It's outside the pulse duration; + * + It's been verified by HW/SW chirp checking + * and neither of those found a chirp. + */ +int +dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re, + struct dfs_bin5radars *br) +{ + int b5_rssithresh = br->br_pulse.b5_rssithresh; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_PULSE, + "%s: re_dur=%d, rssi=%d, check_chirp=%d, " + "hw_chirp=%d, sw_chirp=%d\n", + __func__, + (int) re->re_dur, + (int) re->re_rssi, + !! (re->re_flags & DFS_EVENT_CHECKCHIRP), + !! (re->re_flags & DFS_EVENT_HW_CHIRP), + !! (re->re_flags & DFS_EVENT_SW_CHIRP)); + + /* + * If the sw/hw chirp detection says to fail the pulse, + * do so. + */ + if (DFS_EVENT_NOTCHIRP(re)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s: rejecting chirp: ts=%llu, dur=%d, rssi=%d " + "checkchirp=%d, hwchirp=%d, swchirp=%d\n", + __func__, + (unsigned long long) re->re_full_ts, + (int) re->re_dur, + (int) re->re_rssi, + !! (re->re_flags & DFS_EVENT_CHECKCHIRP), + !! (re->re_flags & DFS_EVENT_HW_CHIRP), + !! (re->re_flags & DFS_EVENT_SW_CHIRP)); + return (0); + } + + /* Adjust the filter threshold for rssi in non TURBO mode */ + if( ! (dfs->ic->ic_curchan->ic_flags & CHANNEL_TURBO)) + b5_rssithresh += br->br_pulse.b5_rssimargin; + + /* + * Check if the pulse is within duration and rssi + * thresholds. + */ + if ((re->re_dur >= br->br_pulse.b5_mindur) && + (re->re_dur <= br->br_pulse.b5_maxdur) && + (re->re_rssi >= b5_rssithresh)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s: dur=%d, rssi=%d - adding!\n", + __func__, (int) re->re_dur, (int) re->re_rssi); + return (1); + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s: too low to be Bin5 pulse tsf=%llu, dur=%d, rssi=%d\n", + __func__, + (unsigned long long) re->re_full_ts, + (int) re->re_dur, + (int) re->re_rssi); + + return (0); +} + + +int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, + struct dfs_event *re, u_int64_t thists) +{ + u_int32_t index,stop; + u_int64_t tsDelta; + + /* Check if this pulse is a valid pulse in terms of repetition, + * if not, return without adding it to the queue. + * PRI : Pulse Repitetion Interval + * BRI : Burst Repitetion Interval */ + if( br->br_numelems != 0){ + index = br->br_lastelem; + tsDelta = thists - br->br_elems[index].be_ts; + if( (tsDelta < DFS_BIN5_PRI_LOWER_LIMIT) || + ( (tsDelta > DFS_BIN5_PRI_HIGHER_LIMIT) && + (tsDelta < DFS_BIN5_BRI_LOWER_LIMIT))) { + return 0; + } + } + /* Circular buffer of size 2^n */ + index = (br->br_lastelem +1) & DFS_MAX_B5_MASK; + br->br_lastelem = index; + if (br->br_numelems == DFS_MAX_B5_SIZE) + br->br_firstelem = (br->br_firstelem+1)&DFS_MAX_B5_MASK; + else + br->br_numelems++; + br->br_elems[index].be_ts = thists; + br->br_elems[index].be_rssi = re->re_rssi; + br->br_elems[index].be_dur = re->re_dur; /* please note that this is in u-sec */ + stop = 0; + index = br->br_firstelem; + while ((!stop) && (br->br_numelems-1) > 0) { + if ((thists - br->br_elems[index].be_ts) > + ((u_int64_t) br->br_pulse.b5_timewindow)) { + br->br_numelems--; + br->br_firstelem = (br->br_firstelem +1) & DFS_MAX_B5_MASK; + index = br->br_firstelem; + } else + stop = 1; + } + return 1; +} + +/* + * If the dfs structure is NULL (which should be illegal if everyting is working + * properly, then signify that a bin5 radar was found + */ + +int +dfs_bin5_check(struct ath_dfs *dfs) +{ + struct dfs_bin5radars *br; + int index[DFS_MAX_B5_SIZE]; + u_int32_t n = 0, i = 0, i1 = 0, this = 0, prev = 0, rssi_diff = 0, width_diff = 0, bursts= 0; + u_int32_t total_diff=0, average_diff=0, total_width=0, average_width=0, numevents=0; + u_int64_t pri; + + + if (dfs == NULL) { + DFS_PRINTK("%s: ic_dfs is NULL\n", __func__); + return 1; + } + for (n=0;n<dfs->dfs_rinfo.rn_numbin5radars; n++) { + br = &(dfs->dfs_b5radars[n]); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "Num elems = %d\n", br->br_numelems); + + /* find a valid bin 5 pulse and use it as reference */ + for(i1=0;i1 < br->br_numelems; i1++) { + this = ((br->br_firstelem +i1) & DFS_MAX_B5_MASK); + if ((br->br_elems[this].be_dur >= MIN_BIN5_DUR_MICROSEC) && + (br->br_elems[this].be_dur <= MAX_BIN5_DUR_MICROSEC)) { + break; + } + } + + prev = this; + for(i = i1 + 1; i < br->br_numelems; i++){ + this = ((br->br_firstelem +i) & DFS_MAX_B5_MASK); + + /* first make sure it is a bin 5 pulse by checking the duration */ + if ((br->br_elems[this].be_dur < MIN_BIN5_DUR_MICROSEC) || (br->br_elems[this].be_dur > MAX_BIN5_DUR_MICROSEC)) { + continue; + } + + /* Rule 1: 1000 <= PRI <= 2000 + some margin */ + if( br->br_elems[this].be_ts >= br->br_elems[prev].be_ts ) { + pri = br->br_elems[this].be_ts - br->br_elems[prev].be_ts; + } + else {//roll over case + //pri = (0xffffffffffffffff - br->br_elems[prev].be_ts) + br->br_elems[this].be_ts; + pri = br->br_elems[this].be_ts; + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + " pri=%llu this.ts=%llu this.dur=%d this.rssi=%d prev.ts=%llu\n", + (unsigned long long)pri, + (unsigned long long)br->br_elems[this].be_ts, + (int) br->br_elems[this].be_dur, + (int) br->br_elems[this].be_rssi, + (unsigned long long)br->br_elems[prev].be_ts); + if(( (pri >= DFS_BIN5_PRI_LOWER_LIMIT) && (pri <= DFS_BIN5_PRI_HIGHER_LIMIT))) { //pri: pulse repitition interval in us + /* Rule 2: pulse width of the pulses in the burst should be same (+/- margin) */ + if( br->br_elems[this].be_dur >= br->br_elems[prev].be_dur) { + width_diff = br->br_elems[this].be_dur - br->br_elems[prev].be_dur; + } + else { + width_diff = br->br_elems[prev].be_dur - br->br_elems[this].be_dur; + } + if( width_diff <= DFS_BIN5_WIDTH_MARGIN ) { + /* Rule 3: RSSI of the pulses in the burst should be same (+/- margin) */ + if( br->br_elems[this].be_rssi >= br->br_elems[prev].be_rssi) { + rssi_diff = br->br_elems[this].be_rssi - br->br_elems[prev].be_rssi; + } + else { + rssi_diff = br->br_elems[prev].be_rssi - br->br_elems[this].be_rssi; + } + if( rssi_diff <= DFS_BIN5_RSSI_MARGIN ) { + bursts++; + /* Save the indexes of this pair for later width variance check */ + if( numevents >= 2 ) { + /* make sure the event is not duplicated, + * possible in a 3 pulse burst */ + if( index[numevents-1] != prev) { + index[numevents++] = prev; + } + } + else { + index[numevents++] = prev; } + index[numevents++] = this; + } else { + DFS_DPRINTK(dfs, + ATH_DEBUG_DFS_BIN5, + "%s %d Bin5 rssi_diff=%d\n", + __func__, __LINE__, rssi_diff); + } + } else { + DFS_DPRINTK(dfs, + ATH_DEBUG_DFS_BIN5, + "%s %d Bin5 width_diff=%d\n", + __func__, __LINE__, + width_diff); + } + } else if ((pri >= DFS_BIN5_BRI_LOWER_LIMIT) && + (pri <= DFS_BIN5_BRI_UPPER_LIMIT)) { + // check pulse width to make sure it is in range of bin 5 + //if ((br->br_elems[this].be_dur >= MIN_BIN5_DUR_MICROSEC) && (br->br_elems[this].be_dur <= MAX_BIN5_DUR_MICROSEC)) { + bursts++; + //} + } else{ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s %d Bin5 PRI check fail pri=%llu\n", + __func__, __LINE__, (unsigned long long)pri); + } + prev = this; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "bursts=%u numevents=%u\n", bursts, numevents); + if ( bursts >= br->br_pulse.b5_threshold) { + if( (br->br_elems[br->br_lastelem].be_ts - br->br_elems[br->br_firstelem].be_ts) < 3000000 ) { + return 0; + } + else { + /* + * don't do this check since not all the cases have this kind of burst width variation. + * + for (i=0; i<bursts; i++){ + total_width += br->br_elems[index[i]].be_dur; + } + average_width = total_width/bursts; + for (i=0; i<bursts; i++){ + total_diff += DFS_DIFF(br->br_elems[index[i]].be_dur, average_width); + } + average_diff = total_diff/bursts; + if( average_diff > DFS_BIN5_WIDTH_MARGIN ) { + return 1; + } else { + + DFS_DPRINTK(ic, ATH_DEBUG_DFS_BIN5, "bursts=%u numevents=%u total_width=%d average_width=%d total_diff=%d average_diff=%d\n", bursts, numevents, total_width, average_width, total_diff, average_diff); + + } + */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "bursts=%u numevents=%u total_width=%d average_width=%d total_diff=%d average_diff=%d\n", bursts, numevents, total_width, average_width, total_diff, average_diff); + DFS_PRINTK("bin 5 radar detected, bursts=%d\n", bursts); + return 1; + } + } + } + + return 0; +} + + +/* Return TRUE if chirping pulse, FALSE if not. + Decision is made based on processing the FFT data included with the PHY error. + Calculate the slope using the maximum bin index reported in the FFT data. + Calculate slope between FFT packet 0 and packet n-1. Also calculate slope between + packet 1 and packet n. + If a pulse is chirping, a slope of 5 and greater is seen. + Non-chirping pulses have slopes of 0, 1, 2 or 3. +*/ + +/* + * Chirp detection for Sowl/Howl. + */ +static int +dfs_check_chirping_sowl(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, int is_ctl, int is_ext, int *slope, int *is_dc) +{ +#define FFT_LEN 70 +#define FFT_LOWER_BIN_MAX_INDEX_BYTE 66 +#define FFT_UPPER_BIN_MAX_INDEX_BYTE 69 +#define MIN_CHIRPING_SLOPE 4 + int is_chirp=0; + int p, num_fft_packets=0; + int ctl_slope=0, ext_slope=0; + int ctl_high0, ctl_low0, ctl_slope0=0, ext_high0, ext_low0, ext_slope0=0; + int ctl_high1, ctl_low1, ctl_slope1=0, ext_high1, ext_low1, ext_slope1=0; + u_int8_t *fft_data_ptr; + + *slope = 0; + *is_dc = 0; + + num_fft_packets = datalen / FFT_LEN; + fft_data_ptr = ((u_int8_t*)buf); + + /* DEBUG - Print relevant portions of the FFT data*/ + for (p=0; p < num_fft_packets; p++) { + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "fft_data_ptr=0x%p\t", fft_data_ptr); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "[66]=%d [69]=%d\n", + *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2, + *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2); + + fft_data_ptr += FFT_LEN; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "datalen=%d num_fft_packets=%d\n", datalen, num_fft_packets); + + /* There is not enough FFT data to figure out whether the pulse is chirping or not*/ + if (num_fft_packets < 4) { + return 0; + } + + fft_data_ptr = ((u_int8_t*)buf); + + if (is_ctl) { + + fft_data_ptr = ((u_int8_t*)buf); + ctl_low0 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + fft_data_ptr += FFT_LEN; + ctl_low1 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + + // last packet with first packet + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 1)); + ctl_high1 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + + // second last packet with 0th packet + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 2)); + ctl_high0 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + + ctl_slope0 = ctl_high0 - ctl_low0; + if (ctl_slope0 < 0) ctl_slope0 *= (-1); + + ctl_slope1 = ctl_high1 - ctl_low1; + if (ctl_slope1 < 0) ctl_slope1 *= (-1); + + ctl_slope = ((ctl_slope0 > ctl_slope1) ? ctl_slope0: ctl_slope1); + *slope = ctl_slope; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "ctl_slope0=%d ctl_slope1=%d ctl_slope=%d\n", + ctl_slope0, ctl_slope1, ctl_slope); + + } else if (is_ext) { + + fft_data_ptr = ((u_int8_t*)buf); + ext_low0 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + + fft_data_ptr += FFT_LEN; + ext_low1 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 1)); + ext_high1 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 2)); + ext_high0 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + + ext_slope0 = ext_high0 - ext_low0; + if (ext_slope0 < 0) ext_slope0 *= (-1); + + ext_slope1 = ext_high1 - ext_low1; + if (ext_slope1 < 0) ext_slope1 *= (-1); + + ext_slope = ((ext_slope0 > ext_slope1) ? ext_slope0: ext_slope1); + *slope = ext_slope; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT | ATH_DEBUG_DFS_BIN5, + "ext_slope0=%d ext_slope1=%d ext_slope=%d\n", + ext_slope0, ext_slope1, ext_slope); + } else + return 0; + + if ((ctl_slope >= MIN_CHIRPING_SLOPE) || (ext_slope >= MIN_CHIRPING_SLOPE)) { + is_chirp = 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5 | ATH_DEBUG_DFS_BIN5_FFT | + ATH_DEBUG_DFS_PHYERR_SUM, + "is_chirp=%d is_dc=%d\n", is_chirp, *is_dc); + } + return is_chirp; + +#undef FFT_LEN +#undef FFT_LOWER_BIN_MAX_INDEX_BYTE +#undef FFT_UPPER_BIN_MAX_INDEX_BYTE +#undef MIN_CHIRPING_SLOPE +} + +/* + * Merlin (and Osprey, etc) chirp radar chirp detection. + */ +static int +dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + int is_ctl, int is_ext, int *slope, int *is_dc) +{ +#define ABS_DIFF(_x, _y) ((int)_x > (int)_y ? (int)_x - (int)_y : (int)_y - (int)_x) +#define ABS(_x) ((int)_x > 0 ? (int)_x : - (int)_x) + +#define DELTA_STEP 1 /* This should be between 1 and 3. Default is 1. */ +#define NUM_DIFFS 3 /* Number of Diffs to compute. valid range is 2-4 */ +#define MAX_DIFF 2 /* Threshold for difference of delta peaks */ +#define BIN_COUNT_MAX 6 /* Max. number of strong bins for narrow band */ + + +/* + * Dynamic 20/40 mode FFT packet format related definition + */ + +#define NUM_FFT_BYTES_HT40 70 +#define NUM_BIN_BYTES_HT40 64 +#define NUM_SUBCHAN_BINS_HT40 64 +#define LOWER_INDEX_BYTE_HT40 66 +#define UPPER_INDEX_BYTE_HT40 69 +#define LOWER_WEIGHT_BYTE_HT40 64 +#define UPPER_WEIGHT_BYTE_HT40 67 +#define LOWER_MAG_BYTE_HT40 65 +#define UPPER_MAG_BYTE_HT40 68 + +/* + * Static 20 mode FFT packet format related definition + */ + +#define NUM_FFT_BYTES_HT20 31 +#define NUM_BIN_BYTES_HT20 28 +#define NUM_SUBCHAN_BINS_HT20 56 +#define LOWER_INDEX_BYTE_HT20 30 +#define UPPER_INDEX_BYTE_HT20 30 +#define LOWER_WEIGHT_BYTE_HT20 28 +#define UPPER_WEIGHT_BYTE_HT20 28 +#define LOWER_MAG_BYTE_HT20 29 +#define UPPER_MAG_BYTE_HT20 29 + + int num_fft_packets; /* number of FFT packets reported to software */ + int num_fft_bytes; + int num_bin_bytes; + int num_subchan_bins; + int lower_index_byte; + int upper_index_byte; + int lower_weight_byte; + int upper_weight_byte; + int lower_mag_byte; + int upper_mag_byte; + + int max_index_lower [DELTA_STEP + NUM_DIFFS]; + int max_index_upper [DELTA_STEP + NUM_DIFFS]; + int max_mag_lower [DELTA_STEP + NUM_DIFFS]; + int max_mag_upper [DELTA_STEP + NUM_DIFFS]; + int bin_wt_lower [DELTA_STEP + NUM_DIFFS]; + int bin_wt_upper [DELTA_STEP + NUM_DIFFS]; + int max_mag_sel [DELTA_STEP + NUM_DIFFS]; + int max_mag [DELTA_STEP + NUM_DIFFS]; + int max_index [DELTA_STEP + NUM_DIFFS]; + + + + int max_d[] = {10, 19, 28}; + int min_d[] = {1, 2, 3}; + + u_int8_t *ptr; /* pointer to FFT data */ + int i; + int fft_start; + int chirp_found; + int delta_peak[NUM_DIFFS]; + int j; + int bin_count; + int bw_mask; + int delta_diff; + int same_sign; + int temp; + + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + num_fft_bytes = NUM_FFT_BYTES_HT40; + num_bin_bytes = NUM_BIN_BYTES_HT40; + num_subchan_bins = NUM_SUBCHAN_BINS_HT40; + lower_index_byte = LOWER_INDEX_BYTE_HT40; + upper_index_byte = UPPER_INDEX_BYTE_HT40; + lower_weight_byte = LOWER_WEIGHT_BYTE_HT40; + upper_weight_byte = UPPER_WEIGHT_BYTE_HT40; + lower_mag_byte = LOWER_MAG_BYTE_HT40; + upper_mag_byte = UPPER_MAG_BYTE_HT40; + + /* if we are in HT40MINUS then swap primary and extension */ + if (IS_CHAN_HT40_MINUS(dfs->ic->ic_curchan)) { + temp = is_ctl; + is_ctl = is_ext; + is_ext = temp; + } + + } else { + num_fft_bytes = NUM_FFT_BYTES_HT20; + num_bin_bytes = NUM_BIN_BYTES_HT20; + num_subchan_bins = NUM_SUBCHAN_BINS_HT20; + lower_index_byte = LOWER_INDEX_BYTE_HT20; + upper_index_byte = UPPER_INDEX_BYTE_HT20; + lower_weight_byte = LOWER_WEIGHT_BYTE_HT20; + upper_weight_byte = UPPER_WEIGHT_BYTE_HT20; + lower_mag_byte = LOWER_MAG_BYTE_HT20; + upper_mag_byte = UPPER_MAG_BYTE_HT20; + } + + ptr = (u_int8_t*)buf; + /* + * sanity check for FFT buffer + */ + + if ((ptr == NULL) || (datalen == 0)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "%s: FFT buffer pointer is null or size is 0\n", __func__); + return 0; + } + + num_fft_packets = (datalen - 3) / num_fft_bytes; + if (num_fft_packets < (NUM_DIFFS + DELTA_STEP)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "datalen = %d, num_fft_packets = %d, too few packets... (exiting)\n", datalen, num_fft_packets); + return 0; + } + + if ((((datalen - 3) % num_fft_bytes) == 2) && (datalen > num_fft_bytes)) { + // FIXME !!! + ptr += 2; + datalen -= 2; + } + + for (i = 0; i < (NUM_DIFFS + DELTA_STEP); i++) { + fft_start = i * num_fft_bytes; + bin_wt_lower[i] = ptr[fft_start + lower_weight_byte] & 0x3f; + bin_wt_upper[i] = ptr[fft_start + upper_weight_byte] & 0x3f; + + max_index_lower[i] = ptr[fft_start + lower_index_byte] >> 2; + max_index_upper[i] = (ptr[fft_start + upper_index_byte] >> 2) + num_subchan_bins; + + if (!IS_CHAN_HT40(dfs->ic->ic_curchan)) { + /* + * for HT20 mode indices are 6 bit signed number + */ + max_index_lower[i] ^= 0x20; + max_index_upper[i] = 0; + } + /* + * Reconstruct the maximum magnitude for each sub-channel. Also select + * and flag the max overall magnitude between the two sub-channels. + */ + + max_mag_lower[i] = ((ptr[fft_start + lower_index_byte] & 0x03) << 8) + + ptr[fft_start + lower_mag_byte]; + max_mag_upper[i] = ((ptr[fft_start + upper_index_byte] & 0x03) << 8) + + ptr[fft_start + upper_mag_byte]; + bw_mask = ((bin_wt_lower[i] == 0) ? 0 : is_ctl) + + (((bin_wt_upper[i] == 0) ? 0 : is_ext) << 1); + + /* + * Limit the max bin based on channel bandwidth + * If the upper sub-channel max index is stuck at '1', the signal is dominated + * by residual DC (or carrier leak) and should be ignored. + */ + + if (bw_mask == 1) { + max_mag_sel[i] = 0; + max_mag[i] = max_mag_lower[i]; + max_index[i] = max_index_lower[i]; + } else if(bw_mask == 2) { + max_mag_sel[i] = 1; + max_mag[i] = max_mag_upper[i]; + max_index[i] = max_index_upper[i]; + } else if(max_index_upper[i] == num_subchan_bins) { + max_mag_sel[i] = 0; /* Ignore DC bin. */ + max_mag[i] = max_mag_lower[i]; + max_index[i] = max_index_lower[i]; + } else { + if (max_mag_upper[i] > max_mag_lower[i]) { + max_mag_sel[i] = 1; + max_mag[i] = max_mag_upper[i]; + max_index[i] = max_index_upper[i]; + } else { + max_mag_sel[i] = 0; + max_mag[i] = max_mag_lower[i]; + max_index[i] = max_index_lower[i]; + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "i=%d, max_index[i]=%d, max_index_lower[i]=%d, " + "max_index_upper[i]=%d\n", + i, max_index[i], max_index_lower[i], max_index_upper[i]); + } + + + + chirp_found = 1; + delta_diff = 0; + same_sign = 1; + + /* + delta_diff computation -- look for movement in peak. + make sure that the chirp direction (i.e. sign) is always the same, + i.e. sign of the two peaks should be same. + */ + for (i = 0; i < NUM_DIFFS; i++) { + delta_peak[i] = max_index[i + DELTA_STEP] - max_index[i]; + if (i > 0) { + delta_diff = delta_peak[i] - delta_peak[i-1]; + same_sign = !((delta_peak[i] & 0x80) ^ (delta_peak[i-1] & 0x80)); + } + chirp_found &= (ABS(delta_peak[i]) >= min_d[DELTA_STEP - 1]) && + (ABS(delta_peak[i]) <= max_d[DELTA_STEP - 1]) && + same_sign && + (ABS(delta_diff) <= MAX_DIFF); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "i=%d, delta_peak[i]=%d, delta_diff=%d\n", + i, delta_peak[i], delta_diff); + } + + + if (chirp_found) + { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "%s: CHIRPING_BEFORE_STRONGBIN_YES\n", __func__); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "%s: CHIRPING_BEFORE_STRONGBIN_NO\n", __func__); + } + + /* + Work around for potential hardware data corruption bug. Check for + wide band signal by counting strong bins indicated by bitmap flags. + This check is done if chirp_found is true. We do this as a final check + to weed out corrupt FFTs bytes. This looks expensive but in most cases it + will exit early. + */ + + for (i = 0; (i < (NUM_DIFFS + DELTA_STEP)) && (chirp_found == 1); i++) { + bin_count = 0; + /* point to the start of the 1st byte of the selected sub-channel. */ + fft_start = (i * num_fft_bytes) + (max_mag_sel[i] ? (num_subchan_bins >> 1) : 0); + for (j = 0; j < (num_subchan_bins >> 1); j++) + { + /* + * If either bin is flagged "strong", accumulate the bin_count. + * It's not accurate, but good enough... + */ + bin_count += (ptr[fft_start + j] & 0x88) ? 1 : 0; + } + chirp_found &= (bin_count > BIN_COUNT_MAX) ? 0 : 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "i=%d, computed bin_count=%d\n", i, bin_count); + } + + if (chirp_found) + { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT | ATH_DEBUG_DFS_PHYERR_SUM, + "%s: CHIRPING_YES\n", __func__); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT | ATH_DEBUG_DFS_PHYERR_SUM, + "%s: CHIRPING_NO\n", __func__); + } + return chirp_found; + +#undef ABS_DIFF +#undef ABS +#undef DELTA_STEP +#undef NUM_DIFFS +#undef MAX_DIFF +#undef BIN_COUNT_MAX + +#undef NUM_FFT_BYTES_HT40 +#undef NUM_BIN_BYTES_HT40 +#undef NUM_SUBCHAN_BINS_HT40 +#undef LOWER_INDEX_BYTE_HT40 +#undef UPPER_INDEX_BYTE_HT40 +#undef LOWER_WEIGHT_BYTE_HT40 +#undef UPPER_WEIGHT_BYTE_HT40 +#undef LOWER_MAG_BYTE_HT40 +#undef UPPER_MAG_BYTE_HT40 + +#undef NUM_FFT_BYTES_HT40 +#undef NUM_BIN_BYTES_HT40 +#undef NUM_SUBCHAN_BINS_HT40 +#undef LOWER_INDEX_BYTE_HT40 +#undef UPPER_INDEX_BYTE_HT40 +#undef LOWER_WEIGHT_BYTE_HT40 +#undef UPPER_WEIGHT_BYTE_HT40 +#undef LOWER_MAG_BYTE_HT40 +#undef UPPER_MAG_BYTE_HT40 +} + +int +dfs_check_chirping(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, int is_ctl, int is_ext, int *slope, int *is_dc) +{ + + if (dfs->dfs_caps.ath_dfs_use_enhancement) + return dfs_check_chirping_merlin(dfs, buf, datalen, is_ctl, + is_ext, slope, is_dc); + else + return dfs_check_chirping_sowl(dfs, buf, datalen, is_ctl, + is_ext, slope, is_dc); +} + +u_int8_t +dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, u_int32_t diff_ts, + u_int8_t old_dur) +{ + + /* + * Pulses may get split into 2 during chirping, this print is only + * to show that it happened, we do not handle this condition if we + * cannot detect the chirping. + */ + /* + * SPLIT pulses will have a time stamp difference of < 50 + */ + if (diff_ts < 50) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s SPLIT pulse diffTs=%u dur=%d (old_dur=%d)\n", + __func__, diff_ts, + dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur); + } + /* + * Check if this is the 2nd or 3rd pulse in the same burst, + * PRI will be between 1000 and 2000 us + */ + if (((diff_ts >= DFS_BIN5_PRI_LOWER_LIMIT) && + (diff_ts <= DFS_BIN5_PRI_HIGHER_LIMIT))) { + /* + * This pulse belongs to the same burst as the pulse before, + * so return the same random duration for it + */ + DFS_DPRINTK(dfs,ATH_DEBUG_DFS_BIN5, + "%s this pulse belongs to the same burst as before, give " + "it same dur=%d (old_dur=%d)\n", + __func__, dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur); + + return (dfs->dfs_rinfo.dfs_last_bin5_dur); + } + /* + * This pulse does not belong to this burst, return unchanged + * duration. + */ + return old_dur; +} + +/* + * Chirping pulses may get cut off at DC and report lower durations. + * + * This function will compute a suitable random duration for each pulse. + * Duration must be between 50 and 100 us, but remember that in + * ath_process_phyerr() which calls this function, we are dealing with the + * HW reported duration (unconverted). dfs_process_radarevent() will + * actually convert the duration into the correct value. + * + * XXX This function doesn't take into account whether the hardware + * is operating in 5GHz fast clock mode or not. + * + * XXX And this function doesn't take into account whether the hardware + * is peregrine or not. Grr. + */ +int +dfs_get_random_bin5_dur(struct ath_dfs *dfs, u_int64_t tstamp) +{ + u_int8_t new_dur=MIN_BIN5_DUR; + int range; + + get_random_bytes(&new_dur, sizeof(u_int8_t)); + + range = (MAX_BIN5_DUR - MIN_BIN5_DUR + 1); + + new_dur %= range; + + new_dur += MIN_BIN5_DUR; + + return new_dur; +} + +#endif /* ATH_SUPPORT_DFS */ + diff --git a/CORE/SERVICES/DFS/src/dfs_init.c b/CORE/SERVICES/DFS/src/dfs_init.c new file mode 100644 index 000000000000..3fc9a0946549 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_init.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_init.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifdef ATH_SUPPORT_DFS + +extern int domainoverride; + +/* + * Clear all delay lines for all filter types + * + * This may be called before any radar pulses are configured + * (eg on a non-DFS channel, with radar PHY errors still showing up.) + * In that case, just drop out early. + */ +void dfs_reset_alldelaylines(struct ath_dfs *dfs) +{ + struct dfs_filtertype *ft = NULL; + struct dfs_filter *rf; + struct dfs_delayline *dl; + struct dfs_pulseline *pl; + int i,j; + + if (dfs == NULL) { + printk("%s[%d]: sc_dfs is NULL\n",__func__,__LINE__); + //DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); + return; + } + pl = dfs->pulses; + + if (pl == NULL) { + printk("%s[%d]: pl==NULL, dfs=%p\n",__func__,__LINE__,dfs); + //DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: pl==NULL, dfs=%p\n",__func__,dfs); + return; + } + + if (dfs->dfs_b5radars == NULL) { + printk("%s[%d]: pl==NULL, b5radars=%p\n",__func__,__LINE__,dfs->dfs_b5radars); + //DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: pl==NULL, b5radars=%p\n",__func__,dfs->dfs_b5radars); + return; + } + + /* reset the pulse log */ + pl->pl_firstelem = pl->pl_numelems = 0; + pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; + + for (i=0; i<DFS_MAX_RADAR_TYPES; i++) { + if (dfs->dfs_radarf[i] != NULL) { + ft = dfs->dfs_radarf[i]; + for (j=0; j<ft->ft_numfilters; j++) { + rf = &(ft->ft_filters[j]); + dl = &(rf->rf_dl); + if(dl != NULL) { + 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; + dfs->dfs_b5radars[i].br_numelems = 0; + dfs->dfs_b5radars[i].br_lastelem = (0xFFFFFFFF)&DFS_MAX_B5_MASK; + } +} +/* + * Clear only a single delay line + */ + +void dfs_reset_delayline(struct dfs_delayline *dl) +{ + OS_MEMZERO(&(dl->dl_elems[0]), sizeof(dl->dl_elems)); + dl->dl_lastelem = (0xFFFFFFFF)&DFS_MAX_DL_MASK; +} + +void dfs_reset_filter_delaylines(struct dfs_filtertype *dft) +{ + int i; + struct dfs_filter *df; + for (i=0; i< DFS_MAX_NUM_RADAR_FILTERS; i++) { + df = &dft->ft_filters[i]; + dfs_reset_delayline(&(df->rf_dl)); + } +} + +void +dfs_reset_radarq(struct ath_dfs *dfs) +{ + struct dfs_event *event; + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); + return; + } + ATH_DFSQ_LOCK(dfs); + ATH_DFSEVENTQ_LOCK(dfs); + while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) { + event = STAILQ_FIRST(&(dfs->dfs_radarq)); + STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); + OS_MEMZERO(event, sizeof(struct dfs_event)); + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); + } + ATH_DFSEVENTQ_UNLOCK(dfs); + ATH_DFSQ_UNLOCK(dfs); +} + + +/* This function Initialize the radar filter tables + * if the ath dfs domain is uninitalized or + * ath dfs domain is different from hal dfs domain + */ +int dfs_init_radar_filters(struct ieee80211com *ic, + struct ath_dfs_radar_tab_info *radar_info) +{ + u_int32_t T, Tmax; + int numpulses,p,n, i; + int numradars = 0, numb5radars = 0; + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct dfs_filtertype *ft = NULL; + struct dfs_filter *rf=NULL; + struct dfs_pulse *dfs_radars; + struct dfs_bin5pulse *b5pulses=NULL; + int32_t min_rssithresh=DFS_MAX_RSSI_VALUE; + u_int32_t max_pulsedur=0; + + if (dfs == NULL) { + printk("%s[%d]: dfs is NULL\n",__func__,__LINE__); + //DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "dfs is NULL %s",__func__); + return 1; + } + printk("%s[%d]:dfsdomain=%d, numradars=%d, numb5radars=%d\n",__func__, + __LINE__, radar_info->dfsdomain,radar_info->numradars,radar_info->numb5radars); +/* + * DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + * "%s: dfsdomain=%d, numradars=%d, numb5radars=%d\n", + * __func__, + * radar_info->dfsdomain, + * radar_info->numradars, + * radar_info->numb5radars); + */ + /* clear up the dfs domain flag first */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->ath_dfs_isdfsregdomain = 0; +#endif + + /* + * If radar_info is NULL or dfsdomain is NULL, treat + * the rest of the radar configuration as suspect. + */ + if (radar_info == NULL || radar_info->dfsdomain == 0) { + printk("%s[%d]: Unknown dfs domain %d \n",__func__,__LINE__,dfs->dfsdomain); + /*DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Unknown dfs domain %d\n", + __func__, dfs->dfsdomain);*/ + /* Disable radar detection since we don't have a radar domain */ + dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; + return 0; + } + + dfs->dfsdomain = radar_info->dfsdomain; + dfs_radars = radar_info->dfs_radars; + numradars = radar_info->numradars; + b5pulses = radar_info->b5pulses; + numb5radars = radar_info->numb5radars; + + /* XXX this should be an explicit copy of some sort! */ + dfs->dfs_defaultparams = radar_info->dfs_defaultparams; + +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->ath_dfs_isdfsregdomain = 1; +#endif + + dfs->dfs_rinfo.rn_numradars = 0; + /* Clear filter type table */ + for (n=0; n<256; n++) { + for (i=0;i<DFS_MAX_RADAR_OVERLAP; i++) + (dfs->dfs_radartable[n])[i] = -1; + } + /* Now, initialize the 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_radarf[n]->ft_filterdur) && + (dfs_radars[p].rp_numpulses == dfs->dfs_radarf[n]->ft_numpulses) && + (dfs_radars[p].rp_mindur == dfs->dfs_radarf[n]->ft_mindur) && + (dfs_radars[p].rp_maxdur == dfs->dfs_radarf[n]->ft_maxdur)) { + ft = dfs->dfs_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\n", + __func__); + goto bad4; + } + ft = dfs->dfs_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 = 1000000; + + 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_radartable[i])[tableindex] == -1) + stop = 1; + else + tableindex++; + } + if (stop) { + (dfs->dfs_radartable[i])[tableindex] = + (int8_t) (dfs->dfs_rinfo.rn_numradars); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: Too many overlapping radar filters\n", + __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; + rf->rf_threshold = dfs_radars[p].rp_threshold; + rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; + + printk("%s[%d]: minprf = %d maxprf = %d pulsevar = %d thresh=%d\n", + __func__,__LINE__,dfs_radars[p].rp_pulsefreq, dfs_radars[p].rp_max_pulsefreq, + dfs_radars[p].rp_pulsevar, rf->rf_threshold); + printk("%s[%d]:minpri = %d maxpri = %d filterlen = %d filterID = %d\n",__func__,__LINE__, + rf->rf_minpri, rf->rf_maxpri, rf->rf_filterlen, rf->rf_pulseid); + + /*DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "minprf = %d maxprf = %d pulsevar = %d thresh=%d\n", + dfs_radars[p].rp_pulsefreq, dfs_radars[p].rp_max_pulsefreq, dfs_radars[p].rp_pulsevar, rf->rf_threshold); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "minpri = %d maxpri = %d filterlen = %d filterID = %d\n", + rf->rf_minpri, rf->rf_maxpri, rf->rf_filterlen, rf->rf_pulseid);*/ + } + +#ifdef DFS_DEBUG + dfs_print_filters(ic); +#endif + dfs->dfs_rinfo.rn_numbin5radars = numb5radars; + if (dfs->dfs_b5radars != NULL) + OS_FREE(dfs->dfs_b5radars); + + dfs->dfs_b5radars = (struct dfs_bin5radars *)OS_MALLOC(NULL, + numb5radars * sizeof(struct dfs_bin5radars), GFP_KERNEL); + if (dfs->dfs_b5radars == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: cannot allocate memory for bin5 radars\n", + __func__); + goto bad4; + } + for (n=0; n<numb5radars; n++) { + dfs->dfs_b5radars[n].br_pulse = b5pulses[n]; + dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000; + if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < min_rssithresh) + min_rssithresh = dfs->dfs_b5radars[n].br_pulse.b5_rssithresh; + if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur) + max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur; + } + dfs_reset_alldelaylines(dfs); + dfs_reset_radarq(dfs); + dfs->dfs_curchan_radindex = -1; + dfs->dfs_extchan_radindex = -1; + dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh; + /* Convert durations to TSF ticks */ + dfs->dfs_rinfo.rn_maxpulsedur = dfs_round((int32_t)((max_pulsedur*100/80)*100)); + /* relax the max pulse duration a little bit due to inaccuracy caused by chirping. */ + dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur +20; + printk("%s[%d]: DFS min filter rssiThresh = %d \n",__func__,__LINE__,min_rssithresh); + printk("%s[%d]:DFS max pulse dur = %d ticks\n ",__func__,__LINE__,dfs->dfs_rinfo.rn_maxpulsedur); + //DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "DFS min filter rssiThresh = %d\n",min_rssithresh); + //DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "DFS max pulse dur = %d ticks\n", dfs->dfs_rinfo.rn_maxpulsedur); + return 0; + + bad4: + return 1; +} + +void +dfs_clear_stats(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + if (dfs == NULL) + return; + OS_MEMZERO(&dfs->ath_dfs_stats, sizeof (struct dfs_stats)); + dfs->ath_dfs_stats.last_reset_tstamp = ic->ic_get_TSF64(ic); +} + +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/DFS/src/dfs_ioctl.h b/CORE/SERVICES/DFS/src/dfs_ioctl.h new file mode 100644 index 000000000000..7503715b280c --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_ioctl.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_ioctl.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +/* + * ioctl defines + */ + +#ifndef _DFS_IOCTL_H_ +#define _DFS_IOCTL_H_ + +#define DFS_MUTE_TIME 1 +#define DFS_SET_THRESH 2 +#define DFS_GET_THRESH 3 +#define DFS_GET_USENOL 4 +#define DFS_SET_USENOL 5 +#define DFS_RADARDETECTS 6 +#define DFS_BANGRADAR 7 +#define DFS_SHOW_NOL 8 +#define DFS_DISABLE_DETECT 9 +#define DFS_ENABLE_DETECT 10 +#define DFS_DISABLE_FFT 11 +#define DFS_ENABLE_FFT 12 +#define DFS_SET_DEBUG_LEVEL 13 +#define DFS_GET_NOL 14 +#define DFS_SET_NOL 15 + +#define DFS_SET_FALSE_RSSI_THRES 16 +#define DFS_SET_PEAK_MAG 17 +#define DFS_IGNORE_CAC 18 +#define DFS_SET_NOL_TIMEOUT 19 +#define DFS_LAST_IOCTL 20 +#ifndef IEEE80211_CHAN_MAX +#define IEEE80211_CHAN_MAX 255 +#endif + +struct dfsreq_nolelem { + u_int16_t nol_freq; /* NOL channel frequency */ + u_int16_t nol_chwidth; + unsigned long nol_start_ticks; /* OS ticks when the NOL timer started */ + u_int32_t nol_timeout_ms; /* Nol timeout value in msec */ +}; + +struct dfsreq_nolinfo { + u_int32_t ic_nchans; + struct dfsreq_nolelem dfs_nol[IEEE80211_CHAN_MAX]; +}; + +/* + * ioctl parameter types + */ + +#define DFS_PARAM_FIRPWR 1 +#define DFS_PARAM_RRSSI 2 +#define DFS_PARAM_HEIGHT 3 +#define DFS_PARAM_PRSSI 4 +#define DFS_PARAM_INBAND 5 +//5413 specific parameters +#define DFS_PARAM_RELPWR 7 +#define DFS_PARAM_RELSTEP 8 +#define DFS_PARAM_MAXLEN 9 + +struct dfs_ioctl_params { + int32_t dfs_firpwr; /* FIR pwr out threshold */ + int32_t dfs_rrssi; /* Radar rssi thresh */ + int32_t dfs_height; /* Pulse height thresh */ + int32_t dfs_prssi; /* Pulse rssi thresh */ + int32_t dfs_inband; /* Inband thresh */ + int32_t dfs_relpwr; /* pulse relative pwr thresh */ + int32_t dfs_relstep; /* pulse relative step thresh */ + int32_t dfs_maxlen; /* pulse max duration */ +}; + +/* + * XXX keep these in sync with ath_dfs_phyerr_param! + */ +#define DFS_IOCTL_PARAM_NOVAL 65535 +#define DFS_IOCTL_PARAM_ENABLE 0x8000 + +#endif /* _DFS_IOCTL_H_ */ diff --git a/CORE/SERVICES/DFS/src/dfs_ioctl_private.h b/CORE/SERVICES/DFS/src/dfs_ioctl_private.h new file mode 100644 index 000000000000..2e506e7782bb --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_ioctl_private.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_ioctl_private.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +/* + * ioctl defines + */ + +#ifndef _DFS_IOCTL_PRIVATE_H_ +#define _DFS_IOCTL_PRIVATE_H_ + +/* + * Assert that the NOVAL values match. + */ +#if (ATH_DFS_PHYERR_PARAM_NOVAL != DFS_IOCTL_PARAM_NOVAL) +#error "ATH_DFS_PHYERR_PARAM_NOVAL != DFS_IOCTL_PARAM_NOVAL" +#endif + +/* + * Assert that the ENABLE values match. + */ +#if (ATH_DFS_PHYERR_PARAM_ENABLE != DFS_IOCTL_PARAM_ENABLE) +#error "ATH_DFS_PHYERR_PARAM_ENABLE != DFS_IOCTL_PARAM_ENABLE" +#endif + +/* + * These two methods are used by the lmac glue to copy between + * the DFS and HAL PHY configuration. + * + * I'm "cheating" here and assuming that the ENABLE and NOVAL + * values match - see the above macros. + */ +static inline void +ath_dfs_ioctlparam_to_dfsparam(const struct dfs_ioctl_params *src, + struct ath_dfs_phyerr_param *dst) +{ + + dst->pe_firpwr = src->dfs_firpwr; + dst->pe_rrssi = src->dfs_rrssi; + dst->pe_height = src->dfs_height; + dst->pe_prssi = src->dfs_prssi; + dst->pe_inband = src->dfs_inband; + dst->pe_relpwr = src->dfs_relpwr; + dst->pe_relstep = src->dfs_relstep; + dst->pe_maxlen = src->dfs_maxlen; +} + +static inline void +ath_dfs_dfsparam_to_ioctlparam(struct ath_dfs_phyerr_param *src, + struct dfs_ioctl_params *dst) +{ + + dst->dfs_firpwr = src->pe_firpwr; + dst->dfs_rrssi = src->pe_rrssi; + dst->dfs_height = src->pe_height; + dst->dfs_prssi = src->pe_prssi; + dst->dfs_inband = src->pe_inband; + dst->dfs_relpwr = src->pe_relpwr; + dst->dfs_relstep = src->pe_relstep; + dst->dfs_maxlen = src->pe_maxlen; +} + +#endif /* _DFS_IOCTL_PRIVATE_H_ */ diff --git a/CORE/SERVICES/DFS/src/dfs_misc.c b/CORE/SERVICES/DFS/src/dfs_misc.c new file mode 100644 index 000000000000..04e2630647e0 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_misc.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_misc.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifndef UNINET +/* TO DO DFS +#include <ieee80211_channel.h> +*/ +#endif +#ifdef ATH_SUPPORT_DFS + +static int adjust_pri_per_chan_busy(int ext_chan_busy, int pri_margin) +{ + int adjust_pri=0; + + if(ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) { + + adjust_pri = (ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) * (pri_margin); + adjust_pri /= 100; + + } + return adjust_pri; +} + +static int adjust_thresh_per_chan_busy(int ext_chan_busy, int thresh) +{ + int adjust_thresh=0; + + if(ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) { + + adjust_thresh = (ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) * thresh; + adjust_thresh /= 100; + + } + return adjust_thresh; +} +/* For the extension channel, if legacy traffic is present, we see a lot of false alarms, +so make the PRI margin narrower depending on the busy % for the extension channel.*/ + +int +dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, + int is_fixed_pattern) +{ + + int adjust_pri=0, ext_chan_busy=0; + int pri_margin; + + if (is_fixed_pattern) + pri_margin = DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN; + else + pri_margin = DFS_DEFAULT_PRI_MARGIN; + + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic); + if(ext_chan_busy >= 0) { + dfs->dfs_rinfo.ext_chan_busy_ts = dfs->ic->ic_get_TSF64(dfs->ic); + dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; + } else { + // Check to see if the cached value of ext_chan_busy can be used + ext_chan_busy = 0; + if (dfs->dfs_rinfo.dfs_ext_chan_busy) { + if (dfs->dfs_rinfo.rn_lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) { + ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + " PRI Use cached copy of ext_chan_busy extchanbusy=%d \n", ext_chan_busy); + } + } + } + adjust_pri = adjust_pri_per_chan_busy(ext_chan_busy, pri_margin); + + pri_margin -= adjust_pri; + } + return pri_margin; +} + +/* For the extension channel, if legacy traffic is present, we see a lot of false alarms, +so make the thresholds higher depending on the busy % for the extension channel.*/ + +int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, + int is_extchan_detect) +{ + int ext_chan_busy=0; + int thresh, adjust_thresh=0; + + thresh = rf->rf_threshold; + + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic); + if(ext_chan_busy >= 0) { + dfs->dfs_rinfo.ext_chan_busy_ts = dfs->ic->ic_get_TSF64(dfs->ic); + dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; + } else { + // Check to see if the cached value of ext_chan_busy can be used + ext_chan_busy = 0; + if (dfs->dfs_rinfo.dfs_ext_chan_busy) { + if (dfs->dfs_rinfo.rn_lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) { + ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + " THRESH Use cached copy of ext_chan_busy extchanbusy=%d rn_lastfull_ts=%llu ext_chan_busy_ts=%llu\n", + ext_chan_busy, + (unsigned long long)dfs->dfs_rinfo.rn_lastfull_ts, + (unsigned long long)dfs->dfs_rinfo.ext_chan_busy_ts); + } + } + } + + adjust_thresh = adjust_thresh_per_chan_busy(ext_chan_busy, thresh); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + " filterID=%d extchanbusy=%d adjust_thresh=%d\n", + rf->rf_pulseid, ext_chan_busy, adjust_thresh); + + thresh += adjust_thresh; + } + return thresh; +} + + +u_int32_t dfs_round(int32_t val) +{ + u_int32_t ival,rem; + + if (val < 0) + return 0; + ival = val/100; + rem = val-(ival*100); + if (rem <50) + return ival; + else + return(ival+1); +} + +struct ieee80211_channel * +ieee80211_get_extchan(struct ieee80211com *ic) +{ + int chan_offset = 0; + if (IEEE80211_IS_CHAN_HT40PLUS_CAPABLE(ic->ic_curchan)) { + chan_offset = 20; + } else if (IEEE80211_IS_CHAN_HT40MINUS_CAPABLE(ic->ic_curchan)) { + chan_offset = -20; + } else { + return NULL; + } + return(ic->ic_find_channel(ic, ic->ic_curchan->ic_freq + chan_offset, IEEE80211_CHAN_11NA_HT20)); +} + +/* + * Finds the radar state entry that matches the current channel + */ +struct dfs_state * +dfs_getchanstate(struct ath_dfs *dfs, u_int8_t *index, int ext_chan_flag) +{ + struct dfs_state *rs=NULL; + int i; + struct ieee80211_channel *cmp_ch; + + if (dfs == NULL) { + printk("%s[%d]: sc_dfs is NULL\n",__func__,__LINE__); + // DFS_DPRINTK(dfs, ATH_DEBUG_DFS,"%s: sc_dfs is NULL\n",__func__); + return NULL; + } + + if (ext_chan_flag) { + cmp_ch = ieee80211_get_extchan(dfs->ic); + if (cmp_ch) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "Extension channel freq = %u flags=0x%x\n", cmp_ch->ic_freq, cmp_ch->ic_flagext); + } else { + return NULL; + } + + } else { + cmp_ch = dfs->ic->ic_curchan; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "Primary channel freq = %u flags=0x%x\n", cmp_ch->ic_freq, cmp_ch->ic_flagext); + } + for (i=0;i<DFS_NUM_RADAR_STATES; i++) { + if ((dfs->dfs_radar[i].rs_chan.ic_freq== cmp_ch->ic_freq) && + (dfs->dfs_radar[i].rs_chan.ic_flags == cmp_ch->ic_flags)) { + if (index != NULL) + *index = (u_int8_t) i; + return &(dfs->dfs_radar[i]); + } + } + /* No existing channel found, look for first free channel state entry */ + for (i=0; i<DFS_NUM_RADAR_STATES; i++) { + if (dfs->dfs_radar[i].rs_chan.ic_freq == 0) { + rs = &(dfs->dfs_radar[i]); + /* Found one, set channel info and default thresholds */ + rs->rs_chan = *cmp_ch; + + /* Copy the parameters from the default set */ + ath_dfs_phyerr_param_copy(&rs->rs_param, + &dfs->dfs_defaultparams); + + if (index != NULL) + *index = (u_int8_t) i; + return (rs); + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: No more radar states left.\n", __func__); + return(NULL); +} + + + +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/DFS/src/dfs_nol.c b/CORE/SERVICES/DFS/src/dfs_nol.c new file mode 100644 index 000000000000..db570b609c33 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_nol.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_nol.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifndef UNINET +/*TO DO DFS +#include <ieee80211_channel.h> +*/ +#endif +#if defined(ATH_SUPPORT_DFS) && !defined(ATH_DFS_RADAR_DETECTION_ONLY) +#include "dfs_ioctl.h" +#include "dfs_ioctl_private.h" +#include "adf_os_time.h" /* adf_os_time_t, adf_os_time_after */ + +static void +dfs_nol_delete(struct ath_dfs *dfs, u_int16_t delfreq, u_int16_t delchwidth); + +static +OS_TIMER_FUNC(dfs_remove_from_nol) +{ + struct dfs_nol_timer_arg *nol_arg; + struct ath_dfs *dfs; + struct ieee80211com *ic; + u_int16_t delfreq; + u_int16_t delchwidth; + + OS_GET_TIMER_ARG(nol_arg, struct dfs_nol_timer_arg *); + + dfs = nol_arg->dfs; + ic = dfs->ic; + delfreq = nol_arg->delfreq; + delchwidth = nol_arg->delchwidth; + + /* Only operate in HOSTAP/IBSS */ + if (ic->ic_opmode != IEEE80211_M_HOSTAP && + ic->ic_opmode != IEEE80211_M_IBSS) + goto done; + + /* Delete the given NOL entry */ + dfs_nol_delete(dfs, delfreq, delchwidth); + + /* Update the wireless stack with the new NOL */ + dfs_nol_update(dfs); + +done: + OS_FREE(nol_arg); + return; +} + +void +dfs_print_nol(struct ath_dfs *dfs) +{ + struct dfs_nolelem *nol; + int i = 0; + uint32_t diff_ms, remaining_sec; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); + return; + } + nol = dfs->dfs_nol; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: NOL\n", __func__); + while (nol != NULL) { + diff_ms = adf_os_ticks_to_msecs(adf_os_ticks() - nol->nol_start_ticks); + diff_ms = (nol->nol_timeout_ms - diff_ms); + remaining_sec = diff_ms / 1000; /* convert to seconds */ + printk("nol:%d channel=%d MHz width=%d MHz time left=%u seconds nol starttick=%llu \n", + i++, nol->nol_freq, nol->nol_chwidth, remaining_sec, + (unsigned long long)nol->nol_start_ticks); + nol = nol->nol_next; + } +} + + +void +dfs_get_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, + int *nchan) +{ + struct dfs_nolelem *nol; + + *nchan = 0; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); + return; + } + + nol = dfs->dfs_nol; + while (nol != NULL) { + dfs_nol[*nchan].nol_freq = nol->nol_freq; + dfs_nol[*nchan].nol_chwidth = nol->nol_chwidth; + dfs_nol[*nchan].nol_start_ticks = nol->nol_start_ticks; + dfs_nol[*nchan].nol_timeout_ms = nol->nol_timeout_ms; + ++(*nchan); + nol = nol->nol_next; + } +} + + +void +dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) +{ +#define TIME_IN_MS 1000 + u_int32_t nol_time_left_ms; + struct ieee80211_channel chan; + int i; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); + return; + } + + for (i = 0; i < nchan; i++) + { + nol_time_left_ms = adf_os_ticks_to_msecs(adf_os_ticks() - dfs_nol[i].nol_start_ticks); + if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) { + chan.ic_freq = dfs_nol[i].nol_freq; + chan.ic_flags= 0; + chan.ic_flagext = 0; + nol_time_left_ms = (dfs_nol[i].nol_timeout_ms - nol_time_left_ms); + dfs_nol_addchan(dfs, &chan, (nol_time_left_ms / TIME_IN_MS)); + } + } +#undef TIME_IN_MS + dfs_nol_update(dfs); +} + + +void +dfs_nol_addchan(struct ath_dfs *dfs, struct ieee80211_channel *chan, + u_int32_t dfs_nol_timeout) +{ +#define TIME_IN_MS 1000 +#define TIME_IN_US (TIME_IN_MS * 1000) + struct dfs_nolelem *nol, *elem, *prev; + struct dfs_nol_timer_arg *dfs_nol_arg; + /* XXX for now, assume all events are 20MHz wide */ + int ch_width = 20; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); + return; + } + nol = dfs->dfs_nol; + prev = dfs->dfs_nol; + elem = NULL; + while (nol != NULL) { + if ((nol->nol_freq == chan->ic_freq) && + (nol->nol_chwidth == ch_width)) { + nol->nol_start_ticks = adf_os_ticks(); + nol->nol_timeout_ms = dfs_nol_timeout*TIME_IN_MS; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s: Update OS Ticks for NOL %d MHz / %d MHz\n", + __func__, nol->nol_freq, nol->nol_chwidth); + OS_CANCEL_TIMER(&nol->nol_timer); + OS_SET_TIMER(&nol->nol_timer, dfs_nol_timeout*TIME_IN_MS); + return; + } + prev = nol; + nol = nol->nol_next; + } + /* Add a new element to the NOL*/ + elem = (struct dfs_nolelem *)OS_MALLOC(NULL, sizeof(struct dfs_nolelem),GFP_ATOMIC); + if (elem == NULL) { + goto bad; + } + dfs_nol_arg = (struct dfs_nol_timer_arg *)OS_MALLOC(NULL, + sizeof(struct dfs_nol_timer_arg), GFP_ATOMIC); + if (dfs_nol_arg == NULL) { + OS_FREE(elem); + goto bad; + } + elem->nol_freq = chan->ic_freq; + elem->nol_chwidth = ch_width; + elem->nol_start_ticks = adf_os_ticks(); + elem->nol_timeout_ms = dfs_nol_timeout*TIME_IN_MS; + elem->nol_next = NULL; + if (prev) { + prev->nol_next = elem; + } else { + /* This is the first element in the NOL */ + dfs->dfs_nol = elem; + } + dfs_nol_arg->dfs = dfs; + dfs_nol_arg->delfreq = elem->nol_freq; + dfs_nol_arg->delchwidth = elem->nol_chwidth; + + OS_INIT_TIMER(NULL, &elem->nol_timer, dfs_remove_from_nol, + dfs_nol_arg); + OS_SET_TIMER(&elem->nol_timer, dfs_nol_timeout*TIME_IN_MS); + + /* Update the NOL counter */ + dfs->dfs_nol_count++; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s: new NOL channel %d MHz / %d MHz\n", + __func__, + elem->nol_freq, + elem->nol_chwidth); + return; + +bad: + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL | ATH_DEBUG_DFS, + "%s: failed to allocate memory for nol entry\n", __func__); + +#undef TIME_IN_MS +#undef TIME_IN_US +} + +/* + * Delete the given frequency/chwidth from the NOL. + */ +static void +dfs_nol_delete(struct ath_dfs *dfs, u_int16_t delfreq, u_int16_t delchwidth) +{ + struct dfs_nolelem *nol,**prev_next; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); + return; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s: remove channel=%d/%d MHz from NOL\n", + __func__, + delfreq, delchwidth); + prev_next = &(dfs->dfs_nol); + nol = dfs->dfs_nol; + while (nol != NULL) { + if (nol->nol_freq == delfreq && nol->nol_chwidth == delchwidth) { + *prev_next = nol->nol_next; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s removing channel %d/%dMHz from NOL tstamp=%d\n", + __func__, nol->nol_freq, nol->nol_chwidth, + (adf_os_ticks_to_msecs(adf_os_ticks()) / 1000)); + OS_CANCEL_TIMER(&nol->nol_timer); + OS_FREE(nol); + nol = NULL; + nol = *prev_next; + + /* Update the NOL counter */ + dfs->dfs_nol_count--; + + /* Be paranoid! */ + if (dfs->dfs_nol_count < 0) { + DFS_PRINTK("%s: dfs_nol_count < 0; eek!\n", __func__); + dfs->dfs_nol_count = 0; + } + + } else { + prev_next = &(nol->nol_next); + nol = nol->nol_next; + } + } +} + +/* + * Notify the driver/umac that it should update the channel radar/NOL + * flags based on the current NOL list. + */ +void +dfs_nol_update(struct ath_dfs *dfs) +{ + struct ieee80211com *ic = dfs->ic; + struct dfs_nol_chan_entry *dfs_nol; + struct dfs_nolelem *nol; + int nlen; + + /* + * Allocate enough entries to store the NOL. + * + * At least on Linux (don't ask why), if you allocate a 0 entry + * array, the returned pointer is 0x10. Make sure you're + * aware of this when you start debugging. + */ + dfs_nol = (struct dfs_nol_chan_entry *)OS_MALLOC(NULL, + sizeof(struct dfs_nol_chan_entry) * dfs->dfs_nol_count, + GFP_ATOMIC); + + if (dfs_nol == NULL) { + /* + * XXX TODO: if this fails, just schedule a task to retry + * updating the NOL at a later stage. That way the NOL + * update _DOES_ happen - hopefully the failure was just + * temporary. + */ + DFS_PRINTK("%s: failed to allocate NOL update memory!\n", + __func__); + return; + } + + + /* populate the nol array */ + nlen = 0; + + nol = dfs->dfs_nol; + while (nol != NULL && nlen < dfs->dfs_nol_count) { + dfs_nol[nlen].nol_chfreq = nol->nol_freq; + dfs_nol[nlen].nol_chwidth = nol->nol_chwidth; + dfs_nol[nlen].nol_start_ticks = nol->nol_start_ticks; + dfs_nol[nlen].nol_timeout_ms = nol->nol_timeout_ms; + nlen++; + nol = nol->nol_next; + } + + /* Be suitably paranoid for now */ + if (nlen != dfs->dfs_nol_count) + DFS_PRINTK("%s: nlen (%d) != dfs->dfs_nol_count (%d)!\n", + __func__, nlen, dfs->dfs_nol_count); + + /* + * Call the driver layer to have it recalculate the NOL flags for + * each driver/umac channel. + * + * If the list is empty, pass NULL instead of dfs_nol. + * + * The operating system may have some special representation for + * "malloc a 0 byte memory region" - for example, + * Linux 2.6.38-13 (ubuntu) returns 0x10 rather than a valid + * allocation (and is likely not NULL so the pointer doesn't + * match NULL checks in any later code. + */ + ic->ic_dfs_clist_update(ic, DFS_NOL_CLIST_CMD_UPDATE, + (nlen > 0) ? dfs_nol : NULL, nlen); + + /* + * .. and we're done. + */ + OS_FREE(dfs_nol); +} + +void dfs_nol_timer_cleanup(struct ath_dfs *dfs) +{ + struct dfs_nolelem *nol = dfs->dfs_nol, *prev; + + /* First Cancel timer */ + while (nol) { + OS_CANCEL_TIMER(&nol->nol_timer); + nol = nol->nol_next; + } + /* Free NOL elem, don't mix this while loop with above loop */ + nol = dfs->dfs_nol; + while (nol) { + prev = nol; + nol = nol->nol_next; + OS_FREE(prev); + } + return; +} +#endif /* defined(ATH_SUPPORT_DFS) && !defined(ATH_DFS_RADAR_DETECTION_ONLY) */ diff --git a/CORE/VOSS/src/packet.c b/CORE/SERVICES/DFS/src/dfs_phyerr.h index 980b96f56bc5..5b471d8f0d9e 100644 --- a/CORE/VOSS/src/packet.c +++ b/CORE/SERVICES/DFS/src/dfs_phyerr.h @@ -25,44 +25,40 @@ * to the Linux Foundation. */ -/**======================================================================== +/*=========================================================================== - \file packet.c - \brief Implementation of packet module + dfs_phyerr.h - ========================================================================*/ -/**========================================================================= - EDIT HISTORY FOR FILE + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE This section contains comments describing changes made to the module. Notice that changes are listed in reverse chronological order. - $Header:$ $DateTime: $ $Author: $ - when who what, where, why - -------- --- ----------------------------------------- - 26/03/2013 Ganesh Created module for Packet Handling - Babu - ==========================================================================*/ -#include "packet.h" -#include "adf_nbuf.h" -#include "vos_memory.h" - -/** - * voss_rx_packet_free Free the Rx Packet - * @ Rx Packet - */ -void voss_rx_packet_free(void* rxpacket) -{ - tp_rxpacket rx_packet = (tp_rxpacket)rxpacket; + when who what, where, why +---------- --- -------------------------------------------------------- - /* Free up the Adf nbuf */ - adf_nbuf_free(rx_packet->rx_nbuf); +===========================================================================*/ - /* Free up the Rx packet */ - vos_mem_free(rx_packet); -} +#ifndef __DFS_PHYERR_H__ +#define __DFS_PHYERR_H__ +extern int dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, u_int8_t rssi, u_int8_t ext_rssi, + u_int32_t rs_tstamp, u_int64_t fulltsf, struct dfs_phy_err *e); +#endif /* __DFS_PHYERR_H__ */ diff --git a/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c b/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c new file mode 100644 index 000000000000..bb584a5883c8 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_phyerr_tlv.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +/* TO DO DFS +#include <ieee80211_channel.h> +*/ +#include "dfs_phyerr.h" +#include "dfs_phyerr_tlv.h" + +/* + * Parsed radar status + */ +struct rx_radar_status { + uint32_t raw_tsf; + uint32_t tsf_offset; + int rssi; + int pulse_duration; + int is_chirp:1; + int delta_peak; + int delta_diff; + int sidx; + int freq_offset; /* in KHz */ +}; + + +struct rx_search_fft_report { + uint32_t total_gain_db; + uint32_t base_pwr_db; + int fft_chn_idx; + int peak_sidx; + int relpwr_db; + int avgpwr_db; + int peak_mag; + int num_str_bins_ib; +}; + + +/* + * XXX until "fastclk" is stored in the DFS configuration.. + */ +#define PERE_IS_OVERSAMPLING(_dfs) (1) + +/* + * XXX there _has_ to be a better way of doing this! + * -adrian + */ +static int32_t +sign_extend_32(uint32_t v, int nb) +{ + uint32_t m = 1U << (nb - 1); + + /* Chop off high bits, just in case */ + v &= v & ((1U << nb) - 1); + + /* Extend */ + return (v ^ m) - m; +} + +/* + * Calculate the frequency offset from the given signed bin index + * from the radar summary report. + * + * This takes the oversampling mode into account. + * + * For oversampling, each bin has resolution 44MHz/128. + * For non-oversampling, each bin has resolution 40MHz/128. + * + * It returns kHz - ie, 1000th's of MHz. + */ +static int +calc_freq_offset(int sindex, int is_oversampling) +{ + + if (is_oversampling) + return (sindex * (44000 / 128)); + else + return (sindex * (40000 / 128)); +} + +static void +radar_summary_print(struct ath_dfs *dfs, struct rx_radar_status *rsu) +{ + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " pulsedur=%d\n", rsu->pulse_duration); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " rssi=%d\n", rsu->rssi); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " ischirp=%d\n", rsu->is_chirp); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " sidx=%d\n", rsu->sidx); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " raw tsf=%d\n", rsu->raw_tsf); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " tsf_offset=%d\n", rsu->tsf_offset); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " cooked tsf=%d\n", rsu->raw_tsf - rsu->tsf_offset); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + " frequency offset=%d.%d MHz (oversampling=%d)\n", + (int) (rsu->freq_offset / 1000), + (int) abs(rsu->freq_offset % 1000), + PERE_IS_OVERSAMPLING(dfs)); +} + +/* + * Parse the radar summary frame. + * + * The frame contents _minus_ the TLV are passed in. + */ +static void +radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, + struct rx_radar_status *rsu) +{ + uint32_t rs[2]; + + /* Drop out if we have < 2 DWORDs available */ + if (len < sizeof(rs)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | + ATH_DEBUG_DFS_PHYERR_SUM, + "%s: len (%d) < expected (%d)!\n", + __func__, + len, + sizeof(rs)); + } + + /* + * Since the TLVs may be unaligned for some reason + * we take a private copy into aligned memory. + * This enables us to use the HAL-like accessor macros + * into the DWORDs to access sub-DWORD fields. + */ + OS_MEMCPY(rs, buf, sizeof(rs)); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x\n", __func__, rs[0], rs[1]); +// DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):\n", __func__, buf); + + /* Populate the fields from the summary report */ + rsu->tsf_offset = + MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_TSF_OFFSET); + rsu->pulse_duration = + MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_DUR); + rsu->is_chirp = + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_IS_CHIRP); + rsu->sidx = sign_extend_32( + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_SIDX), + 10); + rsu->freq_offset = + calc_freq_offset(rsu->sidx, PERE_IS_OVERSAMPLING(dfs)); + + /* These are only relevant if the pulse is a chirp */ + rsu->delta_peak = sign_extend_32( + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_PEAK), + 6); + rsu->delta_diff = + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_DIFF); +} + +static void +radar_fft_search_report_parse(struct ath_dfs *dfs, const char *buf, size_t len, + struct rx_search_fft_report *rsfr) +{ + uint32_t rs[2]; + + /* Drop out if we have < 2 DWORDs available */ + if (len < sizeof(rs)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | + ATH_DEBUG_DFS_PHYERR_SUM, + "%s: len (%d) < expected (%d)!\n", + __func__, + len, + sizeof(rs)); + } + + /* + * Since the TLVs may be unaligned for some reason + * we take a private copy into aligned memory. + * This enables us to use the HAL-like accessor macros + * into the DWORDs to access sub-DWORD fields. + */ + OS_MEMCPY(rs, buf, sizeof(rs)); + rsfr->total_gain_db = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_TOTAL_GAIN_DB); + rsfr->base_pwr_db = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_BASE_PWR_DB); + rsfr->fft_chn_idx = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_FFT_CHN_IDX); + rsfr->peak_sidx = sign_extend_32(MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_PEAK_SIDX), 12); + rsfr->relpwr_db = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_RELPWR_DB); + rsfr->avgpwr_db = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_AVGPWR_DB); + rsfr->peak_mag = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_PEAK_MAG); + rsfr->num_str_bins_ib = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_NUM_STR_BINS_IB); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x\n", __func__, rs[0], rs[1]); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->total_gain_db = %d\n", __func__, rsfr->total_gain_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->base_pwr_db = %d\n", __func__, rsfr->base_pwr_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->fft_chn_idx = %d\n", __func__, rsfr->fft_chn_idx); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->peak_sidx = %d\n", __func__, rsfr->peak_sidx); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->relpwr_db = %d\n", __func__, rsfr->relpwr_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->avgpwr_db = %d\n", __func__, rsfr->avgpwr_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->peak_mag = %d\n", __func__, rsfr->peak_mag); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->num_str_bins_ib = %d\n", __func__, rsfr->num_str_bins_ib); +} + +/* + * Parse a Peregrine BB TLV frame. + * + * This routine parses each TLV, prints out what's going on and + * calls an appropriate sub-function. + * + * Since the TLV format doesn't _specify_ all TLV components are + * DWORD aligned, we must treat them as not and access the fields + * appropriately. + */ +static int +tlv_parse_frame(struct ath_dfs *dfs, struct rx_radar_status *rs, + struct rx_search_fft_report *rsfr, const char *buf, size_t len, u_int8_t rssi) +{ + int i = 0; + uint32_t tlv_hdr[1]; + bool first_tlv = true; + bool false_detect = false; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: total length = %d bytes\n", __func__, len); + while ((i < len ) && (false_detect == false)) { + /* Ensure we at least have four bytes */ + if ((len - i) < sizeof(tlv_hdr)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | + ATH_DEBUG_DFS_PHYERR_SUM, + "%s: ran out of bytes, len=%d, i=%d\n", + __func__, len, i); + return (0); + } + + /* + * Copy the offset into the header, + * so the DWORD style access macros + * can be used. + */ + OS_MEMCPY(&tlv_hdr, buf + i, sizeof(tlv_hdr)); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: HDR: TLV SIG=0x%x, TAG=0x%x, LEN=%d bytes\n", + __func__, + MS(tlv_hdr[TLV_REG], TLV_SIG), + MS(tlv_hdr[TLV_REG], TLV_TAG), + MS(tlv_hdr[TLV_REG], TLV_LEN)); + + /* + * Sanity check the length field is available in + * the remaining frame. Drop out if this isn't + * the case - we can't trust the rest of the TLV + * entries. + */ + if (MS(tlv_hdr[TLV_REG], TLV_LEN) + i >= len) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: TLV oversize: TLV LEN=%d, available=%d, " + "i=%d\n", + __func__, + MS(tlv_hdr[TLV_REG], TLV_LEN), + len, + i); + break; + } + + /* Skip the TLV header - one DWORD */ + i += sizeof(tlv_hdr); + + /* Handle the payload */ + /* XXX TODO! */ + switch (MS(tlv_hdr[TLV_REG], TLV_SIG)) { + case TAG_ID_RADAR_PULSE_SUMMARY: /* Radar pulse summary */ + /* XXX TODO verify return value */ + /* XXX TODO validate only seeing one of these */ + radar_summary_parse(dfs, buf + i, + MS(tlv_hdr[TLV_REG], TLV_LEN), rs); + break; + case TAG_ID_SEARCH_FFT_REPORT: + radar_fft_search_report_parse(dfs, buf + i, + MS(tlv_hdr[TLV_REG], TLV_LEN), rsfr); + /* + we examine search FFT report and make the following assumption + as per algorithms group's input: + (1) There may be multiple TLV + (2) We make false detection decison solely based on the first TLV + (3) If the first TLV is a serch FFT report then we check the peak_mag value. + When RSSI is equal to dfs->ath_dfs_false_rssI_thres (default 50) + and peak_mag is less than 2 * dfs->ath_dfs_peak_mag (default 40) + we treat it as false detect. + Please note that 50 is not a true RSSI estimate, but value indicated + by HW for RF saturation event. + */ + + if ((first_tlv == true) && + (rssi == dfs->ath_dfs_false_rssi_thres) && + (rsfr->peak_mag < (2 * dfs->ath_dfs_peak_mag))) { + false_detect = true; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s: setting false_detect to TRUE\n", __func__); + } + + break; + default: + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: unknown entry, SIG=0x%02x\n", + __func__, + MS(tlv_hdr[TLV_REG], TLV_SIG)); + } + + /* Skip the payload */ + i += MS(tlv_hdr[TLV_REG], TLV_LEN); + first_tlv = false; + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s: done\n\n", __func__); + + return (false_detect? 0 : 1); +} + +/* + * Calculate the channel centre in MHz. + */ +static int +tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) +{ + uint32_t chan_centre; + uint32_t chan_width; + int chan_offset; + + /* + * For now, just handle up to VHT80 correctly. + */ + if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) { + DFS_PRINTK("%s: dfs->ic=%p, that or curchan is null?\n", + __func__, dfs->ic); + return (0); + /* + * For now, the only 11ac channel with freq1/freq2 setup is + * VHT80. + * + * XXX should have a flag macro to check this! + */ + } else if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { + /* 11AC, so cfreq1/cfreq2 are setup */ + + /* + * XXX if it's 80+80 this won't work - need to use seg + * appropriately! + */ + + chan_centre = dfs->ic->ic_ieee2mhz( + dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1, + dfs->ic->ic_curchan->ic_flags); + } else { + /* HT20/HT40 */ + + /* + * XXX this is hard-coded - it should be 5 or 10 for + * half/quarter appropriately. + */ + chan_width = 20; + + /* Grab default channel centre */ + chan_centre = ieee80211_chan2freq(dfs->ic, + dfs->ic->ic_curchan); + + /* Calculate offset based on HT40U/HT40D and VHT40U/VHT40D */ + if (IEEE80211_IS_CHAN_11N_HT40PLUS(dfs->ic->ic_curchan) || + dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40PLUS) + chan_offset = chan_width; + else if (IEEE80211_IS_CHAN_11N_HT40MINUS(dfs->ic->ic_curchan) || + dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40MINUS) + chan_offset = -chan_width; + else + chan_offset = 0; + + /* Calculate new _real_ channel centre */ + chan_centre += (chan_offset / 2); + } + + /* + * XXX half/quarter rate support! + */ + + /* Return ev_chan_centre in MHz */ + return (chan_centre); +} + +/* + * Calculate the centre frequency and low/high range for a radar pulse event. + * + * XXX TODO: Handle half/quarter rates correctly! + * XXX TODO: handle VHT160 correctly! + * XXX TODO: handle VHT80+80 correctly! + */ +static int +tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, + uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) +{ + int chan_width; + int chan_centre; + + /* Fetch the channel centre frequency in MHz */ + chan_centre = tlv_calc_freq_info(dfs, rs); + + /* Convert to KHz */ + chan_centre *= 1000; + + /* + * XXX hard-code event width to be 2 * bin size for now; + * XXX this needs to take into account the core clock speed + * XXX for half/quarter rate mode. + */ + if (PERE_IS_OVERSAMPLING(dfs)) + chan_width = (44000 * 2 / 128); + else + chan_width = (40000 * 2 / 128); + + /* XXX adjust chan_width for half/quarter rate! */ + + /* + * Now we can do the math to figure out the correct channel range. + */ + (*freq_centre) = (uint32_t) (chan_centre + rs->freq_offset); + (*freq_lo) = (uint32_t) ((chan_centre + rs->freq_offset) + - chan_width); + (*freq_hi) = (uint32_t) ((chan_centre + rs->freq_offset) + + chan_width); + + return (1); +} + +/* + * The chirp bandwidth in KHz is defined as: + * + * totalBW(KHz) = delta_peak(mean) + * * [ (bin resolution in KHz) / (radar_fft_long_period in uS) ] + * * pulse_duration (us) + * + * The bin resolution depends upon oversampling. + * + * For now, we treat the radar_fft_long_period as a hard-coded 8uS. + */ +static int +tlv_calc_event_freq_chirp(struct ath_dfs *dfs, struct rx_radar_status *rs, + uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) +{ + int32_t bin_resolution; /* KHz * 100 */ + int32_t radar_fft_long_period = 8; /* microseconds */ + int32_t delta_peak; + int32_t pulse_duration; + int32_t total_bw; + int32_t chan_centre; + int32_t freq_1, freq_2; + + /* + * KHz isn't enough resolution here! + * So treat it as deci-hertz (10Hz) and convert back to KHz + * later. + */ + if (PERE_IS_OVERSAMPLING(dfs)) + bin_resolution = (44000 * 100) / 128; + else + bin_resolution = (40000 * 100) / 128; + + delta_peak = rs->delta_peak; + pulse_duration = rs->pulse_duration; + + total_bw = delta_peak * (bin_resolution / radar_fft_long_period) * + pulse_duration; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | ATH_DEBUG_DFS_PHYERR_SUM, + "%s: delta_peak=%d, pulse_duration=%d, bin_resolution=%d.%dKHz, " + "radar_fft_long_period=%d, total_bw=%d.%ldKHz\n", + __func__, + delta_peak, + pulse_duration, + bin_resolution / 1000, + bin_resolution % 1000, + radar_fft_long_period, + total_bw / 100, + abs(total_bw % 100)); + + total_bw /= 100; /* back to KHz */ + + /* Grab the channel centre frequency in MHz */ + chan_centre = tlv_calc_freq_info(dfs, rs); + + /* Early abort! */ + if (chan_centre == 0) { + (*freq_centre) = 0; + return (0); + } + + /* Convert to KHz */ + chan_centre *= 1000; + + /* + * sidx is the starting frequency; total_bw is a signed value and + * for negative chirps (ie, moving down in frequency rather than up) + * the end frequency may be less than the start frequency. + */ + if (total_bw > 0) { + freq_1 = chan_centre + rs->freq_offset; + freq_2 = chan_centre + rs->freq_offset + total_bw; + } else { + freq_1 = chan_centre + rs->freq_offset + total_bw; + freq_2 = chan_centre + rs->freq_offset; + } + + (*freq_lo) = (uint32_t)(freq_1); + (*freq_hi) = (uint32_t)(freq_2); + (*freq_centre) = (uint32_t) (freq_1 + (abs(total_bw) / 2)); + + return (1); +} + +/* + * Calculate the centre and band edge frequencies of the given radar + * event. + */ +static int +tlv_calc_event_freq(struct ath_dfs *dfs, struct rx_radar_status *rs, + uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) +{ + if (rs->is_chirp) + return tlv_calc_event_freq_chirp(dfs, rs, freq_centre, + freq_lo, freq_hi); + else + return tlv_calc_event_freq_pulse(dfs, rs, freq_centre, + freq_lo, freq_hi); +} + +/* + * This is the public facing function which parses the PHY error + * and populates the dfs_phy_err struct. + */ +int +dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, u_int64_t fulltsf, + struct dfs_phy_err *e) +{ + struct rx_radar_status rs; + struct rx_search_fft_report rsfr; + + OS_MEMZERO(&rs, sizeof(rs)); + + /* + * Add the ppdu_start/ppdu_end fields given to us by the upper + * layers. The firmware gives us a summary set of parameters rather + * than the whole PPDU_START/PPDU_END descriptor contenst. + */ + rs.rssi = rssi; + rs.raw_tsf = rs_tstamp; + + /* + * Try parsing the TLV set. + */ + if (! tlv_parse_frame(dfs, &rs, &rsfr, buf, datalen, rssi)){ + printk("%s[%d]: !tlv_parse_frame FAILED \n",__func__,__LINE__); + return (0); + } + /* For debugging, print what we have parsed */ + radar_summary_print(dfs, &rs); + + /* Populate dfs_phy_err from rs */ + OS_MEMSET(e, 0, sizeof(*e)); + e->rssi = rs.rssi; + e->dur = rs.pulse_duration; + e->is_pri = 1; /* XXX always PRI for now */ + e->is_ext = 0; + e->is_dc = 0; + e->is_early = 0; + /* + * XXX TODO: add a "chirp detection enabled" capability or config + * bit somewhere, in case for some reason the hardware chirp + * detection AND FFTs are disabled. + */ + /* For now, assume this hardware always does chirp detection */ + e->do_check_chirp = 1; + e->is_hw_chirp = !! (rs.is_chirp); + e->is_sw_chirp = 0; /* We don't yet do software chirp checking */ + + e->fulltsf = fulltsf; + e->rs_tstamp = rs.raw_tsf - rs.tsf_offset; + + /* XXX error check */ + (void) tlv_calc_event_freq(dfs, &rs, &e->freq, &e->freq_lo, + &e->freq_hi); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, + "%s: fbin=%d, freq=%d.%d MHz, raw tsf=%u, offset=%d, " + "cooked tsf=%u, rssi=%d, dur=%d, is_chirp=%d, fulltsf=%llu, " + "freq=%d.%d MHz, freq_lo=%d.%dMHz, freq_hi=%d.%d MHz\n", + __func__, + rs.sidx, + (int) (rs.freq_offset / 1000), + (int) abs(rs.freq_offset % 1000), + rs.raw_tsf, + rs.tsf_offset, + e->rs_tstamp, + rs.rssi, + rs.pulse_duration, + (int) rs.is_chirp, + (unsigned long long) fulltsf, + (int) e->freq / 1000, + (int) abs(e->freq) % 1000, + (int) e->freq_lo / 1000, + (int) abs(e->freq_lo) % 1000, + (int) e->freq_hi / 1000, + (int) abs(e->freq_hi) % 1000); + + return (1); +} diff --git a/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h b/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h new file mode 100644 index 000000000000..c15e7f5517c1 --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_phyerr_tlv.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ +#ifndef __DFS_PHYERR_PEREGRINE_H__ +#define __DFS_PHYERR_PEREGRINE_H__ + +/* + * Register manipulation macros that expect bit field defines + * to follow the convention that an _S suffix is appended for + * a shift count, while the field mask has no suffix. + */ +#define SM(_v, _f) (((_v) << _f##_S) & _f) +#define MS(_v, _f) (((_v) & _f) >> _f##_S) + +/* + * The TLV dword is at the beginning of each TLV section. + */ +#define TLV_REG 0x00 + +#define TLV_LEN 0x0000FFFF +#define TLV_LEN_S 0 + +#define TLV_SIG 0x00FF0000 +#define TLV_SIG_S 16 + +#define TLV_TAG 0xFF000000 +#define TLV_TAG_S 24 + +#define TAG_ID_SEARCH_FFT_REPORT 0xFB +#define TAG_ID_RADAR_PULSE_SUMMARY 0xF8 +/* + * Radar pulse summary + * + * + TYPE=0xF8 (Radar pulse summary reprot) + * + SIG=0xBB (baseband PHY generated TLV components) + */ + +#define RADAR_REPORT_PULSE_REG_1 0x00 + +#define RADAR_REPORT_PULSE_IS_CHIRP 0x80000000 +#define RADAR_REPORT_PULSE_IS_CHIRP_S 31 + +#define RADAR_REPORT_PULSE_IS_MAX_WIDTH 0x40000000 +#define RADAR_REPORT_PULSE_IS_MAX_WIDTH_S 30 + +#define RADAR_REPORT_AGC_TOTAL_GAIN 0x3FF00000 +#define RADAR_REPORT_AGC_TOTAL_GAIN_S 20 + +#define RADAR_REPORT_PULSE_DELTA_DIFF 0x000F0000 +#define RADAR_REPORT_PULSE_DELTA_DIFF_S 16 + +#define RADAR_REPORT_PULSE_DELTA_PEAK 0x0000FC00 +#define RADAR_REPORT_PULSE_DELTA_PEAK_S 10 + +#define RADAR_REPORT_PULSE_SIDX 0x000003FF +#define RADAR_REPORT_PULSE_SIDX_S 0x0 + +#define RADAR_REPORT_PULSE_REG_2 0x01 + +#define RADAR_REPORT_PULSE_SRCH_FFT_A_VALID 0x80000000 +#define RADAR_REPORT_PULSE_SRCH_FFT_A_VALID_S 31 + +#define RADAR_REPORT_PULSE_AGC_MB_GAIN 0x7F000000 +#define RADAR_REPORT_PULSE_AGC_MB_GAIN_S 24 + +#define RADAR_REPORT_PULSE_SUBCHAN_MASK 0x00FF0000 +#define RADAR_REPORT_PULSE_SUBCHAN_MASK_S 16 + +#define RADAR_REPORT_PULSE_TSF_OFFSET 0x0000FF00 +#define RADAR_REPORT_PULSE_TSF_OFFSET_S 8 + +#define RADAR_REPORT_PULSE_DUR 0x000000FF +#define RADAR_REPORT_PULSE_DUR_S 0 + +#define SEARCH_FFT_REPORT_REG_1 0x00 + + +#define SEARCH_FFT_REPORT_TOTAL_GAIN_DB 0xFF800000 +#define SEARCH_FFT_REPORT_TOTAL_GAIN_DB_S 23 + +#define SEARCH_FFT_REPORT_BASE_PWR_DB 0x007FC000 +#define SEARCH_FFT_REPORT_BASE_PWR_DB_S 14 + +#define SEARCH_FFT_REPORT_FFT_CHN_IDX 0x00003000 +#define SEARCH_FFT_REPORT_FFT_CHN_IDX_S 12 + +#define SEARCH_FFT_REPORT_PEAK_SIDX 0x00000FFF +#define SEARCH_FFT_REPORT_PEAK_SIDX_S 0 + +#define SEARCH_FFT_REPORT_REG_2 0x01 + +#define SEARCH_FFT_REPORT_RELPWR_DB 0xFC000000 +#define SEARCH_FFT_REPORT_RELPWR_DB_S 26 + +#define SEARCH_FFT_REPORT_AVGPWR_DB 0x03FC0000 +#define SEARCH_FFT_REPORT_AVGPWR_DB_S 18 + +#define SEARCH_FFT_REPORT_PEAK_MAG 0x0003FF00 +#define SEARCH_FFT_REPORT_PEAK_MAG_S 8 + +#define SEARCH_FFT_REPORT_NUM_STR_BINS_IB 0x000000FF +#define SEARCH_FFT_REPORT_NUM_STR_BINS_IB_S 0 + + + +/* + * Although this code is now not parsing the whole frame (descriptor + * and all), the relevant fields are still useful information + * for anyone who is working on the PHY error part of DFS pattern + * matching. + * + * However, to understand _where_ these descriptors start, you + * should do some digging into the peregrine descriptor format. + * The 30 second version: each RX ring has a bitmap listing which + * descriptors are to be included, and then a set of offsets + * into the RX buffer for where each descriptor will be written. + * It's not like the 802.11n generation hardware which has + * a fixed descriptor format. + */ + +/* + * RX_PPDU_START + */ +#define RX_PPDU_START_LEN (10*4) + +#define RX_PPDU_START_REG_4 0x0004 +#define RX_PPDU_START_RSSI_COMB 0x000000FF +#define RX_PPDU_START_RSSI_COMB_S 0 + +/* + * RX_PPDU_END + */ +#define RX_PPDU_END_LEN (21*4) + +#define RX_PPDU_END_REG_16 16 +#define RX_PPDU_END_TSF_TIMESTAMP 0xFFFFFFFF +#define RX_PPDU_END_TSF_TIMESTAMP_S 0 + +#define RX_PPDU_END_REG_18 18 +#define RX_PPDU_END_PHY_ERR_CODE 0x0000FF00 +#define RX_PPDU_END_PHY_ERR_CODE_S 8 +#define RX_PPDU_END_PHY_ERR 0x00010000 +#define RX_PPDU_END_PHY_ERR_S 16 + +/* + * The RSSI values can have "special meanings". + * + * If rssi=50, it means that the peak detector triggered. + */ +#define RSSI_PEAK_DETECTOR_SAT 50 + +/* + * + * If rssi=25, it means that the ADC was saturated, but that only is + * valid when there is one ADC gain change. For short pulses this + * is true - you won't have time to do a gain change before the pulse + * goes away. But for longer pulses, ADC gain changes can occur, so + * you'll get a more accurate RSSI figure. + * + * For short pulses (and the definition of "short" still isn't clear + * at the time of writing) there isn't any real time to do a gain change + * (or two, or three..) in order to get an accurate estimation of signal + * sizing. Thus, RSSI will not be very accurate for short duration pulses. + * All you can really say for certain is that yes, there's a pulse that + * met the requirements of the pulse detector. + * + * For more information, see the 802.11ac Microarchitecture guide. + * (TODO: add a twiki reference.) + */ + +#endif /* __DFS_PHYERR_PEREGRINE_H__ */ diff --git a/CORE/SERVICES/DFS/src/dfs_process_phyerr.c b/CORE/SERVICES/DFS/src/dfs_process_phyerr.c new file mode 100644 index 000000000000..f98cb99964ff --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_process_phyerr.c @@ -0,0 +1,883 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_process_phyerr.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +#include "dfs_phyerr.h" /* For chip-specific phyerr function declarations */ +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifndef UNINET +/* TO DO DFS +#include <ieee80211_channel.h> +*/ +#endif +#ifdef ATH_SUPPORT_DFS + +/* + * Return the frequency width for the current operating channel. + * + * This isn't the channel width - it's how wide the reported event + * may be. For HT20 this is 20MHz. For HT40 on Howl and later it'll + * still be 20MHz - the hardware returns either pri or ext channel. + */ +static inline int +dfs_get_event_freqwidth(struct ath_dfs *dfs) +{ + + /* Handle edge cases during startup/transition, shouldn't happen! */ + if (dfs == NULL) + return (0); + if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) + return (0); + + /* + * XXX For now, assume 20MHz wide - but this is incorrect when + * operating in half/quarter mode! + */ + return (20); +} + +/* + * Return the centre frequency for the current operating channel and + * event. + * + * This is for post-Owl 11n chips which report pri/extension channel + * events. + */ +static inline uint16_t +dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc) +{ + struct ieee80211com *ic; + int chan_offset = 0, chan_width; + + /* Handle edge cases during startup/transition, shouldn't happen! */ + if (dfs == NULL) + return (0); + if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) + return (0); + + ic = dfs->ic; + + /* + * + * For wide channels, DC and ext frequencies need a bit of hand-holding + * based on whether it's an upper or lower channel. + */ + chan_width = dfs_get_event_freqwidth(dfs); + + if (IEEE80211_IS_CHAN_11N_HT40PLUS(ic->ic_curchan)) + chan_offset = chan_width; + else if (IEEE80211_IS_CHAN_11N_HT40MINUS(ic->ic_curchan)) + chan_offset = -chan_width; + else + chan_offset = 0; + + /* + * Check for DC events first - the sowl code may just set all + * the bits together.. + */ + if (is_dc) { + /* + * XXX TODO: Should DC events be considered 40MHz wide here? + */ + return (ieee80211_chan2freq(ic, ic->ic_curchan) + + (chan_offset / 2)); + } + + /* + * For non-wide channels, the centre frequency is just ic_freq. + * The centre frequency for pri events is still ic_freq. + */ + if (is_pri) { + return (ieee80211_chan2freq(ic, ic->ic_curchan)); + } + + if (is_ext) { + return (ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width); + } + + /* XXX shouldn't get here */ + return (ieee80211_chan2freq(ic, ic->ic_curchan)); +} + +/* + * Process an Owl-style phy error. + * + * Return 1 on success or 0 on failure. + */ +int +dfs_process_phyerr_owl(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, u_int64_t fulltsf, + struct dfs_phy_err *e) +{ + const char *cbuf = (const char *) buf; + u_int8_t dur; + int event_width; + + /* XXX this shouldn't be kept count here */ + dfs->ath_dfs_stats.owl_phy_errors++; + + /* + * HW cannot detect extension channel radar so it only passes us + * primary channel radar data + */ + if (datalen == 0) + dur = 0; + else + dur = ((u_int8_t *) cbuf)[0]; + + /* + * This is a spurious event; toss. + */ + if (rssi == 0 && dur == 0) + dfs->ath_dfs_stats.datalen_discards++; + return (0); + + /* + * Fill out dfs_phy_err with the information we have + * at hand. + */ + OS_MEMSET(e, 0, sizeof(*e)); + e->rssi = rssi; + e->dur = dur; + e->is_pri = 1; + e->is_ext = 0; + e->is_dc = 0; + e->is_early = 1; + e->fulltsf = fulltsf; + e->rs_tstamp = rs_tstamp; + + /* + * Owl only ever reports events on the primary channel; + * it doesn't even see events on the secondary channel. + */ + event_width = dfs_get_event_freqwidth(dfs); + e->freq = dfs_get_event_freqcentre(dfs, 1, 0, 0) * 1000; + e->freq_lo = e->freq - (event_width / 2) * 1000; + e->freq_hi = e->freq + (event_width / 2) * 1000; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, + "%s: rssi=%u dur=%u, freq=%d MHz, freq_lo=%d MHz, " + "freq_hi=%d MHz\n", + __func__, + rssi, + dur, + e->freq / 1000, + e->freq_lo / 1000, + e->freq_hi / 1000); + + return (1); +} + +/* + * Process a Sowl/Howl style phy error. + */ +int +dfs_process_phyerr_sowl(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, u_int64_t fulltsf, + struct dfs_phy_err *e) +{ +#define EXT_CH_RADAR_FOUND 0x02 +#define PRI_CH_RADAR_FOUND 0x01 +#define EXT_CH_RADAR_EARLY_FOUND 0x04 + const char *cbuf = (const char *) buf; + u_int8_t dur = 0; + u_int8_t pulse_bw_info, pulse_length_ext, pulse_length_pri; + int pri_found, ext_found; + int early_ext = 0; + int event_width; + + /* + * If radar can be detected on the extension channel, datalen zero + * pulses are bogus, discard them. + */ + if (!datalen) { + dfs->ath_dfs_stats.datalen_discards++; + return (0); + } + + /* Ensure that we have at least three bytes of payload */ + if (datalen < 3) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: short error frame (%d bytes)\n", + __func__, datalen); + dfs->ath_dfs_stats.datalen_discards++; + return (0); + } + + /* + * Fetch the payload directly - the compiler will happily generate + * byte-read instructions with a const char * cbuf pointer. + */ + pulse_length_pri = cbuf[datalen - 3]; + pulse_length_ext = cbuf[datalen - 2]; + pulse_bw_info = cbuf[datalen - 1]; + + /* + * Only the last 3 bits of the BW info are relevant, they indicate + * which channel the radar was detected in. + */ + pulse_bw_info &= 0x07; + + /* + * If pulse on DC, both primary and extension flags will be set + */ + if (((pulse_bw_info & EXT_CH_RADAR_FOUND) && + (pulse_bw_info & PRI_CH_RADAR_FOUND))) { + /* + * Conducted testing, when pulse is on DC, both + * pri and ext durations are reported to be same. + * + * Radiated testing, when pulse is on DC, different + * pri and ext durations are reported, so take the + * larger of the two + */ + if (pulse_length_ext >= pulse_length_pri) { + dur = pulse_length_ext; + ext_found = 1; + } else { + dur = pulse_length_pri; + pri_found = 1; + } + dfs->ath_dfs_stats.dc_phy_errors++; + } else { + if (pulse_bw_info & EXT_CH_RADAR_FOUND) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + dfs->ath_dfs_stats.ext_phy_errors++; + } + if (pulse_bw_info & PRI_CH_RADAR_FOUND) { + dur = pulse_length_pri; + pri_found = 1; + ext_found = 0; + dfs->ath_dfs_stats.pri_phy_errors++; + } + if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + early_ext = 1; + dfs->ath_dfs_stats.early_ext_phy_errors++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "EARLY ext channel dur=%u rssi=%u datalen=%d\n", + dur, rssi, datalen); + } + if (! pulse_bw_info) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "ERROR channel dur=%u rssi=%u pulse_bw_info=0x%x " + "datalen MOD 4 = %d\n", + dur, rssi, pulse_bw_info, + (datalen & 0x3)); + /* + * Bogus bandwidth info received in descriptor, + * so ignore this PHY error + */ + dfs->ath_dfs_stats.bwinfo_errors++; + return (0); + } + } + + /* + * Always use combined RSSI reported, unless RSSI reported on + * extension is stronger + */ + if ((ext_rssi > rssi) && (ext_rssi < 128)) { + rssi = ext_rssi; + } + + /* + * Fill out the rssi/duration fields from above. + */ + OS_MEMSET(e, 0, sizeof(*e)); + e->rssi = rssi; + e->dur = dur; + e->is_pri = pri_found; + e->is_ext = ext_found; + e->is_dc = !! (((pulse_bw_info & EXT_CH_RADAR_FOUND) && + (pulse_bw_info & PRI_CH_RADAR_FOUND))); + e->is_early = early_ext; + e->fulltsf = fulltsf; + e->rs_tstamp = rs_tstamp; + + /* + * Sowl and later can report pri/ext events. + */ + event_width = dfs_get_event_freqwidth(dfs); + e->freq = + dfs_get_event_freqcentre(dfs, e->is_pri, e->is_ext, e->is_dc) + * 1000; + e->freq_lo = e->freq - (event_width / 2) * 1000; + e->freq_hi = e->freq + (event_width / 2) * 1000; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, + "%s: pulse_bw_info=0x%x pulse_length_ext=%u pulse_length_pri=%u " + "rssi=%u ext_rssi=%u, freq=%d MHz, freq_lo=%d MHz, " + "freq_hi=%d MHz\n", + __func__, + pulse_bw_info, + pulse_length_ext, + pulse_length_pri, + rssi, + ext_rssi, + e->freq / 1000, + e->freq_lo / 1000, + e->freq_hi / 1000); + + return (1); +} + +/* + * Process a Merlin/Osprey style phy error. + */ +int +dfs_process_phyerr_merlin(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, + u_int64_t fulltsf, struct dfs_phy_err *e) +{ + const char *cbuf = (const char *) buf; + u_int8_t pulse_bw_info = 0; + + /* + * Process using the sowl code + */ + if (! dfs_process_phyerr_sowl(dfs, buf, datalen, rssi, ext_rssi, + rs_tstamp, fulltsf, e)) { + return (0); + } + + /* + * For osprey (and Merlin) bw_info has implication for selecting + * RSSI value. So re-fetch the bw_info field so the RSSI values + * can be appropriately overridden. + */ + pulse_bw_info = cbuf[datalen - 1]; + + switch (pulse_bw_info & 0x03) { + case 0x00: + /* No radar in ctrl or ext channel */ + rssi = 0; + break; + case 0x01: + /* radar in ctrl channel */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "RAW RSSI: rssi=%u ext_rssi=%u\n", + rssi, ext_rssi); + if (ext_rssi >= (rssi + 3)) { + /* + * cannot use ctrl channel RSSI if + * extension channel is stronger + */ + rssi = 0; + } + break; + case 0x02: + /* radar in extension channel */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "RAW RSSI: rssi=%u ext_rssi=%u\n", + rssi, ext_rssi); + if (rssi >= (ext_rssi + 12)) { + /* + * cannot use extension channel RSSI if control channel + * is stronger + */ + rssi = 0; + } else { + rssi = ext_rssi; + } + break; + case 0x03: + /* when both are present use stronger one */ + if (rssi < ext_rssi) { + rssi = ext_rssi; + } + break; + } + + /* + * Override the rssi decision made by the sowl code. + * The rest of the fields (duration, timestamp, etc) + * are left untouched. + */ + e->rssi = rssi; + + return(1); +} + +static void +dump_phyerr_contents(const char *d, int len) +{ + int i, n, bufsize = 64; + + /* + * This is statically sized for a 4-digit address + 16 * 2 digit + * data string. + * + * It's done so the printk() passed to the kernel is an entire + * line, so the kernel logging code will atomically print it. + * Otherwise we'll end up with interleaved lines with output + * from other kernel threads. + */ + char buf[64]; + + /* Initial conditions */ + buf[0] = '\n'; + n = 0; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) { + n += snprintf(buf + n, bufsize - n, + "%04x: ", i); + } + n += snprintf(buf + n, bufsize - n, "%02x ", d[i] & 0xff); + if (i % 16 == 15) { + n = 0; + buf[0] = '\0'; + } + } + + /* + * Print the final line if we didn't print it above. + */ + if (n != 0) + printk("%s: %s\n", __func__, buf); +} + +void +dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen, + u_int8_t r_rssi, u_int8_t r_ext_rssi, u_int32_t r_rs_tstamp, + u_int64_t r_fulltsf) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct ieee80211_channel *chan=ic->ic_curchan; + struct dfs_event *event; + struct dfs_phy_err e; + int empty; + + + dfs->dfs_phyerr_count++; + //dump_phyerr_contents(buf, datalen); + /* + * XXX The combined_rssi_ok support has been removed. + * This was only clear for Owl. + * + * XXX TODO: re-add this; it requires passing in the ctl/ext + * RSSI set from the RX status descriptor. + * + * XXX TODO TODO: this may be done for us from the legacy + * phy error path in ath_dev; please review that code. + */ + + /* + * At this time we have a radar pulse that we need to examine and + * queue. But if dfs_process_radarevent already detected radar and set + * CHANNEL_INTERFERENCE flag then do not queue any more radar data. + * When we are in a new channel this flag will be clear and we will + * start queueing data for new channel. (EV74162) + */ + if (dfs->dfs_debug_mask & ATH_DEBUG_DFS_PHYERR_PKT) + //dump_phyerr_contents(buf, datalen); + + if (IEEE80211_IS_CHAN_RADAR(chan)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: Radar already found in the channel, " + " do not queue radar data\n", + __func__); + return; + } + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n",__func__); + return; + } + dfs->ath_dfs_stats.total_phy_errors++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s[%d] phyerr %d len %d\n", + __func__, __LINE__, + dfs->ath_dfs_stats.total_phy_errors, datalen); + + /* + * hardware stores this as 8 bit signed value. + * we will cap it at 0 if it is a negative number + */ + if (r_rssi & 0x80) + r_rssi = 0; + + if (r_ext_rssi & 0x80) + r_ext_rssi = 0; + + OS_MEMSET(&e, 0, sizeof(e)); + + /* + * This is a bit evil - instead of just passing in + * the chip version, the existing code uses a set + * of HAL capability bits to determine what is + * possible. + * + * The way I'm decoding it is thus: + * + * + DFS enhancement? Merlin or later + * + DFS extension channel? Sowl or later. (Howl?) + * + otherwise, Owl (and legacy.) + */ + if (dfs->dfs_caps.ath_chip_is_bb_tlv) { + if (dfs_process_phyerr_bb_tlv(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0) { + dfs->dfs_phyerr_reject_count++; + return; + } else { + if (dfs->dfs_phyerr_freq_min > e.freq) + dfs->dfs_phyerr_freq_min = e. freq; + + if (dfs->dfs_phyerr_freq_max < e.freq) + dfs->dfs_phyerr_freq_max = e. freq; + } + } else if (dfs->dfs_caps.ath_dfs_use_enhancement) { + if (dfs_process_phyerr_merlin(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0){ + return; + } + } else if (dfs->dfs_caps.ath_dfs_ext_chan_ok) { + if (dfs_process_phyerr_sowl(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0){ + return; + } + } else { + if (dfs_process_phyerr_owl(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0){ + return; + } + } + + /* + * If the hardware supports radar reporting on the extension channel + * it will supply FFT data for longer radar pulses. + * + * TLV chips don't go through this software check - the hardware + * check should be enough. If we want to do software checking + * later on then someone will have to craft an FFT parser + * suitable for the TLV FFT data format. + */ + if ((! dfs->dfs_caps.ath_chip_is_bb_tlv) && + dfs->dfs_caps.ath_dfs_ext_chan_ok) { + /* + * HW has a known issue with chirping pulses injected at or + * around DC in 40MHz mode. Such pulses are reported with + * much lower durations and SW then discards them because + * they do not fit the minimum bin5 pulse duration. + * + * To work around this issue, if a pulse is within a 10us + * range of the bin5 min duration, check if the pulse is + * chirping. If the pulse is chirping, bump up the duration + * to the minimum bin5 duration. + * + * This makes sure that a valid chirping pulse will not be + * discarded because of incorrect low duration. + * + * TBD - Is it possible to calculate the 'real' duration of + * the pulse using the slope of the FFT data? + * + * TBD - Use FFT data to differentiate between radar pulses + * and false PHY errors. + * This will let us reduce the number of false alarms seen. + * + * BIN 5 chirping pulses are only for FCC or Japan MMK4 domain + */ + if (((dfs->dfsdomain == DFS_FCC_DOMAIN) || + (dfs->dfsdomain == DFS_MKK4_DOMAIN)) && + (e.dur >= MAYBE_BIN5_DUR) && (e.dur < MAX_BIN5_DUR)) { + int add_dur; + int slope = 0, dc_found = 0; + + /* + * Set the event chirping flags; as we're doing + * an actual chirp check. + */ + e.do_check_chirp = 1; + e.is_hw_chirp = 0; + e.is_sw_chirp = 0; + + /* + * dfs_check_chirping() expects is_pri and is_ext + * to be '1' for true and '0' for false for now, + * as the function itself uses these values in + * constructing things rather than testing them + * for 'true' or 'false'. + */ + add_dur = dfs_check_chirping(dfs, buf, datalen, + (e.is_pri ? 1 : 0), + (e.is_ext ? 1 : 0), + &slope, &dc_found); + if (add_dur) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "old dur %d slope =%d\n", e.dur, slope); + e.is_sw_chirp = 1; + // bump up to a random bin5 pulse duration + if (e.dur < MIN_BIN5_DUR) { + e.dur = dfs_get_random_bin5_dur(dfs, + e.fulltsf); + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "new dur %d\n", e.dur); + } else { + /* set the duration so that it is rejected */ + e.is_sw_chirp = 0; + e.dur = MAX_BIN5_DUR + 100; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "is_chirping = %d dur=%d \n", + add_dur, e.dur); + } + } else { + /* + * We have a pulse that is either bigger than + * MAX_BIN5_DUR or * less than MAYBE_BIN5_DUR + */ + if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || + (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { + /* + * XXX Would this result in very large pulses + * wrapping around to become short pulses? + */ + if (e.dur >= MAX_BIN5_DUR) { + /* + * set the duration so that it is + * rejected + */ + e.dur = MAX_BIN5_DUR + 50; + } + } + } + } + + /* + * Add the parsed, checked and filtered entry to the radar pulse + * event list. This is then checked by dfs_radar_processevent(). + * + * XXX TODO: some filtering is still done below this point - fix + * XXX this! + */ + ATH_DFSEVENTQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_eventq)); + ATH_DFSEVENTQ_UNLOCK(dfs); + if (empty) { + return; + } + + /* + * If the channel is a turbo G channel, then the event is + * for the adaptive radio (AR) pattern matching rather than + * radar detection. + */ + if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) { + if (!(dfs->dfs_proc_phyerr & DFS_AR_EN)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s: DFS_AR_EN not enabled\n", + __func__); + return; + } + ATH_DFSEVENTQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_eventq)); + if (event == NULL) { + ATH_DFSEVENTQ_UNLOCK(dfs); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: no more events space left\n", + __func__); + return; + } + STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + event->re_rssi = e.rssi; + event->re_dur = e.dur; + event->re_full_ts = e.fulltsf; + event->re_ts = (e.rs_tstamp) & DFS_TSMASK; + event->re_chanindex = dfs->dfs_curchan_radindex; + event->re_flags = 0; + + /* + * Handle chirp flags. + */ + if (e.do_check_chirp) { + event->re_flags |= DFS_EVENT_CHECKCHIRP; + if (e.is_hw_chirp) + event->re_flags |= DFS_EVENT_HW_CHIRP; + if (e.is_sw_chirp) + event->re_flags |= DFS_EVENT_SW_CHIRP; + } + + ATH_ARQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_arq), event, re_list); + ATH_ARQ_UNLOCK(dfs); + } else { + if (IEEE80211_IS_CHAN_DFS(chan)) { + if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "%s: DFS_RADAR_EN not enabled\n", + __func__); + return; + } + /* + * rssi is not accurate for short pulses, so do + * not filter based on that for short duration pulses + * + * XXX do this filtering above? + */ + if (dfs->dfs_caps.ath_dfs_ext_chan_ok) { + if ((e.rssi < dfs->dfs_rinfo.rn_minrssithresh && + (e.dur > 4)) || + e.dur > (dfs->dfs_rinfo.rn_maxpulsedur) ) { + dfs->ath_dfs_stats.rssi_discards++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "Extension channel pulse is " + "discarded: dur=%d, " + "maxpulsedur=%d, rssi=%d, " + "minrssi=%d\n", + e.dur, + dfs->dfs_rinfo.rn_maxpulsedur, + e.rssi, + dfs->dfs_rinfo.rn_minrssithresh); + return; + } + } else { + if (e.rssi < dfs->dfs_rinfo.rn_minrssithresh || + e.dur > dfs->dfs_rinfo.rn_maxpulsedur) { + /* XXX TODO add a debug statement? */ + dfs->ath_dfs_stats.rssi_discards++; + return; + } + } + + /* + * Add the event to the list, if there's space. + */ + ATH_DFSEVENTQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_eventq)); + if (event == NULL) { + ATH_DFSEVENTQ_UNLOCK(dfs); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: no more events space left\n", + __func__); + return; + } + STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + + dfs->dfs_phyerr_queued_count++; + dfs->dfs_phyerr_w53_counter++; + + event->re_dur = e.dur; + event->re_full_ts = e.fulltsf; + event->re_ts = (e.rs_tstamp) & DFS_TSMASK; + event->re_rssi = e.rssi; + + /* + * Handle chirp flags. + */ + if (e.do_check_chirp) { + event->re_flags |= DFS_EVENT_CHECKCHIRP; + if (e.is_hw_chirp) + event->re_flags |= DFS_EVENT_HW_CHIRP; + if (e.is_sw_chirp) + event->re_flags |= DFS_EVENT_SW_CHIRP; + } + + /* + * Correctly set which channel is being reported on + */ + if (e.is_pri) { + event->re_chanindex = dfs->dfs_curchan_radindex; + } else { + if (dfs->dfs_extchan_radindex == -1) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s - phyerr on ext channel\n", __func__); + } + event->re_chanindex = dfs->dfs_extchan_radindex; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s New extension channel event is added " + "to queue\n",__func__); + } + ATH_DFSQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); + ATH_DFSQ_UNLOCK(dfs); + } + } + + /* + * Schedule the radar/AR task as appropriate. + * + * XXX isn't a lock needed for ath_radar_tasksched? + */ + +/* +* Commenting out the dfs_process_ar_event() since the function is never +* called at run time as dfs_arq will be empty and the function +* dfs_process_ar_event is obsolete and function definition is removed +* as part of dfs_ar.c file +* +* if (!STAILQ_EMPTY(&dfs->dfs_arq)) +* // XXX shouldn't this be a task/timer too? +* dfs_process_ar_event(dfs, ic->ic_curchan); +*/ + + if (!STAILQ_EMPTY(&dfs->dfs_radarq) && !dfs->ath_radar_tasksched) { + dfs->ath_radar_tasksched = 1; + OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0); + } +#undef EXT_CH_RADAR_FOUND +#undef PRI_CH_RADAR_FOUND +#undef EXT_CH_RADAR_EARLY_FOUND +} +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/DFS/src/dfs_process_radarevent.c b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c new file mode 100644 index 000000000000..adb9ad37bcdf --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_process_radarevent.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_radarevent.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifdef ATH_SUPPORT_DFS + +#define FREQ_5500_MHZ 5500 +#define FREQ_5500_MHZ 5500 + +#define DFS_MAX_FREQ_SPREAD 1375 * 1 +#define DFS_LARGE_PRI_MULTIPLIER 4 +#define DFS_W53_DEFAULT_PRI_MULTIPLIER 2 + +static char debug_dup[33]; +static int debug_dup_cnt; + +/* + * Convert the hardware provided duration to TSF ticks (usecs) + * taking the clock (fast or normal) into account. + * + * Legacy (pre-11n, Owl, Sowl, Howl) operate 5GHz using a 40MHz + * clock. Later 11n chips (Merlin, Osprey, etc) operate 5GHz using + * a 44MHz clock, so the reported pulse durations are different. + * + * Peregrine reports the pulse duration in microseconds regardless + * of the operating mode. (XXX TODO: verify this, obviously.) + */ +static inline u_int8_t +dfs_process_pulse_dur(struct ath_dfs *dfs, u_int8_t re_dur) +{ + /* + * Short pulses are sometimes returned as having a duration of 0, + * so round those up to 1. + * + * XXX This holds true for BB TLV chips too, right? + */ + if (re_dur == 0) + return 1; + + /* + * For BB TLV chips, the hardware always returns microsecond + * pulse durations. + */ + if (dfs->dfs_caps.ath_chip_is_bb_tlv) + return re_dur; + + /* + * This is for 11n and legacy chips, which may or may not + * use the 5GHz fast clock mode. + */ + /* Convert 0.8us durations to TSF ticks (usecs) */ + return (u_int8_t)dfs_round((int32_t)((dfs->dur_multiplier)*re_dur)); +} + +/* + * Process a radar event. + * + * If a radar event is found, return 1. Otherwise, return 0. + * + * There is currently no way to specify that a radar event has occured on + * a specific channel, so the current methodology is to mark both the pri + * and ext channels as being unavailable. This should be fixed for 802.11ac + * or we'll quickly run out of valid channels to use. + */ +int +dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) +{ +//commenting for now to validate radar indication msg to SAP +//#if 0 + struct dfs_event re,*event; + struct dfs_state *rs=NULL; + struct dfs_filtertype *ft; + struct dfs_filter *rf; + int found, retval = 0, p, empty; + int events_processed = 0; + u_int32_t tabledepth, index; + u_int64_t deltafull_ts = 0, this_ts, deltaT; + struct ieee80211_channel *thischan; + struct dfs_pulseline *pl; + static u_int32_t test_ts = 0; + static u_int32_t diff_ts = 0; + int ext_chan_event_flag = 0; +#if 0 + int pri_multiplier = 2; +#endif + int i; + + if (dfs == NULL) { + printk("%s[%d]: --------- dfs is NULL ------- \n",__func__,__LINE__); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_sfs is NULL\n", + __func__); + return 0; + } + pl = dfs->pulses; + if ( !(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: radar event on non-DFS chan\n", + __func__); + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + return 0; + } +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + /* TEST : Simulate radar bang, make sure we add the channel to NOL (bug 29968) */ + if (dfs->dfs_bangradar) { + /* bangradar will always simulate radar found on the primary channel */ + rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; + dfs->dfs_bangradar = 0; /* reset */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: bangradar\n", __func__); + retval = 1; + goto dfsfound; + } +#endif + + /* + The HW may miss some pulses especially with high channel loading. + This is true for Japan W53 where channel loaoding is 50%. Also + for ETSI where channel loading is 30% this can be an issue too. + To take care of missing pulses, we introduce pri_margin multiplie. + This is normally 2 but can be higher for W53. + */ + + if ((dfs->dfsdomain == DFS_MKK4_DOMAIN) && + (dfs->dfs_caps.ath_chip_is_bb_tlv) && + (chan->ic_freq < FREQ_5500_MHZ)) { + + dfs->dfs_pri_multiplier = DFS_W53_DEFAULT_PRI_MULTIPLIER; + /* do not process W53 pulses unless we have a minimum number of them */ + if (dfs->dfs_phyerr_w53_counter >= 5) { + /* + for chips that support frequency information, we can + relax PRI restriction if the frequency + spread is narrow. + */ + if ((dfs->dfs_phyerr_freq_max - dfs->dfs_phyerr_freq_min) < DFS_MAX_FREQ_SPREAD) { + dfs->dfs_pri_multiplier = DFS_LARGE_PRI_MULTIPLIER; + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d\n", + __func__, + dfs->dfs_phyerr_w53_counter, + dfs->dfs_phyerr_freq_max, + dfs->dfs_phyerr_freq_min, + dfs->dfs_pri_multiplier); + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + } else { + return 0; + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: pri_multiplier=%d\n", __func__, dfs->dfs_pri_multiplier); + + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + + while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) { + ATH_DFSQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_radarq)); + if (event != NULL) + STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); + ATH_DFSQ_UNLOCK(dfs); + + if (event == NULL) { + empty = 1; + printk("%s[%d]: event is NULL \n",__func__,__LINE__); + break; + } + events_processed++; + re = *event; + + OS_MEMZERO(event, sizeof(struct dfs_event)); + ATH_DFSEVENTQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + + found = 0; + if (re.re_chanindex < DFS_NUM_RADAR_STATES) + rs = &dfs->dfs_radar[re.re_chanindex]; + else { + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + if (rs->rs_chan.ic_flagext & CHANNEL_INTERFERENCE) { + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + + if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { + /* + * Either not started, or 64-bit rollover exactly to zero + * Just prepend zeros to the 15-bit ts + */ + dfs->dfs_rinfo.rn_ts_prefix = 0; + } else { + /* WAR 23031- patch duplicate ts on very short pulses */ + /* This pacth has two problems in linux environment. + * 1)The time stamp created and hence PRI depends entirely on the latency. + * If the latency is high, it possibly can split two consecutive + * pulses in the same burst so far away (the same amount of latency) + * that make them look like they are from differenct bursts. It is + * observed to happen too often. It sure makes the detection fail. + * 2)Even if the latency is not that bad, it simply shifts the duplicate + * timestamps to a new duplicate timestamp based on how they are processed. + * This is not worse but not good either. + * + * Take this pulse as a good one and create a probable PRI later + */ + if (re.re_dur == 0 && re.re_ts == dfs->dfs_rinfo.rn_last_unique_ts) { + debug_dup[debug_dup_cnt++] = '1'; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "\n %s deltaT is 0 \n", __func__); + } else { + dfs->dfs_rinfo.rn_last_unique_ts = re.re_ts; + debug_dup[debug_dup_cnt++] = '0'; + } + if (debug_dup_cnt >= 32){ + debug_dup_cnt = 0; + } + + + if (re.re_ts <= dfs->dfs_rinfo.rn_last_ts) { + dfs->dfs_rinfo.rn_ts_prefix += + (((u_int64_t) 1) << DFS_TSSHIFT); + /* Now, see if it's been more than 1 wrap */ + deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; + if (deltafull_ts > + ((u_int64_t)((DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts))) + deltafull_ts -= (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts; + deltafull_ts = deltafull_ts >> DFS_TSSHIFT; + if (deltafull_ts > 1) { + dfs->dfs_rinfo.rn_ts_prefix += + ((deltafull_ts - 1) << DFS_TSSHIFT); + } + } else { + deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; + if (deltafull_ts > (u_int64_t) DFS_TSMASK) { + deltafull_ts = deltafull_ts >> DFS_TSSHIFT; + dfs->dfs_rinfo.rn_ts_prefix += + ((deltafull_ts - 1) << DFS_TSSHIFT); + } + } + } + /* + * At this stage rn_ts_prefix has either been blanked or + * calculated, so it's safe to use. + */ + this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((u_int64_t) re.re_ts); + dfs->dfs_rinfo.rn_lastfull_ts = re.re_full_ts; + dfs->dfs_rinfo.rn_last_ts = re.re_ts; + + /* + * The hardware returns the duration in a variety of formats, + * so it's converted from the hardware format to TSF (usec) + * values here. + * + * XXX TODO: this should really be done when the PHY error + * is processed, rather than way out here.. + */ + re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur); + + /* + * Calculate the start of the radar pulse. + * + * The TSF is stamped by the MAC upon reception of the + * event, which is (typically?) at the end of the event. + * But the pattern matching code expects the event timestamps + * to be at the start of the event. So to fake it, we + * subtract the pulse duration from the given TSF. + * + * This is done after the 64-bit timestamp has been calculated + * so long pulses correctly under-wrap the counter. Ie, if + * this was done on the 32 (or 15!) bit TSF when the TSF + * value is closed to 0, it will underflow to 0xfffffXX, which + * would mess up the logical "OR" operation done above. + * + * This isn't valid for Peregrine as the hardware gives us + * the actual TSF offset of the radar event, not just the MAC + * TSF of the completed receive. + * + * XXX TODO: ensure that the TLV PHY error processing + * code will correctly calculate the TSF to be the start + * of the radar pulse. + * + * XXX TODO TODO: modify the TLV parsing code to subtract + * the duration from the TSF, based on the current fast clock + * value. + */ + if ((! dfs->dfs_caps.ath_chip_is_bb_tlv) && re.re_dur != 1) { + this_ts -= re.re_dur; + } + + /* Save the pulse parameters in the pulse buffer(pulse line) */ + index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; + if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) + pl->pl_firstelem = (pl->pl_firstelem+1) & DFS_MAX_PULSE_BUFFER_MASK; + else + pl->pl_numelems++; + pl->pl_lastelem = index; + pl->pl_elems[index].p_time = this_ts; + pl->pl_elems[index].p_dur = re.re_dur; + pl->pl_elems[index].p_rssi = re.re_rssi; + diff_ts = (u_int32_t)this_ts - test_ts; + test_ts = (u_int32_t)this_ts; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,"ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu\n",(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time); + if (dfs->dfs_event_log_on) { + i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE; + dfs->radar_log[i].ts = this_ts; + dfs->radar_log[i].diff_ts = diff_ts; + dfs->radar_log[i].rssi = re.re_rssi; + dfs->radar_log[i].dur = re.re_dur; + dfs->dfs_event_log_count++; + } + printk("%s[%d]:xxxxx ts =%u re.re_dur=%u re.re_rssi =%u diff =%u pl->pl_lastelem.p_time=%llu xxxxx\n",__func__,__LINE__,(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (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 + * from adjacent channel. In order to prevent false alarms we + * clear the delay-lines. This might impact positive detections under + * harsh environments, but helps with false detects. */ + + if (diff_ts < 100) { + dfs_reset_alldelaylines(dfs); + dfs_reset_radarq(dfs); + } + found = 0; + + /* BIN5 pulses are FCC and Japan specific */ + + if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { + for (p=0; (p < dfs->dfs_rinfo.rn_numbin5radars) && (!found); p++) { + struct dfs_bin5radars *br; + + br = &(dfs->dfs_b5radars[p]); + if (dfs_bin5_check_pulse(dfs, &re, br)) { + // This is a valid Bin5 pulse, check if it belongs to a burst + re.re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts, re.re_dur); + // Remember our computed duration for the next pulse in the burst (if needed) + dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts; + dfs->dfs_rinfo.dfs_last_bin5_dur = re.re_dur; + + if( dfs_bin5_addpulse(dfs, br, &re, this_ts) ) { + found |= dfs_bin5_check(dfs); + } + } else{ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_PULSE, + "%s not a BIN5 pulse (dur=%d)\n", + __func__, re.re_dur); + } + } + } + + if (found) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Found bin5 radar\n", __func__); + retval |= found; + goto dfsfound; + } + + tabledepth = 0; + rf = NULL; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1," *** chan freq (%d): ts %llu dur %u rssi %u\n", + rs->rs_chan.ic_freq, (unsigned long long)this_ts, re.re_dur, re.re_rssi); + + 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])]; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2," ** RD (%d): ts %x dur %u rssi %u\n", + rs->rs_chan.ic_freq, + re.re_ts, re.re_dur, re.re_rssi); + + if (re.re_rssi < ft->ft_rssithresh && re.re_dur > 4) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,"%s : Rejecting on rssi rssi=%u thresh=%u\n", __func__, re.re_rssi, ft->ft_rssithresh); + printk("%s[%d]: Rejecting on rssi rssi=%u thresh=%u\n",__func__,__LINE__,re.re_rssi, ft->ft_rssithresh); + tabledepth++; + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + deltaT = this_ts - ft->ft_last_ts; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,"deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)\n",(unsigned long long)deltaT, (unsigned long long)this_ts, (unsigned long long)ft->ft_last_ts); + 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.*/ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: Rejecting on pri pri=%lld minpri=%u\n", __func__, (unsigned long long)deltaT, ft->ft_minpri); + printk("%s[%d]:Rejecting on pri pri=%lld minpri=%u\n",__func__,__LINE__,(unsigned long long)deltaT,ft->ft_minpri); + 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)) { + /* The above check is probably not necessary */ + 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. */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u\n", + rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + printk("%s[%d]:filterID= %d::Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u\n",__func__,__LINE__,rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + continue; + } + + if (rf->rf_ignore_pri_window > 0) { + if (deltaT < rf->rf_minpri) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n", + rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + printk("%s[%d]:filterID= %d :: Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n",__func__,__LINE__,rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + /* But update the last time stamp */ + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + } else { + + /* + The HW may miss some pulses especially with high channel loading. + This is true for Japan W53 where channel loaoding is 50%. Also + for ETSI where channel loading is 30% this can be an issue too. + To take care of missing pulses, we introduce pri_margin multiplie. + This is normally 2 but can be higher for W53. + */ + + if ( (deltaT > (dfs->dfs_pri_multiplier * rf->rf_maxpri) ) || (deltaT < rf->rf_minpri) ) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n", + rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); +printk("%s[%d]:filterID= %d :: Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n",__func__,__LINE__,rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + /* But update the last time stamp */ + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + } + dfs_add_pulse(dfs, rf, &re, deltaT, this_ts); + + + /* 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, (u_int32_t) deltaT, re.re_dur); + } else { + found = dfs_bin_check(dfs, rf, (u_int32_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; + } + } + ft->ft_last_ts = this_ts; + retval |= found; + if (found) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "Found on channel minDur = %d, filterId = %d\n",ft->ft_mindur, + rf != NULL ? rf->rf_pulseid : -1); + } + tabledepth++; + } + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + } +dfsfound: + if (retval) { + /* Collect stats */ + dfs->ath_dfs_stats.num_radar_detects++; + thischan = &rs->rs_chan; + printk("%s[%d]: ########################## Radar found on channel %d (%d MHz) ########################## \n",__func__,__LINE__,thischan->ic_ieee, +thischan->ic_freq); + DFS_PRINTK("Radar found on channel %d (%d MHz)\n", + thischan->ic_ieee, + thischan->ic_freq); + +#if 0 //UMACDFS : TODO + /* Disable radar for now */ + rfilt = ath_hal_getrxfilter(ah); + rfilt &= ~HAL_RX_FILTER_PHYRADAR; + ath_hal_setrxfilter(ah, rfilt); +#endif + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + /* XXX Should we really enable again? Maybe not... */ +/* No reason to re-enable so far - Ajay*/ +#if 0 + pe.pe_firpwr = rs->rs_firpwr; + pe.pe_rrssi = rs->rs_radarrssi; + pe.pe_height = rs->rs_height; + pe.pe_prssi = rs->rs_pulserssi; + pe.pe_inband = rs->rs_inband; + /* 5413 specific */ + pe.pe_relpwr = rs->rs_relpwr; + pe.pe_relstep = rs->rs_relstep; + pe.pe_maxlen = rs->rs_maxlen; + + ath_hal_enabledfs(ah, &pe); + rfilt |= HAL_RX_FILTER_PHYRADAR; + ath_hal_setrxfilter(ah, rfilt); +#endif + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "Primary channel freq = %u flags=0x%x\n", + chan->ic_freq, chan->ic_flagext); + if ((dfs->ic->ic_curchan->ic_freq!= thischan->ic_freq)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "Ext channel freq = %u flags=0x%x\n", + thischan->ic_freq, thischan->ic_flagext); + } + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_w53_counter = 0; + } + //printk("IN FUNC %s[%d]: retval = %d \n",__func__,__LINE__,retval); + return retval; +//#endif +// return 1; +} + +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/DFS/src/dfs_staggered.c b/CORE/SERVICES/DFS/src/dfs_staggered.c new file mode 100644 index 000000000000..f5f9f49a45ae --- /dev/null +++ b/CORE/SERVICES/DFS/src/dfs_staggered.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_staggered.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include <ieee80211_var.h> +*/ +#ifdef ATH_SUPPORT_DFS + +static int is_pri_multiple(u_int32_t sample_pri, u_int32_t refpri) +{ +#define MAX_ALLOWED_MISSED 3 + int i; + + if (sample_pri < refpri || (!refpri)) + return 0; + + for (i=1; i<= MAX_ALLOWED_MISSED; i++) { + if((sample_pri%(i*refpri) <= 5)) { + //printk("sample_pri=%d is a multiple of refpri=%d\n", sample_pri, refpri); + return 1; + } + } + return 0; +#undef MAX_ALLOWED_MISSED +} + +static int is_unique_pri(u_int32_t highestpri , u_int32_t midpri, + u_int32_t lowestpri , u_int32_t refpri ) +{ +#define DFS_STAGGERED_PRI_MARGIN_MIN 20 +#define DFS_STAGGERED_PRI_MARGIN_MAX 400 + if ((DFS_DIFF(lowestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) && + (DFS_DIFF(midpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) && + (DFS_DIFF(highestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN)) { + return 1; + } else { + if ((is_pri_multiple(refpri, highestpri)) || (is_pri_multiple(refpri, lowestpri)) || + (is_pri_multiple(refpri, midpri))) + return 0; + } + return 0; +#undef DFS_STAGGERED_PRI_MARGIN_MIN +#undef DFS_STAGGERED_PRI_MARGIN_MAX +} + + +int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t deltaT, u_int32_t width) +{ + u_int32_t refpri, refdur, searchpri=0, deltapri;//, averagerefpri; + u_int32_t n, i, primargin, durmargin; + int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0; + struct dfs_delayline *dl; + u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff; +#if 0 + int numpulses=0; +#endif + int higherthan, lowerthan, numscores; + int numpulseshigh=0, numpulsesmid=0, numpulsestemp=0; + u_int32_t lowestscore=0, lowestscoreindex=0, lowestpri=0; + u_int32_t midscore=0, midscoreindex=0, midpri=0; + u_int32_t highestscore=0, highestscoreindex=0, highestpri=0; + + dl = &rf->rf_dl; + if( dl->dl_numelems < (rf->rf_threshold-1)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numelems %d < threshold for filter %d\n", + dl->dl_numelems, rf->rf_pulseid); + return 0; + } + if( deltaT > rf->rf_filterlen) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numelems %d < threshold for filter %d\n", + dl->dl_numelems, rf->rf_pulseid); + return 0; + } + primargin = 6; + if(rf->rf_maxdur < 10) { + durmargin = 4; + } + else { + durmargin = 6; + } + + OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE); + /* find out the lowest pri */ + for (n=0;n<dl->dl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) + continue; + else if(refpri < lowpri) { + lowpri = dl->dl_elems[delayindex].de_time; + lowpriindex = n; + } + } + /* find out the each delay element's pri score */ + for (n=0;n<dl->dl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) { + continue; + } + + if ( (refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri) ) { + score[n] = 0; + continue; + } + + for (i=0;i<dl->dl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + if( deltapri < primargin) + score[n]++; + } + } + for (n=0;n<dl->dl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "score[%d]=%d pri=%d\n", n, score[n], refdur); + } + + /* find out the 2 or 3 highest scorers */ + scoreindex = 0; + highestscore=0; + highestscoreindex=0; + highestpri=0; numscores=0; lowestscore=0; + + for (n=0;n<dl->dl_numelems; n++) { + higherthan=0; + lowerthan=0; + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + + if ((score[n] >= highestscore) && + (is_unique_pri(highestpri, midpri, lowestpri, refpri))) { + lowestscore = midscore; + lowestpri = midpri; + lowestscoreindex = midscoreindex; + midscore = highestscore; + midpri = highestpri; + midscoreindex = highestscoreindex; + highestscore = score[n]; + highestpri = refpri; + highestscoreindex = n; + } else { + if ((score[n] >= midscore) && + (is_unique_pri(highestpri, midpri, lowestpri, refpri))) { + lowestscore = midscore; + lowestpri = midpri; + lowestscoreindex = midscoreindex; + midscore = score[n]; + midpri = refpri; + midscoreindex = n; + } else if ((score[n] >= lowestscore) && + (is_unique_pri(highestpri, midpri, lowestpri, refpri))) { + lowestscore = score[n]; + lowestpri = refpri; + lowestscoreindex = n; + } + } + + } + + if (midscore == 0) { + // This means we have only 1 pulse type. It can not be staggered! + return 0; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "FINAL highestscore=%d highestscoreindex=%d highestpri=%d\n", + highestscore, highestscoreindex, highestpri); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "FINAL lowestscore=%d lowestscoreindex=%d lowpri=%d\n", + lowestscore, lowestscoreindex, lowestpri); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "FINAL midscore=%d midscoreindex=%d midpri=%d\n", + midscore, midscoreindex, midpri); + + + delayindex = (dl->dl_firstelem + highestscoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "highscoreindex=%d refdur=%d refpri=%d\n", + highestscoreindex, refdur, refpri); + + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur,0, highestpri); + numpulseshigh = numpulsestemp; + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur,0, highestpri + midpri); + if (numpulsestemp > numpulseshigh) { + numpulseshigh = numpulsestemp; + } + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur,0, highestpri + midpri + lowestpri); + if (numpulsestemp > numpulseshigh) { + numpulseshigh = numpulsestemp; + } + + + delayindex = (dl->dl_firstelem + midscoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "midscoreindex=%d refdur=%d refpri=%d\n", + midscoreindex, refdur, refpri); + + //numpulsesmid = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, 1); + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, midpri); + numpulsesmid = numpulsestemp; + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, highestpri + midpri); + if (numpulsestemp > numpulsesmid) { + numpulsesmid = numpulsestemp; + } + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, highestpri + midpri + lowestpri); + if (numpulsestemp > numpulsesmid) { + numpulsesmid = numpulsestemp; + } + + + /*delayindex = (dl->dl_firstelem + lowestscoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(ic, ATH_DEBUG_DFS1, "lowestscoreindex=%d refdur=%d refpri=%d\n", lowestscoreindex, refdur, refpri); + + numpulseslow = dfs_bin_pri_check(dfs, rf, dl, lowestscore, refpri, refdur,0, 1); + */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numpulseshigh=%d, numpulsesmid=%d\n", + numpulseshigh, numpulsesmid); +// printf("numpulseshigh=%d, numpulsesmid=%d, numpulseslow %d\n",numpulseshigh, numpulsesmid, numpulseslow); + + if ( (numpulseshigh >= rf->rf_threshold) && (numpulsesmid >= rf->rf_threshold) ) { + /*if (numpulses >= rf->rf_threshold) {*/ + found = 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "MATCH filter=%u numpulseshigh=%u numpulsesmid= %u thresh=%u\n", rf->rf_pulseid, numpulseshigh, numpulsesmid, rf->rf_threshold); + } + return found; + } + +#endif /* ATH_SUPPORT_DFS */ diff --git a/CORE/SERVICES/HIF/PCIe/ar6320def.h b/CORE/SERVICES/HIF/PCIe/ar6320def.h index a4b1f4dcf46f..d9de7b513298 100644 --- a/CORE/SERVICES/HIF/PCIe/ar6320def.h +++ b/CORE/SERVICES/HIF/PCIe/ar6320def.h @@ -26,7 +26,7 @@ */ #ifndef _AR6320DEF_H_ -#define AR6320__AR6320DEF_H_ +#define _AR6320DEF_H_ /* Base Addresses */ #define AR6320_RTC_SOC_BASE_ADDRESS 0x00000000 diff --git a/CORE/SERVICES/HIF/PCIe/ar6320v2def.h b/CORE/SERVICES/HIF/PCIe/ar6320v2def.h new file mode 100644 index 000000000000..b889eeb6f3dd --- /dev/null +++ b/CORE/SERVICES/HIF/PCIe/ar6320v2def.h @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320V2DEF_H_ +#define _AR6320V2DEF_H_ + +/* Base Addresses */ +#define AR6320V2_RTC_SOC_BASE_ADDRESS 0x00000800 +#define AR6320V2_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320V2_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320V2_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320V2_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320V2_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320V2_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320V2_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320V2_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320V2_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320V2_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320V2_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320V2_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320V2_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320V2_CE0_BASE_ADDRESS 0x00034400 +#define AR6320V2_CE1_BASE_ADDRESS 0x00034800 +#define AR6320V2_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320V2_CE3_BASE_ADDRESS 0x00035000 +#define AR6320V2_CE4_BASE_ADDRESS 0x00035400 +#define AR6320V2_CE5_BASE_ADDRESS 0x00035800 +#define AR6320V2_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320V2_CE7_BASE_ADDRESS 0x00036000 +#define AR6320V2_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320V2_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320V2_SCRATCH_3_ADDRESS 0x0028 +#define AR6320V2_TARG_DRAM_START 0x00400000 +#define AR6320V2_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320V2_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320V2_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320V2_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320V2_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320V2_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320V2_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320V2_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320V2_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320V2_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320V2_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320V2_SI_CONFIG_I2C_LSB 16 +#define AR6320V2_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320V2_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320V2_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320V2_SI_CONFIG_OFFSET 0x00000000 +#define AR6320V2_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320V2_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320V2_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320V2_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320V2_SI_CS_OFFSET 0x00000004 +#define AR6320V2_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320V2_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320V2_SI_CS_START_LSB 8 +#define AR6320V2_SI_CS_START_MASK 0x00000100 +#define AR6320V2_SI_CS_RX_CNT_LSB 4 +#define AR6320V2_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320V2_SI_CS_TX_CNT_LSB 0 +#define AR6320V2_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320V2_CE_COUNT 8 +#define AR6320V2_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320V2_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff + +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320V2_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320V2_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320V2_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320V2_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320V2_HOST_IS_ADDRESS 0x0030 +#define AR6320V2_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320V2_HOST_IE_ADDRESS 0x002c +#define AR6320V2_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_SR_BA_ADDRESS 0x0000 +#define AR6320V2_SR_SIZE_ADDRESS 0x0004 +#define AR6320V2_CE_CTRL1_ADDRESS 0x0010 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320V2_DR_BA_ADDRESS 0x0008 +#define AR6320V2_DR_SIZE_ADDRESS 0x000c +#define AR6320V2_MISC_IE_ADDRESS 0x0034 +#define AR6320V2_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320V2_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320V2_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320V2_SRC_WATERMARK_LOW_LSB 16 +#define AR6320V2_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320V2_DST_WATERMARK_LOW_LSB 16 +#define AR6320V2_DST_WATERMARK_HIGH_LSB 0 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320V2_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320V2_RTC_STATE_ADDRESS 0x0000 +#define AR6320V2_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320V2_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320V2_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320V2_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320V2_RTC_STATE_V_MASK 0x00000007 +#define AR6320V2_RTC_STATE_V_LSB 0 +#define AR6320V2_RTC_STATE_V_ON 3 +#define AR6320V2_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320V2_FW_IND_EVENT_PENDING 1 +#define AR6320V2_FW_IND_INITIALIZED 2 +#define AR6320V2_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320V2_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320V2_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320V2_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320V2_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320V2_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320V2_CPU_INTR_ADDRESS 0x0010 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320V2_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320V2_CORE_CTRL_ADDRESS 0x0000 +#define AR6320V2_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320V2_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320V2_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320V2_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320V2_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320V2_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320V2_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320V2_SOC_CHIP_ID_REVISION_LSB 8 + +#define AR6320V2_PCIE_INTR_CE_MASK(n) (AR6320V2_PCIE_INTR_CE0_MASK << (n)) +#define AR6320V2_DRAM_BASE_ADDRESS AR6320V2_TARG_DRAM_START +#define AR6320V2_FW_INDICATOR_ADDRESS (AR6320V2_SOC_CORE_BASE_ADDRESS + AR6320V2_SCRATCH_3_ADDRESS) +#define AR6320V2_SYSTEM_SLEEP_OFFSET AR6320V2_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320V2_WLAN_RESET_CONTROL_OFFSET AR6320V2_SOC_RESET_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_OFFSET AR6320V2_SOC_CLOCK_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320V2_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320V2_RESET_CONTROL_SI0_RST_MASK AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320V2_GPIO_BASE_ADDRESS AR6320V2_WLAN_GPIO_BASE_ADDRESS +#define AR6320V2_GPIO_PIN0_OFFSET AR6320V2_WLAN_GPIO_PIN0_ADDRESS +#define AR6320V2_GPIO_PIN1_OFFSET AR6320V2_WLAN_GPIO_PIN1_ADDRESS +#define AR6320V2_GPIO_PIN0_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320V2_GPIO_PIN1_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320V2_SI_BASE_ADDRESS 0x00050000 +#define AR6320V2_CPU_CLOCK_OFFSET AR6320V2_SOC_CPU_CLOCK_OFFSET +#define AR6320V2_LPO_CAL_OFFSET AR6320V2_SOC_LPO_CAL_OFFSET +#define AR6320V2_GPIO_PIN10_OFFSET AR6320V2_WLAN_GPIO_PIN10_ADDRESS +#define AR6320V2_GPIO_PIN11_OFFSET AR6320V2_WLAN_GPIO_PIN11_ADDRESS +#define AR6320V2_GPIO_PIN12_OFFSET AR6320V2_WLAN_GPIO_PIN12_ADDRESS +#define AR6320V2_GPIO_PIN13_OFFSET AR6320V2_WLAN_GPIO_PIN13_ADDRESS +#define AR6320V2_CPU_CLOCK_STANDARD_LSB AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320V2_CPU_CLOCK_STANDARD_MASK AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320V2_LPO_CAL_ENABLE_LSB AR6320V2_SOC_LPO_CAL_ENABLE_LSB +#define AR6320V2_LPO_CAL_ENABLE_MASK AR6320V2_SOC_LPO_CAL_ENABLE_MASK +#define AR6320V2_ANALOG_INTF_BASE_ADDRESS AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320V2_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320V2_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320V2_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320V2_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320V2_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320V2_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320V2_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320V2_COUNT_DEC_ADDRESS 0x0840 +#define AR6320V2_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320V2_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320V2_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320V2_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320V2_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320V2_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320V2_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320V2_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320V2_WINDOW_WRITE_ADDR_ADDRESS 0x0878 + +struct targetdef_s ar6320v2_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320V2_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320V2_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320V2_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320V2_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320V2_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320V2_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320V2_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320V2_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320V2_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320V2_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320V2_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320V2_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320V2_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320V2_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320V2_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320V2_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320V2_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320V2_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320V2_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320V2_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320V2_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320V2_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320V2_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320V2_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320V2_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320V2_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320V2_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320V2_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320V2_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320V2_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320V2_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320V2_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320V2_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320V2_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320V2_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320V2_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320V2_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320V2_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320V2_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320V2_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320V2_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320V2_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320V2_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320V2_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320V2_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320V2_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320V2_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320V2_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320V2_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320V2_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320V2_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320V2_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320V2_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320V2_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320V2_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320V2_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320V2_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320V2_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320V2_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320V2_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR6320V2_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320V2_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320V2_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320V2_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320V2_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320V2_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320V2_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320V2_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320V2_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320V2_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320V2_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320V2_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320V2_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320V2_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320V2_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320V2_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320V2_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320V2_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320V2_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320V2_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320V2_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320V2_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320V2_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320V2_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320V2_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320V2_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320V2_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320V2_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320V2_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320V2_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320V2_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320V2_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320V2_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320V2_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320V2_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320V2_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320V2_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320V2_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320v2_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320V2_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320V2_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320V2_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320V2_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320V2_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320V2_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320V2_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320V2_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320V2_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320V2_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320V2_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320V2_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320V2_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320V2_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320V2_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320V2_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320V2_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320V2_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320V2_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320V2_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320V2_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320V2_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320V2_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320V2_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320V2_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320V2_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320V2_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320V2_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320V2_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR6320V2_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320V2_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320V2_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/CORE/SERVICES/HIF/PCIe/cepci.h b/CORE/SERVICES/HIF/PCIe/cepci.h index 4a04b7020a4d..144cf558d2fc 100644 --- a/CORE/SERVICES/HIF/PCIe/cepci.h +++ b/CORE/SERVICES/HIF/PCIe/cepci.h @@ -24,14 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -//------------------------------------------------------------------------------ -// <copyright file="cepci.h" company="Qualcomm"> -// Copyright (c) 2012 Qualcomm Atheros Inc. All rights reserved. -// $ATH_LICENSE_HOSTSDK0_C$ -//------------------------------------------------------------------------------ -//============================================================================== -// Author(s): ="Qualcomm Atheros Inc." -//============================================================================== #ifndef __CEPCI_H__ #define __CEPCI_H__ diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.c b/CORE/SERVICES/HIF/PCIe/hif_pci.c index 72c24a8fab9f..4b1e4e2336e4 100644 --- a/CORE/SERVICES/HIF/PCIe/hif_pci.c +++ b/CORE/SERVICES/HIF/PCIe/hif_pci.c @@ -52,7 +52,6 @@ #define ATH_MODULE_NAME hif #include <a_debug.h> #include "hif_pci.h" -#include "vos_lock.h" /* use credit flow control over HTC */ unsigned int htc_credit_flow = 1; @@ -1493,6 +1492,8 @@ HIFStop(HIF_DEVICE *hif_device) if (!hif_state->started) { return; /* already stopped or stopping */ } + + sc->hif_init_done = FALSE; /* sync shutdown */ hif_completion_thread_shutdown(hif_state); hif_completion_thread(hif_state); @@ -1523,7 +1524,6 @@ HIFStop(HIF_DEVICE *hif_device) adf_os_timer_cancel(&hif_state->sleep_timer); adf_os_timer_free(&hif_state->sleep_timer); - vos_wake_lock_destroy(&hif_state->hif_wake_lock); hif_state->started = FALSE; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); @@ -1960,7 +1960,6 @@ HIF_sleep_entry(void *arg) A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); hif_state->fake_sleep = FALSE; - vos_wake_lock_release(&hif_state->hif_wake_lock); } else { adf_os_timer_start(&hif_state->sleep_timer, HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); @@ -1972,6 +1971,29 @@ HIF_sleep_entry(void *arg) adf_os_spin_unlock(&hif_state->keep_awake_lock); } +void +HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + A_target_id_t pci_addr = TARGID_TO_PCI_ADDR(hif_state->targid); + struct hif_pci_softc *sc = hif_state->sc; + + adf_os_spin_lock(&hif_state->keep_awake_lock); + /* + * If the deferred sleep timer is running cancel it + * and put the soc into sleep. + */ + if (hif_state->fake_sleep == TRUE) { + adf_os_timer_cancel(&hif_state->sleep_timer); + if (hif_state->verified_awake == FALSE) { + A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + } + hif_state->fake_sleep = FALSE; + } + adf_os_spin_unlock(&hif_state->keep_awake_lock); +} + /* * Called from PCI layer whenever a new PCI device is probed. * Initializes per-device HIF state and notifies the main @@ -2010,7 +2032,6 @@ HIF_PCIDeviceProbed(hif_handle_t hif_hdl) hif_state->sleep_ticks = 0; adf_os_timer_init(NULL, &hif_state->sleep_timer, HIF_sleep_entry, (void *)hif_state); - vos_wake_lock_init(&hif_state->hif_wake_lock, "hif_wake_lock"); hif_state->fw_indicator_address = FW_INDICATOR_ADDRESS; hif_state->targid = A_TARGET_ID(sc->hif_device); @@ -2165,18 +2186,24 @@ HIF_PCIDeviceProbed(hif_handle_t hif_hdl) { A_UINT8 banks_switched = 1; A_UINT32 chip_id; - rv = HIFDiagReadAccess(sc->hif_device, CHIP_ID_ADDRESS, &chip_id); + rv = HIFDiagReadAccess(sc->hif_device, CHIP_ID_ADDRESS | RTC_SOC_BASE_ADDRESS, &chip_id); if (rv != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get chip id val (%d)\n", rv)); goto done; } - if (CHIP_ID_VERSION_GET(chip_id) == 0xD && (CHIP_ID_REVISION_GET(chip_id) == 0x0 || CHIP_ID_REVISION_GET(chip_id) == 0x1)) { - /* for ROME 1.0, 3 banks are switched to IRAM */ - AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("chip ver=0x%x, chip rev=0x%x\n", CHIP_ID_VERSION_GET(chip_id), CHIP_ID_REVISION_GET(chip_id))); - banks_switched = 3; - } - ealloc_value |= ((banks_switched << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & HI_EARLY_ALLOC_IRAM_BANKS_MASK); - } + if (CHIP_ID_VERSION_GET(chip_id) == 0xD) { + if ((CHIP_ID_REVISION_GET(chip_id) == 0x0) || (CHIP_ID_REVISION_GET(chip_id) == 0x1) + || (CHIP_ID_REVISION_GET(chip_id) == 0x4)) { + /* for ROME 1.0/1.1 and 2.1, 3 banks are switched to IRAM */ + banks_switched = 3; + } + else if (CHIP_ID_REVISION_GET(chip_id) == 0x2) { + /* for ROME 1.3, 2 banks are switched to IRAM */ + banks_switched = 2; + } + } + ealloc_value |= ((banks_switched << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & HI_EARLY_ALLOC_IRAM_BANKS_MASK); + } rv = HIFDiagWriteAccess(sc->hif_device, ealloc_targ_addr, ealloc_value); if (rv != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed set early alloc val (%d)\n", rv)); @@ -2295,7 +2322,6 @@ HIFTargetSleepStateAdjust(A_target_id_t targid, adf_os_timer_cancel(&hif_state->sleep_timer); adf_os_timer_start(&hif_state->sleep_timer, HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); - vos_wake_lock_acquire(&hif_state->hif_wake_lock); } adf_os_spin_unlock(&hif_state->keep_awake_lock); } else { diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.h b/CORE/SERVICES/HIF/PCIe/hif_pci.h index e17bc33b24c4..ebea6fca261f 100644 --- a/CORE/SERVICES/HIF/PCIe/hif_pci.h +++ b/CORE/SERVICES/HIF/PCIe/hif_pci.h @@ -95,7 +95,6 @@ struct HIF_CE_state { A_BOOL verified_awake; A_BOOL fake_sleep; adf_os_timer_t sleep_timer; - vos_wake_lock_t hif_wake_lock; unsigned long sleep_ticks; //struct task_struct *pci_dev_inserted_thread; diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 14a000b68de2..f2cc9621d642 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -3,7 +3,6 @@ * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -60,6 +59,9 @@ #define AR9888_DEVICE_ID (0x003c) #define AR6320_DEVICE_ID (0x003e) +#define AR6320_FW_1_1 (0x11) +#define AR6320_FW_1_3 (0x13) +#define AR6320_FW_2_0 (0x20) #define MAX_NUM_OF_RECEIVES 1000 /* Maximum number of Rx buf to process before break out */ @@ -342,6 +344,10 @@ wlan_tasklet(unsigned long data) struct hif_pci_softc *sc = (struct hif_pci_softc *) data; volatile int tmp; + if (sc->hif_init_done == FALSE) { + goto irq_handled; + } + (irqreturn_t)HIF_fw_interrupt_handler(sc->irq_event, sc); CE_per_engine_service_any(sc->irq_event, sc); adf_os_atomic_set(&sc->tasklet_from_intr, 0); @@ -354,6 +360,7 @@ wlan_tasklet(unsigned long data) tasklet_schedule(&sc->intr_tq); return; } +irq_handled: if (LEGACY_INTERRUPTS(sc)) { /* Enable Legacy PCI line interrupts */ A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), @@ -375,6 +382,7 @@ hif_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct ol_softc *ol_sc; int probe_again = 0; u_int16_t device_id; + u_int16_t revision_id; u_int32_t lcr_val; @@ -459,6 +467,10 @@ again: ret = -EIO; goto err_iomap; } + + /* Disable asynchronous suspend */ + device_disable_async_suspend(&pdev->dev); + sc = A_MALLOC(sizeof(*sc)); if (!sc) { ret = -ENOMEM; @@ -480,19 +492,37 @@ again: sc->cacheline_sz = dma_get_cache_alignment(); + pci_read_config_word(pdev, 0x08, &revision_id); + switch (id->device) { case AR9888_DEVICE_ID: - hif_type = HIF_TYPE_AR9888; - target_type = TARGET_TYPE_AR9888; - break; + hif_type = HIF_TYPE_AR9888; + target_type = TARGET_TYPE_AR9888; + break; + case AR6320_DEVICE_ID: - hif_type = HIF_TYPE_AR6320; - target_type = TARGET_TYPE_AR6320; - break; + switch(revision_id) { + case AR6320_FW_1_1: + case AR6320_FW_1_3: + hif_type = HIF_TYPE_AR6320; + target_type = TARGET_TYPE_AR6320; + break; + + case AR6320_FW_2_0: + hif_type = HIF_TYPE_AR6320V2; + target_type = TARGET_TYPE_AR6320V2; + break; + + default: + printk(KERN_ERR "unsupported revision id\n"); + + } + break; + default: - printk(KERN_ERR "unsupported device id\n"); - ret = -ENODEV; - goto err_tgtstate; + printk(KERN_ERR "unsupported device id\n"); + ret = -ENODEV; + goto err_tgtstate; } /* * Attach Target register table. This is needed early on -- @@ -653,6 +683,7 @@ int hif_pci_reinit(struct pci_dev *pdev, const struct pci_device_id *id) u_int32_t hif_type; u_int32_t target_type; u_int32_t lcr_val; + u_int16_t revision_id; again: ret = 0; @@ -753,16 +784,33 @@ again: adf_os_spinlock_init(&sc->target_lock); sc->cacheline_sz = dma_get_cache_alignment(); + pci_read_config_word(pdev, 0x08, &revision_id); switch (id->device) { case AR9888_DEVICE_ID: hif_type = HIF_TYPE_AR9888; target_type = TARGET_TYPE_AR9888; break; + case AR6320_DEVICE_ID: - hif_type = HIF_TYPE_AR6320; - target_type = TARGET_TYPE_AR6320; + switch(revision_id) { + case AR6320_FW_1_1: + case AR6320_FW_1_3: + hif_type = HIF_TYPE_AR6320; + target_type = TARGET_TYPE_AR6320; + break; + + case AR6320_FW_2_0: + hif_type = HIF_TYPE_AR6320V2; + target_type = TARGET_TYPE_AR6320V2; + break; + + default: + printk(KERN_ERR "unsupported revision id\n"); + + } break; + default: printk(KERN_ERR "%s: Unsupported device ID!\n", __func__); ret = -ENODEV; @@ -1065,6 +1113,30 @@ hif_pci_configure(struct hif_pci_softc *sc, hif_handle_t *hif_hdl) } #endif + if(num_msi_desired == 0) { + printk("\n Using PCI Legacy Interrupt\n"); + + /* Make sure to wake the Target before enabling Legacy Interrupt */ + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_V_MASK); + while (!hif_pci_targ_is_awake(sc, sc->mem)) { + ; + } + /* Use Legacy PCI Interrupts */ + /* + * A potential race occurs here: The CORE_BASE write depends on + * target correctly decoding AXI address but host won't know + * when target writes BAR to CORE_CTRL. This write might get lost + * if target has NOT written BAR. For now, fix the race by repeating + * the write in below synchronization checking. + */ + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); + } + sc->num_msi_intrs = num_msi_desired; sc->ce_count = CE_COUNT; @@ -1102,30 +1174,14 @@ hif_pci_configure(struct hif_pci_softc *sc, hif_handle_t *hif_hdl) *hif_hdl = sc->hif_device; - if(num_msi_desired == 0) { - printk("\n Using PCI Legacy Interrupt\n"); - - /* Make sure to wake the Target before enabling Legacy Interrupt */ - A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, - PCIE_SOC_WAKE_V_MASK); - while (!hif_pci_targ_is_awake(sc, sc->mem)) { - ; - } - /* Use Legacy PCI Interrupts */ - /* - * A potential race occurs here: The CORE_BASE write depends on - * target correctly decoding AXI address but host won't know - * when target writes BAR to CORE_CTRL. This write might get lost - * if target has NOT written BAR. For now, fix the race by repeating - * the write in below synchronization checking. - */ - A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS), - PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); - A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, - PCIE_SOC_WAKE_RESET); - } - + /* + * Flag to avoid potential unallocated memory access from MSI + * interrupt handler which could get scheduled as soon as MSI + * is enabled, i.e to take care of the race due to the order + * in where MSI is enabled before the memory, that will be + * in interrupt handlers, is allocated. + */ + sc->hif_init_done = TRUE; return 0; err_stalled: diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h index 6219544cbc44..74f7130e04c7 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.h +++ b/CORE/SERVICES/HIF/PCIe/if_pci.h @@ -87,6 +87,7 @@ struct hif_pci_softc { struct targetdef_s *targetdef; struct hostdef_s *hostdef; atomic_t tasklet_from_intr; + bool hif_init_done; }; #define TARGID(sc) ((A_target_id_t)(&(sc)->mem)) #define TARGID_TO_HIF(targid) (((struct hif_pci_softc *)((char *)(targid) - (char *)&(((struct hif_pci_softc *)0)->mem)))->hif_device) diff --git a/CORE/SERVICES/HIF/PCIe/regtable.c b/CORE/SERVICES/HIF/PCIe/regtable.c index ad080d3d9f81..822b977b4bb6 100644 --- a/CORE/SERVICES/HIF/PCIe/regtable.c +++ b/CORE/SERVICES/HIF/PCIe/regtable.c @@ -24,35 +24,14 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2010 Atheros Communications, Inc. - * All rights reserved. - * - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ + #include "bmi_msg.h" #include "targaddrs.h" #include "cepci.h" #include "regtable.h" #include "ar9888def.h" #include "ar6320def.h" +#include "ar6320v2def.h" void target_register_tbl_attach(struct hif_pci_softc *sc, u32 target_type) { @@ -63,6 +42,9 @@ void target_register_tbl_attach(struct hif_pci_softc *sc, u32 target_type) case TARGET_TYPE_AR6320: sc->targetdef = &ar6320_targetdef; break; + case TARGET_TYPE_AR6320V2: + sc->targetdef = &ar6320v2_targetdef; + break; default: break; } @@ -77,6 +59,9 @@ void hif_register_tbl_attach(struct hif_pci_softc *sc, u32 hif_type) case HIF_TYPE_AR6320: sc->hostdef = &ar6320_hostdef; break; + case HIF_TYPE_AR6320V2: + sc->hostdef = &ar6320v2_hostdef; + break; default: break; } diff --git a/CORE/SERVICES/HTC/htc.c b/CORE/SERVICES/HTC/htc.c index 9880891b1ee8..2a6172a26989 100644 --- a/CORE/SERVICES/HTC/htc.c +++ b/CORE/SERVICES/HTC/htc.c @@ -781,3 +781,11 @@ void HTCSetTargetToSleep(void *context) #endif #endif } + +void HTCCancelDeferredTargetSleep(void *context) +{ +#if CONFIG_ATH_PCIE_MAX_PERF == 0 + struct ol_softc *sc = (struct ol_softc *)context; + HIFCancelDeferredTargetSleep(sc->hif_hdl); +#endif +} diff --git a/CORE/SERVICES/WMA/regdomain.c b/CORE/SERVICES/WMA/regdomain.c index 1daa4aa9ec81..5a0b8d498174 100644 --- a/CORE/SERVICES/WMA/regdomain.c +++ b/CORE/SERVICES/WMA/regdomain.c @@ -372,7 +372,7 @@ u_int32_t regdmn_getwmodesnreg(u_int32_t modesAvail, return modesAvail; } -static void regdmn_get_ctl_info(struct regulatory *reg, u_int32_t modesAvail, +void regdmn_get_ctl_info(struct regulatory *reg, u_int32_t modesAvail, u_int32_t modeSelect) { const REG_DOMAIN *regdomain2G = NULL; @@ -478,3 +478,25 @@ void regdmn_set_regval(struct regulatory *reg) regdmn_get_ctl_info(reg, wma->reg_cap.wireless_modes, modeSelect); return; } + +/* get the ctl from regdomain */ +u_int8_t regdmn_get_ctl_for_regdmn(u_int32_t reg_dmn) +{ + u_int8_t i; + u_int8_t default_regdmn_ctl = FCC; + + if (reg_dmn == CTRY_DEFAULT) + { + return default_regdmn_ctl; + } + else + { + for (i = 0; i < ol_regdmn_Rdt.regDomainsCt; i++) + { + if (ol_regdmn_Rdt.regDomains[i].regDmnEnum == reg_dmn) + return ol_regdmn_Rdt.regDomains[i].conformance_test_limit; + } + } + return -1; +} + diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index e674a23f2523..207cd2910088 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -67,6 +67,10 @@ #include "wlan_tgt_def_config.h" #endif +#if defined(QCA_IBSS_SUPPORT) +#include "wlan_hdd_assoc.h" +#endif + #include "adf_nbuf.h" #include "adf_os_types.h" #include "ol_txrx_api.h" @@ -87,7 +91,6 @@ #include "testmode.h" #endif - #if !defined(REMOVE_PKT_LOG) && !defined(QCA_WIFI_ISOC) #include "pktlog_ac.h" #endif @@ -98,6 +101,9 @@ #include "csrApi.h" #include "ol_fw.h" +#include "wma_dfs_interface.h" +#include "dfs_interface.h" +#include "radar_filters.h" /* ################### defines ################### */ #define WMA_2_4_GHZ_MAX_FREQ 3000 #define WOW_CSA_EVENT_OFFSET 12 @@ -107,6 +113,15 @@ /* default value */ #define DEFAULT_INFRA_STA_KEEP_ALIVE_PERIOD 20 #define DEFAULT_MAX_IDLETIME 20 +/* pdev vdev and peer stats*/ +#define FW_PDEV_STATS_SET 0x1 +#define FW_VDEV_STATS_SET 0x2 +#define FW_PEER_STATS_SET 0x4 +#define FW_STATS_SET 0x7 +/*AR9888/AR6320 noise floor approx value + * similar to the mentioned the TLSHIM + */ +#define WMA_TGT_NOISE_FLOOR_DBM (-96) /*There is no standard way of caluclating minimum inactive *timer and max unresposive timer from max inactive timer *the below expression are taken from qca_main code @@ -127,6 +142,11 @@ #define CHAN_DUMP 2 #define WD_DUMP 3 +/* conformance test limits */ +#define FCC 0x10 +#define MKK 0x40 +#define ETSI 0x30 + #define WMI_DEFAULT_NOISE_FLOOR_DBM (-96) static void wma_send_msg(tp_wma_handle wma_handle, u_int16_t msg_type, @@ -138,10 +158,14 @@ static void wma_send_beacon_tmpl(WMA_HANDLE handle, static void wma_data_tx_ack_comp_hdlr(void *wma_context, adf_nbuf_t netbuf, int32_t status); +#endif static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, tpDelStaSelfParams pdel_sta_self_req_param, u_int8_t generateRsp); -#endif +static struct wma_target_req * +wma_fill_vdev_req(tp_wma_handle wma, u_int8_t vdev_id, + u_int32_t msg_type, u_int8_t type, void *params, + u_int32_t timeout); static tANI_U32 gFwWlanFeatCaps; @@ -155,6 +179,9 @@ static int wma_update_tdls_peer_state(WMA_HANDLE handle, tTdlsPeerStateParams *peerStateParams); #endif +static eHalStatus wma_set_smps_params(tp_wma_handle wma_handle, + tANI_U8 vdev_id, int value); + #if defined(QCA_WIFI_FTM) && !defined(QCA_WIFI_ISOC) void wma_utf_attach(tp_wma_handle wma_handle); void wma_utf_detach(tp_wma_handle wma_handle); @@ -162,6 +189,31 @@ static VOS_STATUS wma_process_ftm_command(tp_wma_handle wma_handle, struct ar6k_testmode_cmd_data *msg_buffer); #endif + +/*DFS Attach*/ +struct ieee80211com* wma_dfs_attach(struct ieee80211com *ic); +static void wma_set_regdomain(a_uint32_t regdmn); + +/*Configure DFS with radar tables and regulatory domain*/ +void wma_dfs_configure(struct ieee80211com *ic); + +/*Configure the current channel with the DFS*/ +struct ieee80211_channel * +wma_dfs_configure_channel(struct ieee80211com *dfs_ic, + wmi_channel *chan, + WLAN_PHY_MODE chanmode, + struct wma_vdev_start_req *req); + +/* VDEV UP */ +static int +wmi_unified_vdev_up_send(wmi_unified_t wmi, + u_int8_t vdev_id, u_int16_t aid, + u_int8_t bssid[IEEE80211_ADDR_LEN]); + + +/* Configure the regulatory domain for DFS radar filter initialization*/ +void wma_set_dfs_regdomain(tp_wma_handle wma); + static void *wma_find_vdev_by_addr(tp_wma_handle wma, u_int8_t *addr, u_int8_t *vdev_id) { @@ -364,7 +416,7 @@ static struct wma_target_req *wma_find_vdev_req(tp_wma_handle wma, } adf_os_spin_unlock_bh(&wma->vdev_respq_lock); if (!found) { - WMA_LOGD("%s: target request not found for vdev_id %d type %d\n", + WMA_LOGP("%s: target request not found for vdev_id %d type %d\n", __func__, vdev_id, type); return NULL; } @@ -457,6 +509,7 @@ static int wma_vdev_start_resp_handler(void *handle, u_int8_t *cmd_param_info, struct wma_target_req *req_msg; WMI_VDEV_START_RESP_EVENTID_param_tlvs *param_buf; wmi_vdev_start_response_event_fixed_param *resp_event; + struct wma_txrx_node *iface; param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *) cmd_param_info; if (!param_buf) { @@ -473,6 +526,7 @@ static int wma_vdev_start_resp_handler(void *handle, u_int8_t *cmd_param_info, return -EINVAL; } vos_timer_stop(&req_msg->event_timeout); + iface = &wma->interfaces[resp_event->vdev_id]; if (req_msg->msg_type == WDA_CHNL_SWITCH_REQ) { tpSwitchChannelParams params = (tpSwitchChannelParams) req_msg->user_data; @@ -481,6 +535,13 @@ static int wma_vdev_start_resp_handler(void *handle, u_int8_t *cmd_param_info, params->chainMask = resp_event->chain_mask; params->smpsMode = host_map_smps_mode(resp_event->smps_mode); params->status = resp_event->status; + if (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT && + (iface->type == WMI_VDEV_TYPE_AP)) { + wmi_unified_vdev_up_send(wma->wmi_handle, + resp_event->vdev_id, + iface->aid, + iface->bssid); + } wma_send_msg(wma, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); } else if (req_msg->msg_type == WDA_ADD_BSS_REQ) { tpAddBssParams bssParams = (tpAddBssParams) req_msg->user_data; @@ -731,8 +792,8 @@ static int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) return -EINVAL; } - WMA_LOGD("%s:\nPEER:[%pM]\n BSSID:[%pM]\nINTERFACE:%d\npeer_ID:%d\n", - __func__, macaddr, wma->interfaces[vdev_id].addr, vdev_id, + WMA_LOGA("PEER:[%pM]\n BSSID:[%pM]\nINTERFACE:%d\npeer_ID:%d\n", + macaddr, wma->interfaces[vdev_id].addr, vdev_id, peer_id); if (kickout_event->reason == WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT) { @@ -767,6 +828,31 @@ static int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) return 0; } +static int wmi_unified_vdev_down_send(wmi_unified_t wmi, u_int8_t vdev_id) +{ + wmi_vdev_down_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s : wmi_buf_alloc failed\n", __func__); + return -ENOMEM; + } + cmd = (wmi_vdev_down_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_down_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_down_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_DOWN_CMDID)) { + WMA_LOGP("Failed to send vdev down\n"); + adf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: vdev_id %d\n", __func__, vdev_id); + return 0; +} + static int wma_vdev_stop_resp_handler(void *handle, u_int8_t *cmd_param_info, u32 len) { @@ -780,6 +866,7 @@ static int wma_vdev_stop_resp_handler(void *handle, u_int8_t *cmd_param_info, #ifdef QCA_IBSS_SUPPORT tDelStaSelfParams del_sta_param; #endif + struct wma_txrx_node *iface; param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info; if (!param_buf) { @@ -809,6 +896,12 @@ static int wma_vdev_stop_resp_handler(void *handle, u_int8_t *cmd_param_info, WMA_LOGD("%s Failed to find peer %pM\n", __func__, params->bssid); wma_remove_peer(wma, params->bssid, resp_event->vdev_id, peer); + wmi_unified_vdev_down_send(wma->wmi_handle, resp_event->vdev_id); + iface = &wma->interfaces[resp_event->vdev_id]; + if (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) { + WMA_LOGD("%s: P2P BSS is stopped", __func__); + iface->bss_status = WMA_BSS_STATUS_STOPPED; + } #ifndef QCA_WIFI_ISOC bcn = wma->interfaces[resp_event->vdev_id].beacon; @@ -836,12 +929,218 @@ static int wma_vdev_stop_resp_handler(void *handle, u_int8_t *cmd_param_info, params->status = VOS_STATUS_SUCCESS; wma_send_msg(wma, WDA_DELETE_BSS_RSP, (void *)params, 0); + if (iface->del_staself_req) { + WMA_LOGD("%s: scheduling defered deletion", __func__); + wma_vdev_detach(wma, iface->del_staself_req, 1); + } } vos_timer_destroy(&req_msg->event_timeout); vos_mem_free(req_msg); return 0; } +static void wma_update_pdev_stats(tp_wma_handle wma, + wmi_pdev_stats *pdev_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tANI_U32 temp_mask; + tANI_U8 *stats_buf; + tCsrGlobalClassAStatsInfo *classa_stats = NULL; + struct wma_txrx_node *node; + u_int8_t i; + + for (i = 0; i < wma->max_bssid; i++) { + node = &wma->interfaces[i]; + stats_rsp_params = node->stats_rsp; + if (stats_rsp_params) { + node->fw_stats_set |= FW_PDEV_STATS_SET; + WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", + i); + stats_buf = (tANI_U8 *) (stats_rsp_params + 1); + temp_mask = stats_rsp_params->statsMask; + if (temp_mask & (1 << eCsrSummaryStats)) + stats_buf += sizeof(tCsrSummaryStatsInfo); + + if (temp_mask & (1 << eCsrGlobalClassAStats)) { + classa_stats = + (tCsrGlobalClassAStatsInfo *) stats_buf; + classa_stats->max_pwr = pdev_stats->chan_tx_pwr; + } + } + } +} + +static void wma_update_vdev_stats(tp_wma_handle wma, + wmi_vdev_stats *vdev_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tCsrSummaryStatsInfo *summary_stats = NULL; + tANI_U8 *stats_buf; + struct wma_txrx_node *node; + tANI_U8 i; + v_S7_t rssi = 0; + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)wma->pGetRssiReq; + + node = &wma->interfaces[vdev_stats->vdev_id]; + stats_rsp_params = node->stats_rsp; + if (stats_rsp_params) { + stats_buf = (tANI_U8 *) (stats_rsp_params + 1); + node->fw_stats_set |= FW_VDEV_STATS_SET; + WMA_LOGD("<---FW VDEV STATS received for vdevId:%d", + vdev_stats->vdev_id); + if (stats_rsp_params->statsMask & + (1 << eCsrSummaryStats)) { + summary_stats = (tCsrSummaryStatsInfo *) stats_buf; + for (i=0 ; i < 4 ; i++) { + summary_stats->tx_frm_cnt[i] = + vdev_stats->tx_frm_cnt[i]; + summary_stats->fail_cnt[i] = + vdev_stats->fail_cnt[i]; + summary_stats->multiple_retry_cnt[i] = + vdev_stats->multiple_retry_cnt[i]; + } + + summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt; + summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt; + summary_stats->rx_discard_cnt = + vdev_stats->rx_discard_cnt; + summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt; + summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt; + summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt; + } + } + + if (pGetRssiReq && + pGetRssiReq->sessionId == vdev_stats->vdev_id) { + if((vdev_stats->vdev_snr.dat_snr > 0) && + (vdev_stats->vdev_snr.bcn_snr > 0)) + rssi = (vdev_stats->vdev_snr.dat_snr + vdev_stats->vdev_snr.bcn_snr)/2; + else + rssi = vdev_stats->vdev_snr.bcn_snr; + + /* Get the absolute rssi value from the current rssi value + * the sinr value is hardcoded into 0 in the core stack + */ + WMA_LOGD("vdev id %d beancon snr %d data snr %d", + vdev_stats->vdev_id, + vdev_stats->vdev_snr.bcn_snr, + vdev_stats->vdev_snr.dat_snr); + + rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM; + WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi, + pGetRssiReq->sessionId); + + /* update the average rssi value to UMAC layer */ + if (NULL != pGetRssiReq->rssiCallback) { + ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(rssi,pGetRssiReq->staId, + pGetRssiReq->pDevContext); + } + + vos_mem_free(pGetRssiReq); + wma->pGetRssiReq = NULL; + } +} + +static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node) +{ + tAniGetPEStatsRsp *stats_rsp_params; + + stats_rsp_params = node->stats_rsp; + /* send response to UMAC*/ + wma_send_msg(wma, WDA_GET_STATISTICS_RSP, (void *)stats_rsp_params, 0) ; + node->stats_rsp = NULL; + node->fw_stats_set = 0; +} + +static void wma_update_peer_stats(tp_wma_handle wma, wmi_peer_stats *peer_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tCsrGlobalClassAStatsInfo *classa_stats = NULL; + struct wma_txrx_node *node; + tANI_U8 *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN]; + tANI_U32 temp_mask; + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]); + if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id)) + return; + + node = &wma->interfaces[vdev_id]; + if (node->stats_rsp) { + node->fw_stats_set |= FW_PEER_STATS_SET; + WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id); + stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp; + stats_buf = (tANI_U8 *) (stats_rsp_params + 1); + temp_mask = stats_rsp_params->statsMask; + if (temp_mask & (1 << eCsrSummaryStats)) + stats_buf += sizeof(tCsrSummaryStatsInfo); + + if (temp_mask & (1 << eCsrGlobalClassAStats)) { + classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf; + WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate); + /*The linkspeed returned by fw is in kbps so convert + *it in to units of 500kbps which is expected by UMAC*/ + if (peer_stats->peer_tx_rate) { + classa_stats->tx_rate = + peer_stats->peer_tx_rate/500; + } + /* currently tx rate flags are not provided by + * the fw*/ + classa_stats->tx_rate_flags = eHAL_TX_RATE_LEGACY; + } + + if (node->fw_stats_set & FW_STATS_SET) { + WMA_LOGD("<--STATS RSP VDEV_ID:%d", vdev_id); + wma_post_stats(wma, node); + } + } +} + +static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + wmi_stats_event_fixed_param *event; + wmi_pdev_stats *pdev_stats; + wmi_vdev_stats *vdev_stats; + wmi_peer_stats *peer_stats; + WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; + u_int8_t i, *temp; + + WMA_LOGD("%s: Enter", __func__); + param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) + return -1; + + event = param_buf->fixed_param; + temp = (A_UINT8 *)param_buf->data; + if (event->num_pdev_stats > 0) { + for (i = 0; i < event->num_pdev_stats; i++) { + pdev_stats = (wmi_pdev_stats*)temp; + wma_update_pdev_stats(wma, pdev_stats); + temp += sizeof(wmi_pdev_stats); + } + } + + if (event->num_vdev_stats > 0) { + for (i = 0; i < event->num_vdev_stats; i++) { + vdev_stats = (wmi_vdev_stats *)temp; + wma_update_vdev_stats(wma, vdev_stats); + temp += sizeof(wmi_vdev_stats); + } + } + + if (event->num_peer_stats > 0) { + for (i = 0; i < event->num_peer_stats; i++) { + peer_stats = (wmi_peer_stats *)temp; + wma_update_peer_stats(wma, peer_stats); + temp += sizeof(wmi_peer_stats); + } + } + + WMA_LOGD("%s: Exit", __func__); + return 0; +} + #ifndef QCA_WIFI_ISOC u_int8_t *wma_add_p2p_ie(u_int8_t *frm) { @@ -1601,10 +1900,182 @@ static int wma_tdls_event_handler(void *handle, u_int8_t *event, u_int32_t len) #endif /* FEATURE_WLAN_TDLS */ /* + * WMI Handler for WMI_PHYERR_EVENTID event from firmware. + * This handler is currently handling only DFS phy errors. + * Return- 1:Success, 0:Failure + */ +static int wma_unified_phyerr_rx_event_handler(void * handle, + u_int8_t *data, u_int32_t datalen) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PHYERR_EVENTID_param_tlvs *param_tlvs; + wmi_comb_phyerr_rx_hdr *pe_hdr; + u_int8_t *bufp; + wmi_single_phyerr_rx_event *ev; + struct ieee80211com *ic = wma->dfs_ic; + adf_os_size_t n; + A_UINT64 tsf64 = 0; + int phy_err_code = 0; + int error = 0; + param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *)data; + + if (!param_tlvs) + { + WMA_LOGE("%s: Received NULL data from FW", __func__); + return 0; + } + + pe_hdr = param_tlvs->hdr; + if (pe_hdr == NULL) + { + WMA_LOGE("%s: Received Data PE Header is NULL", __func__); + return 0; + } + + /* Ensure it's at least the size of the header */ + if (datalen < sizeof(*pe_hdr)) + { + WMA_LOGE("%s: Expected minimum size %d, received %d", + __func__, sizeof(*pe_hdr), datalen); + return 0; + } + + /* + * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's + * at the time the event was sent to us, the TSF value will be + * in the future. + */ + tsf64 = pe_hdr->tsf_l32; + tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32); + + /* + * Loop over the bufp, extracting out phyerrors + * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer, + * which isn't correct here - what we have received here + * is an array of TLV-style PHY errors. + */ + n = 0;/* Start just after the header */ + bufp = param_tlvs->bufp; + while (n < pe_hdr->buf_len) + { + /* ensure there's at least space for the header */ + if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) + { + WMA_LOGE("%s: Not enough space.(datalen=%d, n=%d, hdr=%d bytes", + __func__,pe_hdr->buf_len,n,sizeof(ev->hdr)); + error = 1; + break; + } + /* + * Obtain a pointer to the beginning of the current event. + * data[0] is the beginning of the WMI payload. + */ + ev = (wmi_single_phyerr_rx_event *) &bufp[n]; + + /* + * Sanity check the buffer length of the event against + * what we currently have. + * Since buf_len is 32 bits, we check if it overflows + * a large 32 bit value. It's not 0x7fffffff because + * we increase n by (buf_len + sizeof(hdr)), which would + * in itself cause n to overflow. + * If "int" is 64 bits then this becomes a moot point. + */ + if (ev->hdr.buf_len > 0x7f000000) + { + WMA_LOGE("%s:buf_len is garbage (0x%x)",__func__, + ev->hdr.buf_len); + error = 1; + break; + } + if (n + ev->hdr.buf_len > pe_hdr->buf_len) + { + WMA_LOGE("%s: buf_len exceeds available space n=%d," + "buf_len=%d, datalen=%d", + __func__,n,ev->hdr.buf_len,pe_hdr->buf_len); + error = 1; + break; + } + phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr); + + /* + * If the phyerror category matches, + * pass radar events to the dfs pattern matching code. + * Don't pass radar events with no buffer payload. + */ + if (phy_err_code == 0x5 || phy_err_code == 0x24) + { + if (ev->hdr.buf_len > 0) + { + /* Calling in to the DFS module to process the phyerr */ + dfs_process_phyerr(ic, &ev->bufp[0], ev->hdr.buf_len, + WMI_UNIFIED_RSSI_COMB_GET(&ev->hdr) & 0xff, + /* Extension RSSI */ + WMI_UNIFIED_RSSI_COMB_GET(&ev->hdr) & 0xff, + ev->hdr.tsf_timestamp, + tsf64); + } + } + + /* + * Advance the buffer pointer to the next PHY error. + * buflen is the length of this payload, so we need to + * advance past the current header _AND_ the payload. + */ + n += sizeof(*ev) + ev->hdr.buf_len; + + }/*end while()*/ + if (error) + { + return (0); + } + else + { + return (1); + } +} + +/* + * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware. + * This event is generated by FW when the beacon transmission is offloaded + * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID + * The FW generates this event when the first successful beacon transmission + * after template update + * Return- 1:Success, 0:Failure + */ +static int wma_unified_bcntx_status_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf; + wmi_offload_bcn_tx_status_event_fixed_param *resp_event; + tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind; + + param_buf = (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid bcn tx response event buffer"); + return -EINVAL; + } + + beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *) + vos_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd)); + + resp_event = param_buf->fixed_param; + + beacon_tx_complete_ind->messageType = WDA_DFS_BEACON_TX_SUCCESS_IND; + beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd); + beacon_tx_complete_ind->bssIdx = resp_event->vdev_id; + + wma_send_msg(wma, WDA_DFS_BEACON_TX_SUCCESS_IND, (void *)beacon_tx_complete_ind, 0); + return 0; +} + +/* * Allocate and init wmi adaptation layer. */ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, wda_tgt_cfg_cb tgt_cfg_cb, + wda_dfs_radar_indication_cb radar_ind_cb, tMacOpenParameters *mac_params) { tp_wma_handle wma_handle; @@ -1612,6 +2083,7 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, adf_os_device_t adf_dev; v_VOID_t *wmi_handle; VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + struct ol_softc *scn; WMA_LOGD("%s: Enter", __func__); @@ -1662,13 +2134,27 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, goto err_wmi_attach; } + /* Allocate dfs_ic and initialize DFS */ + wma_handle->dfs_ic = wma_dfs_attach(wma_handle->dfs_ic); + if(wma_handle->dfs_ic == NULL) { + WMA_LOGP("Memory allocation failed for dfs_ic"); + } + + vos_wake_lock_init(&wma_handle->wow_wake_lock, "wow_wakelock"); + #if defined(QCA_WIFI_FTM) && !defined(QCA_WIFI_ISOC) if (vos_get_conparam() == VOS_FTM_MODE) wma_utf_attach(wma_handle); #endif /*TODO: Recheck below parameters */ - mac_params->maxStation = WMA_MAX_SUPPORTED_STAS; + /* + * Increase maxStation by 1 here so that correct hashtable and + * gpLimPeerIdxpool memory is allocated in peCreateSession + */ + scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + mac_params->maxStation = ol_get_number_of_peers_supported(scn) + 1; + mac_params->maxBssId = WMA_MAX_SUPPORTED_BSS; mac_params->frameTransRequired = 0; @@ -1692,6 +2178,7 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, wma_unified_debug_print_event_handler); wma_handle->tgt_cfg_update_cb = tgt_cfg_cb; + wma_handle->dfs_radar_indication_cb = radar_ind_cb; #ifdef QCA_WIFI_ISOC vos_status = vos_event_init(&wma_handle->cfg_nv_tx_complete); @@ -1741,6 +2228,11 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, WMI_PEER_STA_KICKOUT_EVENTID, wma_peer_sta_kickout_event_handler); + /* register for stats response event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_UPDATE_STATS_EVENTID, + wma_stats_event_handler); + #ifdef FEATURE_OEM_DATA_SUPPORT wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_OEM_CAPABILITY_EVENTID, @@ -1754,6 +2246,17 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, WMI_OEM_ERROR_REPORT_EVENTID, wma_oem_error_report_event_callback); #endif + /*register phyerr event handler for handling DFS errors */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PHYERR_EVENTID, + wma_unified_phyerr_rx_event_handler); + + /* Register beacon tx complete event id. The event is required + * for sending channel switch announcement frames + */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OFFLOAD_BCN_TX_STATUS_EVENTID, + wma_unified_bcntx_status_event_handler); /* Firmware debug log */ vos_status = dbglog_init(wma_handle->wmi_handle); @@ -1991,6 +2494,42 @@ static int wma_unified_vdev_delete_send(wmi_unified_t wmi_handle, u_int8_t if_id return ret; } +void wma_vdev_detach_callback(void *ctx) +{ + tp_wma_handle wma; + struct wma_txrx_node *iface = (struct wma_txrx_node *)ctx; + tpDelStaSelfParams param; + struct wma_target_req *req_msg; + + wma = vos_get_context(VOS_MODULE_ID_WDA, + vos_get_global_context(VOS_MODULE_ID_WDA, NULL)); + + if (!wma || !iface->del_staself_req) { + WMA_LOGP("%s: wma %p iface %p", __func__, wma, + iface->del_staself_req); + return; + } + param = (tpDelStaSelfParams) iface->del_staself_req; + WMA_LOGD("%s: sending WDA_DEL_STA_SELF_RSP for vdev %d", + __func__, param->sessionId); + + req_msg = wma_find_vdev_req(wma, param->sessionId, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (req_msg) { + WMA_LOGD("%s: Found vdev request for vdev id %d\n", + __func__, param->sessionId); + vos_timer_stop(&req_msg->event_timeout); + vos_timer_destroy(&req_msg->event_timeout); + adf_os_mem_free(req_msg); + } + if(iface->addBssStaContext) + adf_os_mem_free(iface->addBssStaContext); + vos_mem_zero(iface, sizeof(*iface)); + param->status = VOS_STATUS_SUCCESS; + + wma_send_msg(wma, WDA_DEL_STA_SELF_RSP, (void *)param, 0); +} + /* function : wma_vdev_detach * Descriptin : * Args : @@ -2001,15 +2540,15 @@ static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, u_int8_t generateRsp) { VOS_STATUS status = VOS_STATUS_SUCCESS; - void *txrx_hdl; ol_txrx_peer_handle peer; ol_txrx_pdev_handle pdev; u_int8_t peer_id; u_int8_t vdev_id = pdel_sta_self_req_param->sessionId; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + struct wma_target_req *msg; - if ((wma_handle->interfaces[vdev_id].type == WMI_VDEV_TYPE_AP) && - ((wma_handle->interfaces[vdev_id].sub_type == - WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE))) { + if ((iface->type == WMI_VDEV_TYPE_AP) && + (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { WMA_LOGA("P2P Device: removing self peer %pM", pdel_sta_self_req_param->selfMacAddr); @@ -2026,34 +2565,53 @@ static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, } wma_remove_peer(wma_handle, pdel_sta_self_req_param->selfMacAddr, - pdel_sta_self_req_param->sessionId, - peer); + vdev_id, peer); + } + if ((iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) && + (iface->bss_status == WMA_BSS_STATUS_STARTED)) { + WMA_LOGD("P2P BSS is not yet stopped. Defering vdev deletion"); + iface->del_staself_req = pdel_sta_self_req_param; + return status; } /* remove the interface from ath_dev */ - if (wma_unified_vdev_delete_send(wma_handle->wmi_handle, - pdel_sta_self_req_param->sessionId)) { + if (wma_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id)) { WMA_LOGP("Unable to remove an interface for ath_dev.\n"); status = VOS_STATUS_E_FAILURE; + goto out; } - txrx_hdl = wma_handle->interfaces[pdel_sta_self_req_param->sessionId].handle; - if(!txrx_hdl) + if(!iface->handle) { status = VOS_STATUS_E_FAILURE; - else - ol_txrx_vdev_detach(txrx_hdl, NULL, NULL); - if(wma_handle->interfaces[pdel_sta_self_req_param->sessionId].addBssStaContext) { - adf_os_mem_free(wma_handle->interfaces[pdel_sta_self_req_param->sessionId].addBssStaContext); - } - vos_mem_zero(&wma_handle->interfaces[pdel_sta_self_req_param->sessionId], - sizeof(wma_handle->interfaces[pdel_sta_self_req_param->sessionId])); + WMA_LOGP("handle of vdev_id %d is NULL", vdev_id); + goto out; + } - WMA_LOGA("vdev_id:%hu vdev_hdl:%p\n", pdel_sta_self_req_param->sessionId, - txrx_hdl); + WMA_LOGA("vdev_id:%hu vdev_hdl:%p\n", vdev_id, iface->handle); + if (!generateRsp) { + WMA_LOGD("Call txrx detach w/o callback for vdev %d", vdev_id); + ol_txrx_vdev_detach(iface->handle, NULL, NULL); + goto out; + } -#ifdef QCA_IBSS_SUPPORT + iface->del_staself_req = pdel_sta_self_req_param; + msg = wma_fill_vdev_req(wma_handle, vdev_id, WDA_DEL_STA_SELF_REQ, + WMA_TARGET_REQ_TYPE_VDEV_DEL, iface, 2000); + if (!msg) { + WMA_LOGP("%s: Failed to fill vdev request for vdev_id %d\n", + __func__, vdev_id); + status = VOS_STATUS_E_NOMEM; + goto out; + } + WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id); + ol_txrx_vdev_detach(iface->handle, wma_vdev_detach_callback, iface); + return status; +out: + if(iface->addBssStaContext) + adf_os_mem_free(iface->addBssStaContext); + vos_mem_zero(iface, sizeof(*iface)); + pdel_sta_self_req_param->status = status; if (generateRsp) -#endif wma_send_msg(wma_handle, WDA_DEL_STA_SELF_RSP, (void *)pdel_sta_self_req_param, 0); return status; @@ -2422,21 +2980,13 @@ static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, } else { WMA_LOGE("Failed to get value for WNI_CFG_FRAGMENTATION_THRESHOLD, leaving unchanged"); } - if (self_sta_req->type == WMI_VDEV_TYPE_STA && - mac->roam.configParam.isFastRoamIniFeatureEnabled) { - /* Enable roaming offload - * return value is not significant because some firmware versions may have - * roam offload always enabled. It will stay enabled even if this command fails. - */ - ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, self_sta_req->sessionId, - WMI_VDEV_PARAM_ROAM_FW_OFFLOAD, 1); - if (ret) { - /* could not enable roam offload in firmware. Disable it for host. */ - WMA_LOGE("Failed to set WMI_VDEV_PARAM_ROAM_FW_OFFLOAD"); - } else { + /* Initialize roaming offload state */ + if (self_sta_req->type == WMI_VDEV_TYPE_STA) { wma_handle->roam_offload_vdev_id = (A_UINT32) self_sta_req->sessionId; + wma_handle->roam_offload_enabled = TRUE; + wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, wma_handle->roam_offload_vdev_id, + WMI_VDEV_PARAM_ROAM_FW_OFFLOAD, 1); } - } if (wlan_cfgGetInt(mac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, &cfg_val) == eSIR_SUCCESS) { @@ -2638,21 +3188,21 @@ VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, cmd->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; cmd->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES; - for (i = 0; i < wma_handle->max_bssid; i++) { - if (wma_is_vdev_in_ap_mode(wma_handle, i)) - break; - } - if (i != wma_handle->max_bssid) - cmd->burst_duration = scan_req->maxChannelTime * - WMA_SCAN_AP_PRESENT_MAX_OFFCHANNEL_NUM; + if (scan_req->scanType == eSIR_PASSIVE_SCAN) + cmd->burst_duration = 0; else { - if (scan_req->scanType == eSIR_PASSIVE_SCAN) - cmd->burst_duration = scan_req->maxChannelTime * - WMA_SCAN_MAX_OFFCHANNEL_NUM_PASSIVE; - else - cmd->burst_duration = scan_req->maxChannelTime * - WMA_SCAN_MAX_OFFCHANNEL_NUM_ACTIVE; + if (scan_req->channelList.numChannels < + WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS) { + cmd->burst_duration = + scan_req->channelList.numChannels * + scan_req->maxChannelTime; + } else { + cmd->burst_duration = + WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS * + scan_req->maxChannelTime; + } } + if (!scan_req->p2pScanType) { WMA_LOGD("Normal Scan request"); cmd->scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES; @@ -2780,91 +3330,6 @@ error: } -/*AR9888/AR6320 noise floor approx value - * similar to the mentioned the TLSHIM - */ -#define WMA_TGT_NOISE_FLOOR_DBM (-96) -/* - * WMI event handler for periodic target stats event - */ - -static int wmi_unified_update_stats_event_handler(void* handle, - u_int8_t *data, u_int32_t datalen) -{ - wmi_stats_event_fixed_param *ev; - A_UINT8 *temp; - A_UINT8 i; - WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; - tp_wma_handle wma = (tp_wma_handle) handle; - A_UINT8 rssi = 0; - tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)wma->pGetRssiReq; - u_int8_t vdev_id = 0; - wmi_vdev_stats *vdev_stats = NULL; - - if(NULL != pGetRssiReq) - vdev_id = pGetRssiReq->sessionId; - WMA_LOGD("%s: vdev_id %d\n", __func__, vdev_id); - param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)data; - if (!param_buf) { - WMA_LOGE("%s: Received NULL buf ptr from FW", __func__); - return VOS_STATUS_E_NOMEM; - } - ev = param_buf->fixed_param; - if (NULL != param_buf->data) - temp = (A_UINT8 *)param_buf->data; - if (NULL != ev) { - for (i = 0; i < ev->num_vdev_stats; i++) { - if(NULL == temp ) - continue ; - vdev_stats = (wmi_vdev_stats *)temp; - if(NULL == vdev_stats) - continue; - WMA_LOGE("vdev id %d beancon snr %d data snr %d\n", - vdev_stats->vdev_id, vdev_stats->vdev_snr.bcn_snr, - vdev_stats->vdev_snr.dat_snr); - /* if the data average rssi present return that, - * else return beacon average rssi - */ - if (vdev_stats->vdev_id == vdev_id) { - if((vdev_stats->vdev_snr.dat_snr > 0) && (vdev_stats->vdev_snr.bcn_snr > 0)) - rssi = (vdev_stats->vdev_snr.dat_snr + vdev_stats->vdev_snr.bcn_snr)/2; - else - rssi = vdev_stats->vdev_snr.bcn_snr; - /* Get the absolute rssi value from the current rssi value - * the sinr value is hardcoded into 0 in the core stack - */ - rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM; - WMA_LOGE("Average Rssi = %d, vdev id= %d",(int)rssi, vdev_id); - - /* update the average rssi value to UMAC layer */ - if ((NULL != pGetRssiReq) && (NULL != pGetRssiReq->rssiCallback)) { - ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(rssi,pGetRssiReq->staId, - pGetRssiReq->pDevContext); - pGetRssiReq->rssiCallback = NULL; - vos_mem_free(pGetRssiReq); - wma->pGetRssiReq = NULL; - } - else { - WMA_LOGE("WMA pGetRssiReq->rssiCallback is NULL"); - if (NULL != pGetRssiReq) { - vos_mem_free(pGetRssiReq); - wma->pGetRssiReq = NULL; - } - } - break; - } - - temp += sizeof(wmi_vdev_stats); - } - } - - return VOS_STATUS_SUCCESS; -} - - -/* - * Return the data rssi for the given peer. - */ VOS_STATUS wma_send_snr_request(tp_wma_handle wma_handle, void *pGetRssiReq) { wmi_buf_t buf; @@ -3487,7 +3952,7 @@ v_VOID_t wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle, tpAniSirGlobal ap_profile_p->rsn_ucastcipherset = WMI_CIPHER_NONE; ap_profile_p->rsn_mcastcipherset = WMI_CIPHER_NONE; ap_profile_p->rsn_mcastmgmtcipherset = WMI_CIPHER_NONE; - ap_profile_p->rssi_threshold = 5; + ap_profile_p->rssi_threshold = WMA_ROAM_RSSI_DIFF_DEFAULT; } else { ap_profile_p->ssid.ssid_len = roam_req->ConnectedNetwork.ssId.length; vos_mem_copy(ap_profile_p->ssid.ssid, roam_req->ConnectedNetwork.ssId.ssId, @@ -3500,7 +3965,7 @@ v_VOID_t wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle, tpAniSirGlobal ap_profile_p->rsn_mcastcipherset = eCsrEncryptionType_to_rsn_cipherset(roam_req->ConnectedNetwork.mcencryption); ap_profile_p->rsn_mcastmgmtcipherset = ap_profile_p->rsn_mcastcipherset; - ap_profile_p->rssi_threshold = 5; + ap_profile_p->rssi_threshold = roam_req->RoamRssiDiff; } } @@ -3513,32 +3978,62 @@ v_VOID_t wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle, tpAniSirGlobal v_VOID_t wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle, tpAniSirGlobal pMac, tSirRoamOffloadScanReq *roam_req, wmi_start_scan_cmd_fixed_param *scan_params) { - vos_mem_zero(scan_params, sizeof(wmi_start_scan_cmd_fixed_param)); - if (roam_req != NULL) { - /* Parameters updated after association is complete */ - scan_params->dwell_time_active = roam_req->NeighborScanChannelMinTime; - scan_params->dwell_time_passive = roam_req->NeighborScanChannelMaxTime; - scan_params->min_rest_time = 50; - scan_params->max_rest_time = roam_req->NeighborScanTimerPeriod - scan_params->dwell_time_passive; - scan_params->repeat_probe_time = roam_req->NeighborScanChannelMaxTime/3; - scan_params->probe_spacing_time = 0; - scan_params->probe_delay = 0; - scan_params->max_scan_time = 50000; /* 50 seconds for full scan cycle */ - scan_params->idle_time = 200; - scan_params->burst_duration = roam_req->NeighborScanChannelMaxTime; - } else { - /* roam_req = NULL during initial or pre-assoc invocation */ - scan_params->dwell_time_active = 100; - scan_params->dwell_time_passive = 110; - scan_params->min_rest_time = 50; - scan_params->max_rest_time = 500; - scan_params->repeat_probe_time = 50; - scan_params->probe_spacing_time = 0; - scan_params->probe_delay = 0; - scan_params->max_scan_time = 50000; - scan_params->idle_time = 200; - scan_params->burst_duration = 110; - } + tANI_U16 max_scan_time, min_scan_time, burst_duration; + tANI_U16 nprobes = 1; + vos_mem_zero(scan_params, sizeof(wmi_start_scan_cmd_fixed_param)); + if (roam_req != NULL) { + /* Parameters updated after association is complete */ + WMA_LOGI("%s: Input parameters: NeighborScanChannelMinTime = %d, NeighborScanChannelMaxTime = %d\n", + __func__, roam_req->NeighborScanChannelMinTime, roam_req->NeighborScanChannelMaxTime); + WMA_LOGI("%s: Input parameters: NeighborScanTimerPeriod = %d, HomeAwayTime = %d, nProbes = %d\n", + __func__, roam_req->NeighborScanTimerPeriod, roam_req->HomeAwayTime, roam_req->nProbes); + /* NeighborScanChannelMinTime = SETROAMSCANCHANNELMINTIME and gNeighborScanChannelMinTime */ + if (roam_req->HomeAwayTime > (2 * WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME)) { + burst_duration = roam_req->HomeAwayTime - 2 * WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME; + max_scan_time = min(roam_req->NeighborScanChannelMaxTime, burst_duration); + } else { + burst_duration = max_scan_time = roam_req->NeighborScanChannelMaxTime; + } + /* ROME cld firmware have single value and not min, max + * therefore setting both values to same thing. + */ + min_scan_time = max_scan_time; + nprobes = roam_req->nProbes; + scan_params->dwell_time_active = min_scan_time; + + /* NeighborScanChannelMaxTime = SETSCANCHANNELTIME and gNeighborScanChannelMaxTime */ + /* HomeAwayTime = SETSCANHOMEAWAYTIME and gRoamScanHomeAwayTime */ + /* max_scan_time is for 1 channel, burst_duration is for total for all in a burst */ + scan_params->dwell_time_passive = max_scan_time; + + /* NeighborScanTimerPeriod = SETSCANHOMETIME and gNeighborScanTimerPeriod */ + scan_params->min_rest_time = roam_req->NeighborScanTimerPeriod; + scan_params->max_rest_time = roam_req->NeighborScanTimerPeriod; + scan_params->repeat_probe_time = (nprobes > 0) ? scan_params->dwell_time_active / nprobes : 0; + scan_params->probe_spacing_time = 0; + scan_params->probe_delay = 0; + scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; /* 30 seconds for full scan cycle */ + scan_params->idle_time = scan_params->min_rest_time; + scan_params->burst_duration = burst_duration; + } else { + /* roam_req = NULL during initial or pre-assoc invocation */ + scan_params->dwell_time_active = WMA_ROAM_DWELL_TIME_ACTIVE_DEFAULT; + scan_params->dwell_time_passive = WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT; + scan_params->min_rest_time = WMA_ROAM_MIN_REST_TIME_DEFAULT; + scan_params->max_rest_time = WMA_ROAM_MAX_REST_TIME_DEFAULT; + scan_params->repeat_probe_time = 0; + scan_params->probe_spacing_time = 0; + scan_params->probe_delay = 0; + scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; + scan_params->idle_time = scan_params->min_rest_time; + scan_params->burst_duration = WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT; + } + WMA_LOGI("%s: Rome roam scan parameters: dwell_time_active = %d, dwell_time_passive = %d\n", + __func__, scan_params->dwell_time_active, scan_params->dwell_time_passive); + WMA_LOGI("%s: min_rest_time = %d, max_rest_time = %d, repeat_probe_time = %d\n", + __func__, scan_params->min_rest_time, scan_params->max_rest_time, scan_params->repeat_probe_time); + WMA_LOGI("%s: max_scan_time = %d, idle_time = %d, burst_duration = %d\n", + __func__, scan_params->max_scan_time, scan_params->idle_time, scan_params->burst_duration); } /* function : wma_roam_scan_offload_ap_profile * Descriptin : Send WMI_ROAM_AP_PROFILE TLV to firmware @@ -3614,22 +4109,16 @@ VOS_STATUS wma_roam_scan_offload_init_connect(tp_wma_handle wma_handle) wmi_start_scan_cmd_fixed_param scan_params; wmi_ap_profile ap_profile; - if (!pMac) { - return VOS_STATUS_SUCCESS; - } - if (!pMac->roam.configParam.isFastRoamIniFeatureEnabled) { - /* Fast roaming is disabled */ - return VOS_STATUS_SUCCESS; - } /* first program the parameters to conservative values so that roaming scan won't be * triggered before association completes */ /* rssi_thresh = 10 is low enough */ - vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, 10, 30); + vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, WMA_ROAM_LOW_RSSI_TRIGGER_VERYLOW, + WMA_ROAM_RSSI_THRESH_DIFF_DEFAULT); vos_status = wma_roam_scan_offload_scan_period(wma_handle, - 100000, 500000); + WMA_ROAM_OPP_SCAN_PERIOD_DEFAULT, WMA_ROAM_OPP_SCAN_AGING_PERIOD_DEFAULT); vos_status = wma_roam_scan_offload_rssi_change(wma_handle, - 15, 14); + WMA_ROAM_RSSI_CHANGE_RESCAN_DEFAULT, WMA_ROAM_BEACON_WEIGHT_DEFAULT); wma_roam_scan_fill_ap_profile(wma_handle, pMac, NULL, &ap_profile); vos_status = wma_roam_scan_offload_ap_profile(wma_handle, &ap_profile); @@ -3652,15 +4141,14 @@ VOS_STATUS wma_roam_scan_offload_end_connect(tp_wma_handle wma_handle) wma_handle->vos_context); wmi_start_scan_cmd_fixed_param scan_params; - if (!pMac->roam.configParam.isFastRoamIniFeatureEnabled) { - /* Fast roaming is disabled */ - return VOS_STATUS_SUCCESS; - } + /* If roam scan is running, stop it */ + if (wma_handle->roam_offload_enabled) { - wma_roam_scan_fill_scan_params(wma_handle, pMac, NULL, &scan_params); - vos_status = wma_roam_scan_offload_mode(wma_handle, &scan_params, - WMI_ROAM_SCAN_MODE_NONE); - return vos_status; + wma_roam_scan_fill_scan_params(wma_handle, pMac, NULL, &scan_params); + vos_status = wma_roam_scan_offload_mode(wma_handle, &scan_params, + WMI_ROAM_SCAN_MODE_NONE); + } + return VOS_STATUS_SUCCESS; } /* function : wma_process_roam_scan_req @@ -3676,53 +4164,55 @@ VOS_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, wmi_ap_profile ap_profile; tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, wma_handle->vos_context); - A_INT32 noise_floor = WMI_DEFAULT_NOISE_FLOOR_DBM; WMA_LOGI("%s: command 0x%x\n", __func__, roam_req->Command); - if (!pMac->roam.configParam.isFastRoamIniFeatureEnabled) { - /* Fast roaming is disabled */ - return VOS_STATUS_SUCCESS; - } + if (!wma_handle->roam_offload_enabled) { + /* roam scan offload is not enabled in firmware. + * Cannot initialize it in the middle of connection. + */ + return VOS_STATUS_E_PERM; + } switch (roam_req->Command) { case ROAM_SCAN_OFFLOAD_START: /* * Scan/Roam threshold parameters are translated from fields of tSirRoamOffloadScanReq * to WMITLV values sent to Rome firmware. - * some of these parameters are configurable in qcom_cfg.ini file. + * some of these parameters are configurable in qcom_cfg.ini file. */ - /* First parameter is positive rssi value to trigger rssi based scan. - * Opportunistic scan is started at 30 dB higher that trigger rssi. + /* First parameter is positive rssi value to trigger rssi based scan. + * Opportunistic scan is started at 30 dB higher that trigger rssi. */ - vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, - (roam_req->LookupThreshold - noise_floor), - 30); - if (vos_status != VOS_STATUS_SUCCESS) { + vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, + (roam_req->LookupThreshold - WMA_NOISE_FLOOR_DBM_DEFAULT), + WMA_ROAM_RSSI_THRESH_DIFF_DEFAULT); + if (vos_status != VOS_STATUS_SUCCESS) { break; } - /* Opportunistic scan runs on a timer, value set by NeighborRoamScanRefreshPeriod. - * Age out the entries after 3 such cycles. - */ - vos_status = wma_roam_scan_offload_scan_period(wma_handle, - roam_req->NeighborRoamScanRefreshPeriod, - roam_req->NeighborRoamScanRefreshPeriod * 3); - if (vos_status != VOS_STATUS_SUCCESS) { + /* Opportunistic scan runs on a timer, value set by NeighborRoamScanRefreshPeriod. + * Age out the entries after 3 such cycles. + */ + vos_status = wma_roam_scan_offload_scan_period(wma_handle, + roam_req->NeighborRoamScanRefreshPeriod, + roam_req->NeighborRoamScanRefreshPeriod * 3); + if (vos_status != VOS_STATUS_SUCCESS) { break; } - /* Start new rssi triggered scan only if it changes by RoamRssiDiff value. - * Beacon weight of 14 means average rssi is taken over 14 previous samples + - * 2 times the current beacon's rssi. - */ - vos_status = wma_roam_scan_offload_rssi_change(wma_handle, - roam_req->RoamRssiDiff, 14); - if (vos_status != VOS_STATUS_SUCCESS) { + /* Start new rssi triggered scan only if it changes by RoamRssiDiff value. + * Beacon weight of 14 means average rssi is taken over 14 previous samples + + * 2 times the current beacon's rssi. + */ + vos_status = wma_roam_scan_offload_rssi_change(wma_handle, + WMA_ROAM_RSSI_CHANGE_RESCAN_DEFAULT, + WMA_ROAM_BEACON_WEIGHT_DEFAULT); + if (vos_status != VOS_STATUS_SUCCESS) { break; } wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req, &ap_profile); - vos_status = wma_roam_scan_offload_ap_profile(wma_handle, - &ap_profile); - if (vos_status != VOS_STATUS_SUCCESS) { + vos_status = wma_roam_scan_offload_ap_profile(wma_handle, + &ap_profile); + if (vos_status != VOS_STATUS_SUCCESS) { break; } vos_status = wma_roam_scan_offload_chan_list(wma_handle, @@ -3740,6 +4230,22 @@ VOS_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, case ROAM_SCAN_OFFLOAD_STOP: wma_roam_scan_offload_end_connect(wma_handle); + if (roam_req->StartScanReason == REASON_OS_REQUESTED_ROAMING_NOW) { + vos_msg_t vosMsg; + vosMsg.type = eWNI_SME_ROAM_SCAN_OFFLOAD_RSP; + vosMsg.bodyptr = NULL; + vosMsg.bodyval = roam_req->StartScanReason; + /* + * Since REASSOC request is processed in Roam_Scan_Offload_Rsp + * post a dummy rsp msg back to SME with proper reason code. + */ + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, + (vos_msg_t*)&vosMsg)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "Failed to post the rsp to UMAC" , __func__); + } + } break; case ROAM_SCAN_OFFLOAD_RESTART: @@ -3747,6 +4253,17 @@ VOS_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, break; case ROAM_SCAN_OFFLOAD_UPDATE_CFG: + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, &scan_params); + vos_status = wma_roam_scan_offload_mode(wma_handle, &scan_params, + WMI_ROAM_SCAN_MODE_NONE); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + if (roam_req->RoamScanOffloadEnabled == FALSE) { + break; + } + /* * Runtime (after association) changes to rssi thresholds and other parameters. */ @@ -3756,20 +4273,40 @@ VOS_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, if (vos_status != VOS_STATUS_SUCCESS) { break; } - vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, - (roam_req->LookupThreshold - noise_floor), - 30); - if (vos_status != VOS_STATUS_SUCCESS) { + + vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, + (roam_req->LookupThreshold - WMA_NOISE_FLOOR_DBM_DEFAULT), + WMA_ROAM_RSSI_THRESH_DIFF_DEFAULT); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + vos_status = wma_roam_scan_offload_scan_period(wma_handle, + roam_req->NeighborRoamScanRefreshPeriod, + roam_req->NeighborRoamScanRefreshPeriod * 3); + if (vos_status != VOS_STATUS_SUCCESS) { break; } - vos_status = wma_roam_scan_offload_scan_period(wma_handle, - roam_req->NeighborRoamScanRefreshPeriod, - roam_req->NeighborRoamScanRefreshPeriod * 3); - if (vos_status != VOS_STATUS_SUCCESS) { + + vos_status = wma_roam_scan_offload_rssi_change(wma_handle, + WMA_ROAM_RSSI_CHANGE_RESCAN_DEFAULT, + WMA_ROAM_BEACON_WEIGHT_DEFAULT); + if (vos_status != VOS_STATUS_SUCCESS) { break; } - vos_status = wma_roam_scan_offload_rssi_change(wma_handle, - roam_req->RoamRssiDiff, 14); + + wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req, &ap_profile); + vos_status = wma_roam_scan_offload_ap_profile(wma_handle, + &ap_profile); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, &scan_params); + vos_status = wma_roam_scan_offload_mode(wma_handle, &scan_params, + (WMI_ROAM_SCAN_MODE_PERIODIC + | WMI_ROAM_SCAN_MODE_RSSI_CHANGE)); + break; default: @@ -4198,7 +4735,8 @@ static WLAN_PHY_MODE wma_chan_to_mode(u8 chan, ePhyChanBondState chan_offset, if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) { switch (chan_offset) { case PHY_SINGLE_CHANNEL_CENTERED: - phymode = vht_capable ? MODE_11AC_VHT20 :MODE_11NG_HT20; + /* Configure MODE_11NG_HT20 for self vdev(for vht too) */ + phymode = MODE_11NG_HT20; break; case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: @@ -4268,12 +4806,12 @@ tANI_U8 wma_getCenterChannel(tANI_U8 chan, tANI_U8 chan_offset) } static VOS_STATUS wma_vdev_start(tp_wma_handle wma, - struct wma_vdev_start_req *req) + struct wma_vdev_start_req *req, v_BOOL_t isRestart) { wmi_vdev_start_request_cmd_fixed_param *cmd; wmi_buf_t buf; wmi_channel *chan; - int32_t len; + int32_t len, ret; WLAN_PHY_MODE chanmode; u_int8_t *buf_ptr; struct wma_txrx_node *intr = wma->interfaces; @@ -4330,33 +4868,45 @@ static VOS_STATUS wma_vdev_start(tp_wma_handle wma, * If that is ever the case we would insert the decision whether to * enable the firmware flag here. */ - if (req->is_dfs) { + + /* + * If the Channel is DFS, + * set the WMI_CHAN_FLAG_DFS flag + */ + if (req->is_dfs) { + /* provide the current channel to DFS*/ + wma->dfs_ic->ic_curchan = + wma_dfs_configure_channel(wma->dfs_ic,chan,chanmode,req); WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_DFS); - cmd->disable_hw_ack = (req->oper_mode) ? 0 : 1; + cmd->disable_hw_ack = VOS_TRUE; } - cmd->beacon_interval = req->beacon_intval; + cmd->beacon_interval = req->beacon_intval; cmd->dtim_period = req->dtim_period; /* FIXME: Find out min, max and regulatory power levels */ WMI_SET_CHANNEL_REG_POWER(chan, req->max_txpow); /* TODO: Handle regulatory class, max antenna */ + if (!isRestart) { + cmd->beacon_interval = req->beacon_intval; + cmd->dtim_period = req->dtim_period; + + /* Copy the SSID */ + if (req->ssid.length) { + if (req->ssid.length < sizeof(cmd->ssid.ssid)) + cmd->ssid.ssid_len = req->ssid.length; + else + cmd->ssid.ssid_len = sizeof(cmd->ssid.ssid); + vos_mem_copy(cmd->ssid.ssid, req->ssid.ssId, + cmd->ssid.ssid_len); + } - /* Copy the SSID */ - if (req->ssid.length) { - if (req->ssid.length < sizeof(cmd->ssid.ssid)) - cmd->ssid.ssid_len = req->ssid.length; - else - cmd->ssid.ssid_len = sizeof(cmd->ssid.ssid); - vos_mem_copy(cmd->ssid.ssid, req->ssid.ssId, - cmd->ssid.ssid_len); - } - - if (req->hidden_ssid) - cmd->flags |= WMI_UNIFIED_VDEV_START_HIDDEN_SSID; + if (req->hidden_ssid) + cmd->flags |= WMI_UNIFIED_VDEV_START_HIDDEN_SSID; - if (req->pmf_enabled) - cmd->flags |= WMI_UNIFIED_VDEV_START_PMF_ENABLED; + if (req->pmf_enabled) + cmd->flags |= WMI_UNIFIED_VDEV_START_PMF_ENABLED; + } cmd->num_noa_descriptors = 0; buf_ptr = (u_int8_t *)(((u_int32_t) cmd) + sizeof(*cmd) + @@ -4369,12 +4919,17 @@ static VOS_STATUS wma_vdev_start(tp_wma_handle wma, chan->mhz, req->chan, chanmode, req->is_dfs, req->beacon_intval, cmd->dtim_period, chan->band_center_freq1); - if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, - WMI_VDEV_START_REQUEST_CMDID) < 0) { - WMA_LOGP("Failed to send vdev start command\n"); - adf_nbuf_free(buf); - return VOS_STATUS_E_FAILURE; - } + if (isRestart) + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_RESTART_REQUEST_CMDID); + else + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_START_REQUEST_CMDID); + if (ret < 0) { + WMA_LOGP("Failed to send vdev start command\n"); + adf_nbuf_free(buf); + return VOS_STATUS_E_FAILURE; + } return VOS_STATUS_SUCCESS; } @@ -4394,18 +4949,25 @@ void wma_vdev_resp_timer(void *data) wma = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, vos_context); pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); - WMA_LOGD("%s: request %d is timed out\n", __func__, tgt_req->msg_type); + WMA_LOGA("%s: request %d is timed out", __func__, tgt_req->msg_type); wma_find_vdev_req(wma, tgt_req->vdev_id, tgt_req->type); if (tgt_req->msg_type == WDA_CHNL_SWITCH_REQ) { tpSwitchChannelParams params = (tpSwitchChannelParams)tgt_req->user_data; params->status = VOS_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WDA_SWITCH_CHANNEL_REQ timedout", __func__); wma_send_msg(wma, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); } else if (tgt_req->msg_type == WDA_DELETE_BSS_REQ) { tpDeleteBssParams params = (tpDeleteBssParams)tgt_req->user_data; + struct wma_txrx_node *iface = &wma->interfaces[tgt_req->vdev_id]; peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, &peer_id); wma_remove_peer(wma, params->bssid, tgt_req->vdev_id, peer); + wmi_unified_vdev_down_send(wma->wmi_handle, tgt_req->vdev_id); + if (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) { + WMA_LOGD("%s: P2P BSS is stopped", __func__); + iface->bss_status = WMA_BSS_STATUS_STOPPED; + } #ifdef QCA_IBSS_SUPPORT if (wma_is_vdev_in_ibss_mode(wma, params->sessionId)) { del_sta_param.sessionId = params->sessionId; @@ -4415,7 +4977,25 @@ void wma_vdev_resp_timer(void *data) } #endif params->status = VOS_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WDA_DELETE_BSS_REQ timedout", __func__); wma_send_msg(wma, WDA_DELETE_BSS_RSP, (void *)params, 0); + if (iface->del_staself_req) { + WMA_LOGD("%s: scheduling defered deletion", __func__); + wma_vdev_detach(wma, iface->del_staself_req, 1); + } + } else if (tgt_req->msg_type == WDA_DEL_STA_SELF_REQ) { + struct wma_txrx_node *iface = + (struct wma_txrx_node *)tgt_req->user_data; + tpDelStaSelfParams params = + (tpDelStaSelfParams)iface->del_staself_req; + + params->status = VOS_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WDA_DEL_STA_SELF_REQ timedout", __func__); + wma_send_msg(wma, WDA_DEL_STA_SELF_RSP, + (void *)iface->del_staself_req, 0); + if(iface->addBssStaContext) + adf_os_mem_free(iface->addBssStaContext); + vos_mem_zero(iface, sizeof(*iface)); } vos_timer_destroy(&tgt_req->event_timeout); vos_mem_free(tgt_req); @@ -4423,7 +5003,7 @@ void wma_vdev_resp_timer(void *data) static struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, u_int8_t vdev_id, u_int32_t msg_type, u_int8_t type, - void *params) + void *params, u_int32_t timeout) { struct wma_target_req *req; @@ -4441,7 +5021,7 @@ static struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, u_int8_t vdev req->user_data = params; vos_timer_init(&req->event_timeout, VOS_TIMER_TYPE_SW, wma_vdev_resp_timer, req); - vos_timer_start(&req->event_timeout, 1000); + vos_timer_start(&req->event_timeout, timeout); adf_os_spin_lock_bh(&wma->vdev_respq_lock); list_add_tail(&req->node, &wma->vdev_resp_queue); adf_os_spin_unlock_bh(&wma->vdev_respq_lock); @@ -4476,7 +5056,7 @@ static void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) goto send_resp; } msg = wma_fill_vdev_req(wma, req.vdev_id, WDA_CHNL_SWITCH_REQ, - WMA_TARGET_REQ_TYPE_VDEV_START, params); + WMA_TARGET_REQ_TYPE_VDEV_START, params, 1000); if (!msg) { WMA_LOGP("Failed to fill channel switch request for vdev %d\n", req.vdev_id); @@ -4492,8 +5072,9 @@ static void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) #endif req.beacon_intval = 100; req.dtim_period = 1; - status = wma_vdev_start(wma, &req); - if (status != VOS_STATUS_SUCCESS) { + req.is_dfs = params->isDfsChannel; + status = wma_vdev_start(wma, &req, VOS_TRUE); + if (status != VOS_STATUS_SUCCESS) { wma_remove_vdev_req(wma, req.vdev_id, WMA_TARGET_REQ_TYPE_VDEV_START); WMA_LOGP("vdev start failed status = %d\n", status); goto send_resp; @@ -4739,6 +5320,10 @@ static int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, cmd->peer_vht_caps = params->vht_caps; #endif + + if (params->rmfEnabled) + cmd->peer_flags |= WMI_PEER_PMF; + rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >> IEEE80211_HTCAP_C_RXSTBC_S; if (rx_stbc) { @@ -4965,6 +5550,14 @@ static int32_t wma_set_priv_cfg(tp_wma_handle wma_handle, privcmd->param_vdev_id, privcmd->param_value); break; + case WMI_STA_SMPS_FORCE_MODE_CMDID: + wma_set_mimops(wma_handle, privcmd->param_vdev_id, + privcmd->param_value); + break; + case WMI_STA_SMPS_PARAM_CMDID: + wma_set_smps_params(wma_handle, privcmd->param_vdev_id, + privcmd->param_value); + break; default: WMA_LOGE("Invalid wma config command id:%d", privcmd->param_id); @@ -5003,13 +5596,49 @@ static int wmi_crash_inject(wmi_unified_t wmi_handle) return ret; } +static int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle, + u_int32_t vdev_id, u_int32_t param, u_int32_t value) +{ + wmi_sta_powersave_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + WMA_LOGD("Set Sta Ps param vdevId %d Param %d val %d", + vdev_id, param, value); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("Set Sta Ps param Mem Alloc Failed"); + return -ENOMEM; + } + + cmd = (wmi_sta_powersave_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_powersave_param_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->param = param; + cmd->value = value; + + if (wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_STA_POWERSAVE_PARAM_CMDID)) { + WMA_LOGE("Set Sta Ps param Failed vdevId %d Param %d val %d", + vdev_id, param, value); + adf_nbuf_free(buf); + return -EIO; + } + return 0; +} + static void wma_process_cli_set_cmd(tp_wma_handle wma, wda_cli_set_cmd_t *privcmd) { - int ret = 0, vid = privcmd->param_vdev_id; + int ret = 0, vid = privcmd->param_vdev_id, pps_val = 0; struct wma_txrx_node *intr = wma->interfaces; tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); + struct qpower_params *qparams = &intr[vid].config.qpower_params; WMA_LOGD("wmihandle %p", wma->wmi_handle); @@ -5151,6 +5780,137 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, break; } break; + case PPS_CMD: + WMA_LOGD("dbg pid %d pval %d", privcmd->param_id, + privcmd->param_value); + switch (privcmd->param_id) { + + case WMI_VDEV_PPS_PAID_MATCH: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_PAID_MATCH & 0xffff); + intr[vid].config.pps_params.paid_match_enable = privcmd->param_value; + break; + case WMI_VDEV_PPS_GID_MATCH: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_GID_MATCH & 0xffff); + intr[vid].config.pps_params.gid_match_enable = privcmd->param_value; + break; + case WMI_VDEV_PPS_EARLY_TIM_CLEAR: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EARLY_TIM_CLEAR & 0xffff); + intr[vid].config.pps_params.tim_clear = privcmd->param_value; + break; + case WMI_VDEV_PPS_EARLY_DTIM_CLEAR: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EARLY_DTIM_CLEAR & 0xffff); + intr[vid].config.pps_params.dtim_clear = privcmd->param_value; + break; + case WMI_VDEV_PPS_EOF_PAD_DELIM: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EOF_PAD_DELIM & 0xffff); + intr[vid].config.pps_params.eof_delim = privcmd->param_value; + break; + case WMI_VDEV_PPS_MACADDR_MISMATCH: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_MACADDR_MISMATCH & 0xffff); + intr[vid].config.pps_params.mac_match = privcmd->param_value; + break; + case WMI_VDEV_PPS_DELIM_CRC_FAIL: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_DELIM_CRC_FAIL & 0xffff); + intr[vid].config.pps_params.delim_fail = privcmd->param_value; + break; + case WMI_VDEV_PPS_GID_NSTS_ZERO: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_GID_NSTS_ZERO & 0xffff); + intr[vid].config.pps_params.nsts_zero = privcmd->param_value; + break; + case WMI_VDEV_PPS_RSSI_CHECK: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_RSSI_CHECK & 0xffff); + intr[vid].config.pps_params.rssi_chk = privcmd->param_value; + break; + default: + WMA_LOGE("Invalid param id 0x%x", privcmd->param_id); + break; + } + break; + + case QPOWER_CMD: + WMA_LOGD("QPOWER CLI CMD pid %d pval %d", privcmd->param_id, + privcmd->param_value); + switch (privcmd->param_id) { + case WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT: + WMA_LOGD("QPOWER CLI CMD:Ps Poll Cnt val %d", + privcmd->param_value); + /* Set the QPower Ps Poll Count */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-PsPollCnt Failed vdevId %d val %d", + vid, privcmd->param_value); + } else { + qparams->max_ps_poll_cnt = + privcmd->param_value; + } + break; + case WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE: + WMA_LOGD("QPOWER CLI CMD:Max Tx Before wake val %d", + privcmd->param_value); + /* Set the QPower Max Tx Before Wake */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-MaxTxBefWake Failed vId %d val %d", + vid, privcmd->param_value); + } else { + qparams->max_tx_before_wake = + privcmd->param_value; + } + break; + case WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + WMA_LOGD("QPOWER CLI CMD:Ps Poll Wake Inv val %d", + privcmd->param_value); + /* Set the QPower Spec Ps Poll Wake Inv */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-PsPoll WakeIntv Failed vId %d val %d", + vid, privcmd->param_value); + } else { + qparams->spec_ps_poll_wake_interval = + privcmd->param_value; + } + break; + case WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + WMA_LOGD("QPOWER CLI CMD:Spec NoData Ps Poll val %d", + privcmd->param_value); + /* Set the QPower Spec NoData PsPoll */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-SpecNoDataPsPoll Failed vId %d val %d", + vid, privcmd->param_value); + } else { + qparams->max_spec_nodata_ps_poll = + privcmd->param_value; + } + break; + + default: + WMA_LOGE("Invalid param id 0x%x", privcmd->param_id); + break; + } + break; + default: WMA_LOGE("Invalid vpdev command id"); } @@ -5180,33 +5940,6 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, case WMI_VDEV_PARAM_FIXED_RATE: intr[vid].config.tx_rate = privcmd->param_value; break; - case WMI_VDEV_PPS_PAID_MATCH: - intr[vid].config.pps_params.paid_match_enable = privcmd->param_value; - break; - case WMI_VDEV_PPS_GID_MATCH: - intr[vid].config.pps_params.gid_match_enable = privcmd->param_value; - break; - case WMI_VDEV_PPS_EARLY_TIM_CLEAR: - intr[vid].config.pps_params.tim_clear = privcmd->param_value; - break; - case WMI_VDEV_PPS_EARLY_DTIM_CLEAR: - intr[vid].config.pps_params.dtim_clear = privcmd->param_value; - break; - case WMI_VDEV_PPS_EOF_PAD_DELIM: - intr[vid].config.pps_params.eof_delim = privcmd->param_value; - break; - case WMI_VDEV_PPS_MACADDR_MISMATCH: - intr[vid].config.pps_params.mac_match = privcmd->param_value; - break; - case WMI_VDEV_PPS_DELIM_CRC_FAIL: - intr[vid].config.pps_params.delim_fail = privcmd->param_value; - break; - case WMI_VDEV_PPS_GID_NSTS_ZERO: - intr[vid].config.pps_params.nsts_zero = privcmd->param_value; - break; - case WMI_VDEV_PPS_RSSI_CHECK: - intr[vid].config.pps_params.rssi_chk = privcmd->param_value; - break; default: WMA_LOGE("Invalid wda_cli_set vdev command/Not" " yet implemented 0x%x", privcmd->param_id); @@ -5238,6 +5971,17 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, case WMI_PDEV_PARAM_RX_CHAIN_MASK: wma->pdevconfig.rxchainmask = privcmd->param_value; break; + case WMI_PDEV_PARAM_BURST_ENABLE: + wma->pdevconfig.burst_enable = privcmd->param_value; + if ((wma->pdevconfig.burst_enable == 1) && + (wma->pdevconfig.burst_dur == 0)) + wma->pdevconfig.burst_dur = WMA_DEFAULT_SIFS_BURST_DURATION; + else if (wma->pdevconfig.burst_enable == 0) + wma->pdevconfig.burst_dur = 0; + break; + case WMI_PDEV_PARAM_BURST_DUR: + wma->pdevconfig.burst_dur = privcmd->param_value; + break; case WMI_PDEV_PARAM_POWER_GATING_SLEEP: wma->pdevconfig.pwrgating = privcmd->param_value; break; @@ -5278,6 +6022,15 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, " yet implemented 0x%x", privcmd->param_id); break; } + } else if (5 == privcmd->param_vp_dev) { + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, privcmd->param_vdev_id, + WMI_VDEV_PARAM_PACKET_POWERSAVE, + pps_val); + if (ret) + WMA_LOGE("Failed to send wmi packet power save cmd"); + else + WMA_LOGD("Sent packet power save cmd %d value %x to target", + privcmd->param_id, pps_val); } } @@ -5318,33 +6071,7 @@ int wma_cli_get_command(void *wmapvosContext, int vdev_id, case WMI_VDEV_PARAM_FIXED_RATE: ret = intr[vdev_id].config.tx_rate; break; - case WMI_VDEV_PPS_PAID_MATCH: - ret = intr[vdev_id].config.pps_params.paid_match_enable; - break; - case WMI_VDEV_PPS_GID_MATCH: - ret = intr[vdev_id].config.pps_params.gid_match_enable; - break; - case WMI_VDEV_PPS_EARLY_TIM_CLEAR: - ret = intr[vdev_id].config.pps_params.tim_clear; - break; - case WMI_VDEV_PPS_EARLY_DTIM_CLEAR: - ret = intr[vdev_id].config.pps_params.dtim_clear; - break; - case WMI_VDEV_PPS_EOF_PAD_DELIM: - ret = intr[vdev_id].config.pps_params.eof_delim; - break; - case WMI_VDEV_PPS_MACADDR_MISMATCH: - ret = intr[vdev_id].config.pps_params.mac_match; - break; - case WMI_VDEV_PPS_DELIM_CRC_FAIL: - ret = intr[vdev_id].config.pps_params.delim_fail; - break; - case WMI_VDEV_PPS_GID_NSTS_ZERO: - ret = intr[vdev_id].config.pps_params.nsts_zero; - break; - case WMI_VDEV_PPS_RSSI_CHECK: - ret = intr[vdev_id].config.pps_params.rssi_chk; - break; + default: WMA_LOGE("Invalid cli_get vdev command/Not" " yet implemented 0x%x", param_id); @@ -5385,6 +6112,12 @@ int wma_cli_get_command(void *wmapvosContext, int vdev_id, case WMI_PDEV_PARAM_POWER_GATING_SLEEP: ret = wma->pdevconfig.pwrgating; break; + case WMI_PDEV_PARAM_BURST_ENABLE: + ret = wma->pdevconfig.burst_enable; + break; + case WMI_PDEV_PARAM_BURST_DUR: + ret = wma->pdevconfig.burst_dur; + break; default: WMA_LOGE("Invalid cli_get pdev command/Not" " yet implemented 0x%x", param_id); @@ -5403,43 +6136,66 @@ int wma_cli_get_command(void *wmapvosContext, int vdev_id, " yet implemented 0x%x", param_id); return -EINVAL; } - } - return ret; -} - -static int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle, - u_int32_t vdev_id, u_int32_t param, u_int32_t value) -{ - wmi_sta_powersave_param_cmd_fixed_param *cmd; - wmi_buf_t buf; - int32_t len = sizeof(*cmd); + } else if (PPS_CMD == vpdev) { + switch (param_id) { + case WMI_VDEV_PPS_PAID_MATCH: + ret = intr[vdev_id].config.pps_params.paid_match_enable; + break; + case WMI_VDEV_PPS_GID_MATCH: + ret = intr[vdev_id].config.pps_params.gid_match_enable; + break; + case WMI_VDEV_PPS_EARLY_TIM_CLEAR: + ret = intr[vdev_id].config.pps_params.tim_clear; + break; + case WMI_VDEV_PPS_EARLY_DTIM_CLEAR: + ret = intr[vdev_id].config.pps_params.dtim_clear; + break; + case WMI_VDEV_PPS_EOF_PAD_DELIM: + ret = intr[vdev_id].config.pps_params.eof_delim; + break; + case WMI_VDEV_PPS_MACADDR_MISMATCH: + ret = intr[vdev_id].config.pps_params.mac_match; + break; + case WMI_VDEV_PPS_DELIM_CRC_FAIL: + ret = intr[vdev_id].config.pps_params.delim_fail; + break; + case WMI_VDEV_PPS_GID_NSTS_ZERO: + ret = intr[vdev_id].config.pps_params.nsts_zero; + break; + case WMI_VDEV_PPS_RSSI_CHECK: + ret = intr[vdev_id].config.pps_params.rssi_chk; + break; + default: + WMA_LOGE("Invalid pps vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } else if (QPOWER_CMD == vpdev) { + switch (param_id) { + case WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT: + ret = intr[vdev_id].config.qpower_params.max_ps_poll_cnt; + break; - WMA_LOGD("Set Sta Ps param vdevId %d Param %d val %d", - vdev_id, param, value); + case WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE: + ret = intr[vdev_id].config.qpower_params.max_tx_before_wake; + break; - buf = wmi_buf_alloc(wmi_handle, len); - if (!buf) { - WMA_LOGP("Set Sta Ps param Mem Alloc Failed"); - return -ENOMEM; - } + case WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + ret = + intr[vdev_id].config.qpower_params.spec_ps_poll_wake_interval; + break; - cmd = (wmi_sta_powersave_param_cmd_fixed_param *) wmi_buf_data(buf); - WMITLV_SET_HDR(&cmd->tlv_header, - WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param, - WMITLV_GET_STRUCT_TLVLEN( - wmi_sta_powersave_param_cmd_fixed_param)); - cmd->vdev_id = vdev_id; - cmd->param = param; - cmd->value = value; + case WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + ret = intr[vdev_id].config.qpower_params.max_spec_nodata_ps_poll; + break; - if (wmi_unified_cmd_send(wmi_handle, buf, len, - WMI_STA_POWERSAVE_PARAM_CMDID)) { - WMA_LOGE("Set Sta Ps param Failed vdevId %d Param %d val %d", - vdev_id, param, value); - adf_nbuf_free(buf); - return -EIO; + default: + WMA_LOGE("Invalid generic vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } } - return 0; + return ret; } static void @@ -5618,7 +6374,7 @@ static void wma_add_bss_ap_mode(tp_wma_handle wma, tpAddBssParams add_bss) goto send_fail_resp; } msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, - WMA_TARGET_REQ_TYPE_VDEV_START, add_bss); + WMA_TARGET_REQ_TYPE_VDEV_START, add_bss, 1000); if (!msg) { WMA_LOGP("%s Failed to allocate vdev request vdev_id %d\n", __func__, vdev_id); @@ -5649,14 +6405,13 @@ static void wma_add_bss_ap_mode(tp_wma_handle wma, tpAddBssParams add_bss) vos_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, add_bss->ssId.length); - status = wma_vdev_start(wma, &req); + status = wma_vdev_start(wma, &req, VOS_FALSE); if (status != VOS_STATUS_SUCCESS) { wma_remove_vdev_req(wma, vdev_id, WMA_TARGET_REQ_TYPE_VDEV_START); goto peer_cleanup; } - /* Configure rest of bss info once the vdev started */ wma_vdev_set_bss_params(wma, vdev_id, add_bss->beaconInterval, add_bss->dtimPeriod, add_bss->shortSlotTimeSupported, add_bss->llbCoexist, @@ -5714,7 +6469,7 @@ static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) /* create new vdev for ibss */ vos_copy_macaddr((v_MACADDR_t *)&(add_sta_self_param.selfMacAddr), - (v_MACADDR_t *)&(add_bss->bssId)); + (v_MACADDR_t *)&(add_bss->selfMacAddr)); add_sta_self_param.sessionId = vdev_id; add_sta_self_param.type = WMI_VDEV_TYPE_IBSS; add_sta_self_param.subType = 0; @@ -5731,17 +6486,17 @@ static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) WMA_LOGE("%s: new vdev created for IBSS\n", __func__); /* create self peer */ - status = wma_create_peer(wma, pdev, vdev, add_bss->bssId, + status = wma_create_peer(wma, pdev, vdev, add_bss->selfMacAddr, WMI_PEER_TYPE_DEFAULT, vdev_id); if (status != VOS_STATUS_SUCCESS) { WMA_LOGE("%s: Failed to create peer\n", __func__); goto send_fail_resp; } - peer = ol_txrx_find_peer_by_addr(pdev, add_bss->bssId, &peer_id); + peer = ol_txrx_find_peer_by_addr(pdev, add_bss->selfMacAddr, &peer_id); if (!peer) { WMA_LOGE("%s Failed to find peer %pM\n", __func__, - add_bss->bssId); + add_bss->selfMacAddr); goto send_fail_resp; } @@ -5749,7 +6504,7 @@ static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) add_bss->operMode = BSS_OPERATIONAL_MODE_IBSS; msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, - WMA_TARGET_REQ_TYPE_VDEV_START, add_bss); + WMA_TARGET_REQ_TYPE_VDEV_START, add_bss, 1000); if (!msg) { WMA_LOGP("%s Failed to allocate vdev request vdev_id %d\n", __func__, vdev_id); @@ -5782,7 +6537,7 @@ static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) WMA_LOGD("%s: chan %d chan_offset %d\n", __func__, req.chan, req.chan_offset); WMA_LOGD("%s: ssid = %s\n", __func__, req.ssid.ssId); - status = wma_vdev_start(wma, &req); + status = wma_vdev_start(wma, &req, VOS_FALSE); if (status != VOS_STATUS_SUCCESS) { wma_remove_vdev_req(wma, vdev_id, WMA_TARGET_REQ_TYPE_VDEV_START); @@ -5833,6 +6588,8 @@ static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss) } adf_os_mem_copy(iface->addBssStaContext, &add_bss->staContext, sizeof(tAddStaParams)); + // Save parameters later needed by WDA_ADD_STA_REQ + iface->rmfEnabled = add_bss->rmfEnabled; iface->beaconInterval = add_bss->beaconInterval; iface->dtimPeriod = add_bss->dtimPeriod; iface->llbCoexist = add_bss->llbCoexist; @@ -5846,7 +6603,8 @@ static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss) goto send_fail_resp; } msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, - WMA_TARGET_REQ_TYPE_VDEV_START, add_bss); + WMA_TARGET_REQ_TYPE_VDEV_START, + add_bss, 1000); if (!msg) { WMA_LOGP("%s Failed to allocate vdev request vdev_id %d\n", __func__, vdev_id); @@ -5876,7 +6634,7 @@ static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss) vos_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, add_bss->ssId.length); - status = wma_vdev_start(wma, &req); + status = wma_vdev_start(wma, &req, VOS_FALSE); if (status != VOS_STATUS_SUCCESS) { wma_remove_vdev_req(wma, vdev_id, WMA_TARGET_REQ_TYPE_VDEV_START); @@ -5979,7 +6737,7 @@ static int wmi_unified_vdev_up_send(wmi_unified_t wmi, wmi_buf_t buf; int32_t len = sizeof(*cmd); - printk("%s: VDEV_UP\n", __func__); + WMA_LOGD("%s: VDEV_UP\n", __func__); WMA_LOGD("%s: vdev_id %d aid %d bssid %pM\n", __func__, vdev_id, aid, bssid); buf = wmi_buf_alloc(wmi, len); @@ -6259,6 +7017,95 @@ static int wmi_unified_csa_offload_enable(tp_wma_handle wma, return 0; } +#ifndef CONFIG_QCA_WIFI_ISOC +#ifdef QCA_IBSS_SUPPORT + +static u_int16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num) +{ + /* heart beat timer value look-up table */ + /* entry index : (the number of currently connected peers) - 1 + entry value : the heart time threshold value in seconds for + detecting ibss peer departure */ + static const u_int16_t heart_beat_timer[HDD_MAX_NUM_IBSS_STA] = { + 4, 8, 12, 16, 20, 24, 28, 32, + 36, 40, 44, 48, 52, 56, 60, 64, + 68, 72, 76, 80, 84, 88, 92, 96, + 100, 104, 108, 112, 116, 120, 124, 128}; + + if (peer_num < 1 || peer_num > HDD_MAX_NUM_IBSS_STA) + return 0; + + return heart_beat_timer[peer_num - 1]; + +} + +static void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma, + u_int8_t vdev_id, + int8_t peer_num_delta) +{ + ol_txrx_vdev_handle vdev; + int16_t new_peer_num; + u_int16_t new_timer_value_sec; + u_int32_t new_timer_value_ms; + + if (peer_num_delta != 1 && peer_num_delta != -1) { + WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta); + return; + } + + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("vdev not found : vdev_id %d", vdev_id); + return; + } + + new_peer_num = vdev->ibss_peer_num + peer_num_delta; + if (new_peer_num > HDD_MAX_NUM_IBSS_STA || new_peer_num < 0) { + WMA_LOGE("new peer num %d out of valid boundary", new_peer_num); + return; + } + + /* adjust peer numbers */ + vdev->ibss_peer_num = new_peer_num; + + /* reset timer value if all peers departed */ + if (new_peer_num == 0) { + vdev->ibss_peer_heart_beat_timer = 0; + return; + } + + /* calculate new timer value */ + new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num); + if (new_timer_value_sec == 0) { + WMA_LOGE("timer value %d is invalid for peer number %d", + new_timer_value_sec, new_peer_num); + return; + } + if (new_timer_value_sec == vdev->ibss_peer_heart_beat_timer) { + WMA_LOGD("timer value %d stays same, no need to notify target", + new_timer_value_sec); + return; + } + + /* send new timer value to target */ + vdev->ibss_peer_heart_beat_timer = new_timer_value_sec; + + new_timer_value_ms = ((u_int32_t)new_timer_value_sec) * 1000; + + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS, + new_timer_value_ms)) { + WMA_LOGE("Failed to set IBSS link monitoring timer value"); + return; + } + + WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d", + new_peer_num, new_timer_value_ms); +} + +#endif /* QCA_IBSS_SUPPORT */ +#endif /* CONFIG_QCA_WIFI_ISOC */ + #ifdef FEATURE_WLAN_TDLS static void wma_add_tdls_sta(tp_wma_handle wma, tpAddStaParams add_sta) { @@ -6447,6 +7294,10 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) status = VOS_STATUS_E_FAILURE; } + if (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) { + WMA_LOGD("%s: P2P BSS is started", __func__); + iface->bss_status = WMA_BSS_STATUS_STARTED; + } /* Sta is now associated, configure various params */ /* SM power save, configure the h/w as configured @@ -6470,7 +7321,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) (params->htCapable || params->vhtCapable)) wma_set_ppsconfig(params->smesessionId, WMA_VHT_PPS_DELIM_CRC_FAIL, 1); - + iface->aid = params->assocId; out: params->status = status; WMA_LOGD("%s: statype %d vdev_id %d aid %d bssid %pM staIdx %d status %d\n", @@ -6507,6 +7358,15 @@ static void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta) wma_add_sta_req_ap_mode(wma, add_sta); break; } + +#ifndef CONFIG_QCA_WIFI_ISOC +#ifdef QCA_IBSS_SUPPORT + /* adjust heart beat thresold timer value for detecting ibss peer departure */ + if (oper_mode == BSS_OPERATIONAL_MODE_IBSS) + wma_adjust_ibss_heart_beat_timer(wma, add_sta->smesessionId, 1); +#endif +#endif + } /* @@ -6555,7 +7415,9 @@ static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, wmi_buf_t buf; u_int8_t *buf_ptr; u_int8_t *key_data; - +#ifdef WLAN_FEATURE_11W + struct wma_txrx_node *iface = NULL; +#endif /* WLAN_FEATURE_11W */ if ((key_params->key_type == eSIR_ED_NONE && key_params->key_len) || (key_params->key_type != eSIR_ED_NONE && !key_params->key_len)) { @@ -6625,6 +7487,11 @@ static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, case eSIR_ED_CCMP: cmd->key_cipher = WMI_CIPHER_AES_CCM; break; +#ifdef WLAN_FEATURE_11W + case eSIR_ED_AES_128_CMAC: + cmd->key_cipher = WMI_CIPHER_AES_CMAC; + break; +#endif /* WLAN_FEATURE_11W */ default: /* TODO: MFP ? */ WMA_LOGE("%s:Invalid encryption type:%d", __func__, key_params->key_type); @@ -6664,6 +7531,19 @@ static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, #endif cmd->key_len = key_params->key_len; +#ifdef WLAN_FEATURE_11W + if (key_params->key_type == eSIR_ED_AES_128_CMAC) + { + iface = &wma_handle->interfaces[key_params->vdev_id]; + if (iface) { + iface->key.key_length = key_params->key_len; + vos_mem_copy (iface->key.key, + (const void *) key_params->key_data, + iface->key.key_length); + } + } +#endif /* WLAN_FEATURE_11W */ + WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d" " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id, key_params->key_idx, key_params->key_type, key_params->key_len, @@ -6711,11 +7591,18 @@ static void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info) vos_mem_copy(key_params.peer_mac, wma_handle->interfaces[key_info->smesessionId].bssid, ETH_ALEN); + } + else if (wlan_op_mode_ibss == txrx_vdev->opmode) { + /* vdev mac address will be passed for IBSS mode + ** Self Mac address is supposed to be in wma_handle->hwaddr + */ + vos_mem_copy(key_params.peer_mac, wma_handle->hwaddr, + ETH_ALEN); } else { - /* vdev mac address will be passed for AP/IBSS mode */ + /* vdev mac address will be passed for all other modes */ vos_mem_copy(key_params.peer_mac, txrx_vdev->mac_addr.raw, ETH_ALEN); - } + } if (key_info->numKeys == 0 && (key_info->encType == eSIR_ED_WEP40 || @@ -6945,31 +7832,6 @@ out: wma_send_msg(wma_handle, WDA_SET_STAKEY_RSP, (void *) key_info, 0); } -static int wmi_unified_vdev_down_send(wmi_unified_t wmi, u_int8_t vdev_id) -{ - wmi_vdev_down_cmd_fixed_param *cmd; - wmi_buf_t buf; - int32_t len = sizeof(*cmd); - - buf = wmi_buf_alloc(wmi, len); - if (!buf) { - WMA_LOGP("%s : wmi_buf_alloc failed\n", __func__); - return -ENOMEM; - } - cmd = (wmi_vdev_down_cmd_fixed_param *) wmi_buf_data(buf); - WMITLV_SET_HDR(&cmd->tlv_header, - WMITLV_TAG_STRUC_wmi_vdev_down_cmd_fixed_param, - WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_down_cmd_fixed_param)); - cmd->vdev_id = vdev_id; - if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_DOWN_CMDID)) { - WMA_LOGP("Failed to send vdev down\n"); - adf_nbuf_free(buf); - return -EIO; - } - WMA_LOGD("%s: vdev_id %d\n", __func__, vdev_id); - return 0; -} - static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, tpDeleteStaParams del_sta) { @@ -7059,6 +7921,9 @@ static void wma_delete_sta_req_sta_mode(tp_wma_handle wma, tpDeleteStaParams params) { VOS_STATUS status = VOS_STATUS_SUCCESS; + struct wma_txrx_node *iface; + iface = &wma->interfaces[params->smesessionId]; + iface->uapsd_cached_val = 0; #ifdef FEATURE_WLAN_TDLS if (STA_ENTRY_TDLS_PEER == params->staType) @@ -7068,11 +7933,6 @@ static void wma_delete_sta_req_sta_mode(tp_wma_handle wma, } #endif wma_roam_scan_offload_end_connect(wma); - if (wmi_unified_vdev_down_send(wma->wmi_handle, params->smesessionId) < 0) { - WMA_LOGP("%s: failed to bring down vdev %d\n", - __func__, params->smesessionId); - status = VOS_STATUS_E_FAILURE; - } params->status = status; WMA_LOGD("%s: vdev_id %d status %d\n", __func__, params->smesessionId, status); wma_send_msg(wma, WDA_DELETE_STA_RSP, (void *)params, 0); @@ -7103,6 +7963,15 @@ static void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta) wma_delete_sta_req_ap_mode(wma, del_sta); break; } + +#ifndef CONFIG_QCA_WIFI_ISOC +#ifdef QCA_IBSS_SUPPORT + /* adjust heart beat thresold timer value for detecting ibss peer departure */ + if (oper_mode == BSS_OPERATIONAL_MODE_IBSS) + wma_adjust_ibss_heart_beat_timer(wma, del_sta->smesessionId, -1); +#endif +#endif + } static int32_t wmi_unified_vdev_stop_send(wmi_unified_t wmi, u_int8_t vdev_id) @@ -7158,12 +8027,18 @@ static void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) goto out; } + /*Free the allocated stats response buffer for the the session*/ + if (wma->interfaces[params->smesessionId].stats_rsp) { + vos_mem_free(wma->interfaces[params->smesessionId].stats_rsp); + wma->interfaces[params->smesessionId].stats_rsp = NULL; + } + if (wlan_op_mode_ibss == txrx_vdev->opmode) { wma->ibss_started = 0; } msg = wma_fill_vdev_req(wma, params->smesessionId, WDA_DELETE_BSS_REQ, - WMA_TARGET_REQ_TYPE_VDEV_STOP, params); + WMA_TARGET_REQ_TYPE_VDEV_STOP, params, 1000); if (!msg) { WMA_LOGP("%s: Failed to fill vdev request for vdev_id %d\n", __func__, params->smesessionId); @@ -7633,7 +8508,10 @@ static void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) VOS_STATUS status; #endif u_int8_t *p2p_ie; - vdev = wma_find_vdev_by_addr(wma, bcn_info->bssId, &vdev_id); + tpAniBeaconStruct beacon; + + beacon = (tpAniBeaconStruct)(bcn_info->beacon); + vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id); if (!vdev) { WMA_LOGE("%s : failed to get vdev handle\n", __func__); return; @@ -7643,7 +8521,6 @@ static void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD)) { WMA_LOGE("%s : Beacon Offload Enabled Sending Unified command", __func__); - if (wmi_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4) < 0){ WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ", __func__); return; @@ -8107,15 +8984,26 @@ static void wma_enable_sta_ps_mode(tp_wma_handle wma, tpEnablePsParams ps_req) } } else if (eSIR_ADDON_ENABLE_UAPSD == ps_req->psSetting) { u_int32_t uapsd_val = 0; + struct wma_txrx_node *iface = &wma->interfaces[vdev_id]; uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams); - WMA_LOGD("Enable Uapsd vdevId %d Mask %d", vdev_id, uapsd_val); - ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, - WMI_STA_PS_PARAM_UAPSD, uapsd_val); - if (ret) { - WMA_LOGE("Enable Uapsd Failed vdevId %d", vdev_id); - ps_req->status = VOS_STATUS_E_FAILURE; - goto resp; + if(uapsd_val != iface->uapsd_cached_val) { + WMA_LOGD("Enable Uapsd vdevId %d Mask %d", + vdev_id, uapsd_val); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vdev_id, WMI_STA_PS_PARAM_UAPSD, + uapsd_val); + if (ret) { + WMA_LOGE("Enable Uapsd Failed vdevId %d", + vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + /* Cache the Uapsd Mask */ + iface->uapsd_cached_val = uapsd_val; + } else { + WMA_LOGD("Already Uapsd Enabled vdevId %d Mask %d", + vdev_id, uapsd_val); } WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id); @@ -8285,7 +9173,7 @@ wmi_unified_set_sta_uapsd_auto_trig_cmd( { wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd; int32_t ret; - u_int32_t param_len = (num_ac - 1) * + u_int32_t param_len = num_ac * sizeof(wmi_sta_uapsd_auto_trig_param); u_int32_t cmd_len = sizeof(*cmd) + param_len + WMI_TLV_HDR_SIZE; u_int32_t i; @@ -8713,6 +9601,15 @@ static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason) case WOW_REASON_WLAN_HB: return "WLAN_HB"; #endif /* FEATURE_WLAN_LPHB */ + + case WOW_REASON_CSA_EVENT: + return "CSA_EVENT"; + case WOW_REASON_PROBE_REQ_WPS_IE_RECV: + return "PROBE_REQ_RECV"; + case WOW_REASON_AUTH_REQ_RECV: + return "AUTH_REQ_RECV"; + case WOW_REASON_ASSOC_REQ_RECV: + return "ASSOC_REQ_RECV"; } return "unknown"; } @@ -8799,16 +9696,36 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, wma_wow_wake_reason_str(wake_info->wake_reason), wake_info->vdev_id); - if(wake_info->wake_reason == WOW_REASON_AP_ASSOC_LOST) + if (wake_info->wake_reason == WOW_REASON_AUTH_REQ_RECV) { + WMA_LOGD("Holding 50 sec wake_lock"); + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, 50000); + } else if (wake_info->wake_reason == WOW_REASON_ASSOC_REQ_RECV) { + WMA_LOGD("Holding 30 sec wake_lock"); + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, 30000); + } else if (wake_info->wake_reason == WOW_REASON_DEAUTH_RECVD) { + WMA_LOGD("Holding 30 sec wake_lock"); + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, 30000); + } else if (wake_info->wake_reason == WOW_REASON_DISASSOC_RECVD) { + WMA_LOGD("Holding 30 sec wake_lock"); + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, 30000); + } + + if(wake_info->wake_reason == WOW_REASON_AP_ASSOC_LOST) { + WMA_LOGA("Beacon miss indication on vdev %x", + wake_info->vdev_id); wma_beacon_miss_handler(wma, wake_info->vdev_id); - + } +#ifdef FEATURE_WLAN_SCAN_PNO if (wake_info->wake_reason == WOW_REASON_NLOD) { node = &wma->interfaces[wake_info->vdev_id]; if (node) { WMA_LOGD("NLO match happened"); node->nlo_match_evt_received = TRUE; } + vos_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_WAKE_LOCK_TIMEOUT); } +#endif if (wake_info->wake_reason == WOW_REASON_CSA_EVENT) { WMI_CSA_HANDLING_EVENTID_param_tlvs param; @@ -9065,6 +9982,9 @@ int wma_enable_wow_in_fw(WMA_HANDLE handle) WMA_LOGD("WOW enabled successfully in fw"); + HTCCancelDeferredTargetSleep(vos_get_context(VOS_MODULE_ID_HIF, + wma->vos_context)); + wma->wow.wow_enable_cmd_sent = TRUE; return VOS_STATUS_SUCCESS; } @@ -9131,99 +10051,22 @@ static VOS_STATUS wma_wow_usr(tp_wma_handle wma, u_int8_t vdev_id, static VOS_STATUS wma_wow_ap(tp_wma_handle wma, u_int8_t vdev_id, u_int8_t *enable_ptrn_match) { - u_int8_t unicast_ptrn[] = { 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08 }; - u_int8_t unicst_mask[] = { 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7f }; - u_int8_t unicst_offset = 0; u_int8_t arp_ptrn[] = { 0x08, 0x06 }; u_int8_t arp_mask[] = { 0xff, 0xff }; u_int8_t arp_offset = 20; - u_int8_t discvr_ptrn[] = { 0xe0, 0x00, 0x00, 0xf8 }; - u_int8_t discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 }; - u_int8_t discvr_offset = 38; - u_int8_t dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ }; - u_int8_t dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ }; - u_int8_t dhcp_offset = 0, free_slot; - VOS_STATUS ret = VOS_STATUS_SUCCESS; - - if (!wma->interfaces[vdev_id].vdev_up || - !WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, - WMI_SERVICE_BEACON_OFFLOAD)) { - return ret; - } - - free_slot = wma->wow.total_free_ptrn_id - - wma->wow.used_free_ptrn_id + 1; - - if (free_slot < WMA_AP_WOW_DEFAULT_PTRN_MAX) { - WMA_LOGD("Free slots are not enough, avail:%d, need: %d", - free_slot, WMA_AP_WOW_DEFAULT_PTRN_MAX); - WMA_LOGD("Ignoring default AP mode wow pattern for vdev : %d", - vdev_id); - return ret; - } - - WMA_LOGD("Configuring default AP mode wow pattern for vdev %d", - vdev_id); - - /* Setup unicast IP, EAPOL-like and ARP pkt pattern */ - ret = wma_send_wow_patterns_to_fw(wma, vdev_id, - wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], - unicast_ptrn, sizeof(unicast_ptrn), - unicst_offset, unicst_mask, sizeof(unicst_mask)); - if (ret != VOS_STATUS_SUCCESS) { - WMA_LOGE("Failed to add WOW unicast IP pattern"); - return ret; - } + VOS_STATUS ret; - /* Setup all ARP pkt pattern */ + /* Setup all ARP pkt pattern. This is dummy pattern hence the lenght + is zero */ ret = wma_send_wow_patterns_to_fw(wma, vdev_id, wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], - arp_ptrn, sizeof(arp_ptrn), arp_offset, - arp_mask, sizeof(arp_mask)); + arp_ptrn, 0, arp_offset, + arp_mask, 0); if (ret != VOS_STATUS_SUCCESS) { WMA_LOGE("Failed to add WOW ARP pattern"); return ret; } - /* - * Setup multicast pattern for mDNS 224.0.0.251, - * SSDP 239.255.255.250 and LLMNR 224.0.0.252 - */ - ret = wma_send_wow_patterns_to_fw(wma, vdev_id, - wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], - discvr_ptrn, sizeof(discvr_ptrn), discvr_offset, - discvr_mask, sizeof(discvr_mask)); - if (ret != VOS_STATUS_SUCCESS) { - WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern"); - return ret; - } - - /* Setup all DHCP broadcast pkt pattern */ - ret = wma_send_wow_patterns_to_fw(wma, vdev_id, - wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], - dhcp_pattern, sizeof(dhcp_pattern), dhcp_offset, - dhcp_mask, sizeof(dhcp_mask)); - if (ret != VOS_STATUS_SUCCESS) { - WMA_LOGE("Failed to add WOW DHCP broadcast pattern"); - return ret; - } - *enable_ptrn_match = 1 << vdev_id; return ret; } @@ -9360,12 +10203,14 @@ static bool wma_is_wow_prtn_cached(tp_wma_handle wma, u_int8_t vdev_id) * Pushes wow patterns from local cache to FW and configures * wakeup trigger events. */ -static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma) +static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma, + v_BOOL_t pno_in_progress) { struct wma_txrx_node *iface; VOS_STATUS ret = VOS_STATUS_SUCCESS; u_int8_t ptrn_id, vdev_id; u_int8_t enable_ptrn_match = 0; + v_BOOL_t ap_vdev_available = FALSE; WMA_LOGD("Clearing already configured wow patterns in fw"); @@ -9386,14 +10231,17 @@ static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma) if (!iface->handle || !iface->ptrn_match_enable || - (!wma_is_vdev_in_ap_mode(wma, vdev_id) && + (!(wma_is_vdev_in_ap_mode(wma, vdev_id)|| wma_is_vdev_in_ibss_mode(wma, vdev_id)) && !iface->conn_state)) continue; + if (wma_is_vdev_in_ap_mode(wma, vdev_id) || wma_is_vdev_in_ibss_mode(wma, vdev_id)) + ap_vdev_available = TRUE; + if (wma_is_wow_prtn_cached(wma, vdev_id)) { /* Configure wow patterns provided by the user */ ret = wma_wow_usr(wma, vdev_id, &enable_ptrn_match); - } else if (wma_is_vdev_in_ap_mode(wma, vdev_id)) { + } else if (wma_is_vdev_in_ap_mode(wma, vdev_id) ||wma_is_vdev_in_ibss_mode(wma, vdev_id)) { /* Configure AP mode default wow patterns */ ret = wma_wow_ap(wma, vdev_id, &enable_ptrn_match); } else { @@ -9406,6 +10254,16 @@ static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma) } /* + * Configure csa ie wakeup event. + */ + ret = wma_add_wow_wakeup_event(wma, WOW_CSA_IE_EVENT, TRUE); + + if (ret != VOS_STATUS_SUCCESS) + return ret; + + WMA_LOGD("CSA IE match is enabled in fw"); + + /* * Configure pattern match wakeup event. FW does pattern match * only if pattern match event is enabled. */ @@ -9467,6 +10325,46 @@ static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma) wma->wow.gtk_err_enable ? "enabled" : "disabled"); } #endif + /* Configure probe req based wakeup */ + ret = wma_add_wow_wakeup_event(wma, WOW_PROBE_REQ_WPS_IE_EVENT, + ap_vdev_available); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to configure probe req based wakeup"); + } else { + WMA_LOGD("Probe req based wakeup is %s in fw", + ap_vdev_available ? "enabled" : "disabled"); + } + + /* Configure auth req based wakeup */ + ret = wma_add_wow_wakeup_event(wma, WOW_AUTH_REQ_EVENT, + ap_vdev_available); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to configure auth req based wakeup"); + } else { + WMA_LOGD("Auth req based wakeup is %s in fw", + ap_vdev_available ? "enabled" : "disabled"); + } + + /* Configure assoc req based wakeup */ + ret = wma_add_wow_wakeup_event(wma, WOW_ASSOC_REQ_EVENT, + ap_vdev_available); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to configure assoc req based wakeup"); + } else { + WMA_LOGD("Assoc req based wakeup is %s in fw", + ap_vdev_available ? "enabled" : "disabled"); + } + + /* Configure pno based wakeup */ + ret = wma_add_wow_wakeup_event(wma, WOW_NLO_DETECTED_EVENT, + pno_in_progress); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to configure pno based wakeup"); + } else { + WMA_LOGD("PNO based wakeup is %s in fw", + pno_in_progress ? "enabled" : "disabled"); + } + /* WOW is enabled in pcie suspend callback */ wma->wow.wow_enable = TRUE; wma->wow.wow_enable_cmd_sent = FALSE; @@ -9654,7 +10552,7 @@ static VOS_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) * 3) Is PNO in progress in any one of vdev ? */ for (i = 0; i < wma->max_bssid; i++) { - if (wma_is_vdev_in_ap_mode(wma, i) && + if ( (wma_is_vdev_in_ap_mode(wma, i) || wma_is_vdev_in_ibss_mode(wma, i)) && wma->interfaces[i].vdev_up && WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD)) { @@ -9687,7 +10585,7 @@ enable_wow: * At this point, suspend indication is received on * last vdev. It's the time to enable wow in fw. */ - ret = wma_feed_wow_config_to_fw(wma); + ret = wma_feed_wow_config_to_fw(wma, pno_in_progress); if (ret != VOS_STATUS_SUCCESS) { vos_mem_free(info); return ret; @@ -9771,6 +10669,7 @@ static VOS_STATUS wma_resume_req(tp_wma_handle wma, tpSirWlanResumeParam info) ret = wma_send_host_wakeup_ind_to_fw(wma); vos_mem_free(info); + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, 2000); return ret; } @@ -9787,6 +10686,58 @@ int wma_is_wow_mode_selected(WMA_HANDLE handle) return wma->wow.wow_enable; } +tAniGetPEStatsRsp * wma_get_stats_rsp_buf(tAniGetPEStatsReq *get_stats_param) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tANI_U32 len, temp_mask, counter = 0; + + len= sizeof(tAniGetPEStatsRsp); + temp_mask = get_stats_param->statsMask; + + while (temp_mask) { + if (temp_mask & 1) { + switch (counter) { + case eCsrSummaryStats: + len += sizeof(tCsrSummaryStatsInfo); + break; + case eCsrGlobalClassAStats: + len += sizeof(tCsrGlobalClassAStatsInfo); + break; + case eCsrGlobalClassBStats: + len += sizeof(tCsrGlobalClassBStatsInfo); + break; + case eCsrGlobalClassCStats: + len += sizeof(tCsrGlobalClassCStatsInfo); + break; + case eCsrGlobalClassDStats: + len += sizeof(tCsrGlobalClassDStatsInfo); + break; + case eCsrPerStaStats: + len += sizeof(tCsrPerStaStatsInfo); + break; + } + } + + counter++; + temp_mask >>= 1; + } + + stats_rsp_params = (tAniGetPEStatsRsp *)vos_mem_malloc(len); + if (!stats_rsp_params) { + WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp"); + VOS_ASSERT(0); + return NULL; + } + + vos_mem_zero(stats_rsp_params, len); + stats_rsp_params->staId = get_stats_param->staId; + stats_rsp_params->statsMask = get_stats_param->statsMask; + stats_rsp_params->msgType = WDA_GET_STATISTICS_RSP; + stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp); + stats_rsp_params->rc = eHAL_STATUS_SUCCESS; + return stats_rsp_params; +} + /* function : wma_get_stats_req * Description : return the statistics * Args : wma handle, pointer to tAniGetPEStatsReq @@ -9796,32 +10747,70 @@ static void wma_get_stats_req(WMA_HANDLE handle, tAniGetPEStatsReq *get_stats_param) { tp_wma_handle wma_handle = (tp_wma_handle) handle; + struct wma_txrx_node *node; + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; tAniGetPEStatsRsp *pGetPEStatsRspParams; + u_int8_t len = sizeof(wmi_request_stats_cmd_fixed_param); - if(get_stats_param) - vos_mem_free(get_stats_param); + WMA_LOGD("%s: Enter", __func__); + node = &wma_handle->interfaces[get_stats_param->sessionId]; + if (node->stats_rsp) { + pGetPEStatsRspParams = node->stats_rsp; + if (pGetPEStatsRspParams->staId == get_stats_param->staId && + pGetPEStatsRspParams->statsMask == + get_stats_param->statsMask) { + WMA_LOGI("Stats for staId %d with stats mask %d " + "is pending.... ignore new request", + get_stats_param->staId, + get_stats_param->statsMask); + goto end; + } else { + vos_mem_free(node->stats_rsp); + node->stats_rsp = NULL; + node->fw_stats_set = 0; + } + } - pGetPEStatsRspParams = - (tAniGetPEStatsRsp *)vos_mem_malloc(sizeof(tAniGetPEStatsRsp)); + pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param); + if (!pGetPEStatsRspParams) + goto end; - if(!pGetPEStatsRspParams) { - WMA_LOGE("%s: Memory Allocation Failure", __func__); - return; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed to allocate wmi buffer", __func__); + goto failed; } - vos_mem_zero(pGetPEStatsRspParams, sizeof(tAniGetPEStatsRsp)); - pGetPEStatsRspParams->msgLen = sizeof(tAniGetPEStatsRsp); + node->fw_stats_set = 0; + node->stats_rsp = pGetPEStatsRspParams; + cmd = (wmi_request_stats_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param)); + cmd->stats_id = WMI_REQUEST_PEER_STAT|WMI_REQUEST_PDEV_STAT| + WMI_REQUEST_VDEV_STAT; + cmd->vdev_id = get_stats_param->sessionId; + WMI_CHAR_ARRAY_TO_MAC_ADDR(node->bssid, &cmd->peer_macaddr); + WMA_LOGD("STATS REQ VDEV_ID:%d-->", cmd->vdev_id); + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_REQUEST_STATS_CMDID)) { - /* TODO: As of now there is no WMI command to get the - * statistics. If WMI command for getting stats is available, - * then send the WMI command for getting the stats. - * Return status as FAILURE for now */ - pGetPEStatsRspParams->rc = eHAL_STATUS_FAILURE; + vos_mem_free(buf); + goto failed; + } + + goto end; +failed: + pGetPEStatsRspParams->rc = eHAL_STATUS_FAILURE; + node->stats_rsp = NULL; /* send response to UMAC*/ wma_send_msg(wma_handle, WDA_GET_STATISTICS_RSP, pGetPEStatsRspParams, 0) ; - +end: + vos_mem_free(get_stats_param); + WMA_LOGD("%s: Exit", __func__); return; } @@ -10570,7 +11559,7 @@ static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, tpSirHostOffloadR /* Fill data only for NS offload in the first ARP tuple for LA */ if (!bArpOnly && - (pHostOffloadParams->enableOrDisable == SIR_OFFLOAD_ENABLE && i==0)) { + ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE) && i==0)) { ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; /*Copy the target/solicitation/remote ip addr */ @@ -10608,7 +11597,7 @@ static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, tpSirHostOffloadR WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE)); /* Fill data for ARP and NS in the first tupple for LA */ - if ((wma->mArpInfo.enableOrDisable == SIR_OFFLOAD_ENABLE) && (i==0)) { + if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE) && (i==0)) { /*Copy the target ip addr and flags*/ arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID; A_MEMCPY(&arp_tuple->target_ipaddr,wma->mArpInfo.params.hostIpv4Addr, @@ -11956,7 +12945,7 @@ static int wma_roam_event_callback(WMA_HANDLE handle, u_int8_t *event_buf, switch(wmi_event->reason) { case WMI_ROAM_REASON_BMISS: - WMA_LOGD("%s:Beacon Miss for vdevid %x",__func__, + WMA_LOGA("Beacon Miss for vdevid %x", wmi_event->vdev_id); wma_beacon_miss_handler(wma_handle, wmi_event->vdev_id); break; @@ -12241,7 +13230,8 @@ wma_batch_scan_result_event_handler pHddApMetaInfo->ssid[0] = '\0'; } pHddApMetaInfo->ch = network_info->ch; - pHddApMetaInfo->rssi = network_info->rssi; + pHddApMetaInfo->rssi = ((network_info->rssi + 100) - + WMI_DEFAULT_NOISE_FLOOR_DBM); pHddApMetaInfo->timestamp = network_info->timestamp; WMA_LOGD("ch %d rssi %d timestamp %d",pHddApMetaInfo->ch, @@ -12464,14 +13454,6 @@ VOS_STATUS wma_start(v_VOID_t *vos_ctx) vos_status = VOS_STATUS_E_FAILURE; goto end; } - /* register target stats event handler */ - status = wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_UPDATE_STATS_EVENTID, - wmi_unified_update_stats_event_handler); - if (status) { - WMA_LOGP("Failed to register stats event handler"); - vos_status = VOS_STATUS_E_FAILURE; - goto end; - } #ifdef FEATURE_WLAN_SCAN_PNO if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, @@ -12573,6 +13555,10 @@ VOS_STATUS wma_start(v_VOID_t *vos_ctx) goto end; } +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_init(&wma_handle->pno_wake_lock, "wlan_pno_wl"); +#endif + end: WMA_LOGD("%s: Exit", __func__); return vos_status; @@ -12681,11 +13667,16 @@ VOS_STATUS wma_close(v_VOID_t *vos_ctx) ptrn_id++) wma_free_wow_ptrn(wma_handle, ptrn_id); +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_destroy(&wma_handle->pno_wake_lock); +#endif /* unregister Firmware debug log */ vos_status = dbglog_deinit(wma_handle->wmi_handle); if(vos_status != VOS_STATUS_SUCCESS) WMA_LOGP("dbglog_deinit failed"); + + vos_wake_lock_destroy(&wma_handle->wow_wake_lock); /* close the vos events */ vos_event_destroy(&wma_handle->wma_ready_event); vos_event_destroy(&wma_handle->target_suspend); @@ -12988,6 +13979,8 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) hdd_tgt_cfg.band_cap = eCSR_BAND_ALL; } + hdd_tgt_cfg.max_intf_count = wma_handle->wlan_resource_config.num_vdevs; + adf_os_mem_copy(hdd_tgt_cfg.hw_macaddr.bytes, wma_handle->hwaddr, ATH_MAC_LEN); @@ -13251,6 +14244,39 @@ v_VOID_t wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) } } +static void wma_set_regdomain(a_uint32_t regdmn) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + u_int32_t modeSelect = 0xFFFFFFFF; + + /* Set DFS regulatory domain */ + wma_set_dfs_regdomain(wma); + + switch (wma->phy_capability) { + case WMI_11G_CAPABILITY: + case WMI_11NG_CAPABILITY: + modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO | + REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE | + REGDMN_MODE_11A_QUARTER_RATE | REGDMN_MODE_11NA_HT20 | + REGDMN_MODE_11NA_HT40PLUS | REGDMN_MODE_11NA_HT40MINUS | + REGDMN_MODE_11AC_VHT20 | REGDMN_MODE_11AC_VHT40PLUS | + REGDMN_MODE_11AC_VHT40MINUS | REGDMN_MODE_11AC_VHT80); + break; + case WMI_11A_CAPABILITY: + case WMI_11NA_CAPABILITY: + case WMI_11AC_CAPABILITY: + modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G | + REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 | + REGDMN_MODE_11NG_HT40PLUS | REGDMN_MODE_11NG_HT40MINUS | + REGDMN_MODE_11AC_VHT20_2G | REGDMN_MODE_11AC_VHT40_2G | + REGDMN_MODE_11AC_VHT80_2G); + break; + } + + return; +} + /* function : wma_rx_ready_event * Descriptin : * Args : @@ -13330,6 +14356,8 @@ v_VOID_t wma_rx_ready_event(WMA_HANDLE handle, void *cmd_param_info) vos_event_set(&wma_handle->wma_ready_event); + wma_set_dfs_regdomain(wma_handle); + WMA_LOGD("Exit"); } @@ -13481,6 +14509,14 @@ VOS_STATUS WDA_TxPacket(void *wma_context, void *tx_frame, u_int16_t frmLen, tpSirMacFrameCtl pFc = (tpSirMacFrameCtl)(adf_nbuf_data(tx_frame)); u_int8_t use_6mbps = 0; u_int8_t downld_comp_required = 0; +#ifdef WLAN_FEATURE_11W + tANI_U8 *pFrame = NULL; + void *pPacket = NULL; + u_int16_t newFrmLen = 0; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); +#endif /* WLAN_FEATURE_11W */ /* Get the vdev handle from vdev id */ txrx_vdev = wma_handle->interfaces[vdev_id].handle; @@ -13495,6 +14531,12 @@ VOS_STATUS WDA_TxPacket(void *wma_context, void *tx_frame, u_int16_t frmLen, return VOS_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_11W + if(!pMac) { + WMA_LOGE("pMac Handle is NULL"); + return VOS_STATUS_E_FAILURE; + } +#endif /* WLAN_FEATURE_11W */ /* * Currently only support to * send 80211 Mgmt and 80211 Data are added. @@ -13504,6 +14546,43 @@ VOS_STATUS WDA_TxPacket(void *wma_context, void *tx_frame, u_int16_t frmLen, WMA_LOGE("No Support to send other frames except 802.11 Mgmt/Data"); return VOS_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_11W + if ((iface && iface->rmfEnabled && pFc->wep) && + (frmType == HAL_TXRX_FRM_802_11_MGMT) && + (pFc->subType == SIR_MAC_MGMT_DISASSOC || + pFc->subType == SIR_MAC_MGMT_DEAUTH || + pFc->subType == SIR_MAC_MGMT_ACTION)) { + struct ieee80211_frame *wh = + (struct ieee80211_frame *)adf_nbuf_data(tx_frame); + /* Allocate extra bytes for privacy header and trailer */ + newFrmLen = frmLen + IEEE80211_CCMP_HEADERLEN + IEEE80211_CCMP_MICLEN; + vos_status = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )newFrmLen, ( void** ) &pFrame, + ( void** ) &pPacket ); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGP("Failed to allocate %d bytes for RMF" + " status code (%x)", newFrmLen, vos_status); + /* Free the original packet memory */ + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + goto error; + } + + /* Initialize the frame with 0's and only fill + MAC header and data, Keep the CCMP header and + trailer as 0's, firmware shall fill this */ + vos_mem_set( pFrame, newFrmLen , 0 ); + vos_mem_copy( pFrame, wh, sizeof(*wh)); + vos_mem_copy( pFrame + sizeof(*wh) + IEEE80211_CCMP_HEADERLEN, + pData + sizeof(*wh), frmLen - sizeof(*wh)); + + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + tx_frame = pPacket; + frmLen = newFrmLen; + } +#endif /* WLAN_FEATURE_11W */ if ((frmType == HAL_TXRX_FRM_802_11_MGMT) && (pFc->subType == SIR_MAC_MGMT_PROBE_RSP)) { @@ -13787,15 +14866,21 @@ int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) else { cmd->suspend_opt = WMI_PDEV_SUSPEND; } - + vos_event_reset(&wma_handle->target_suspend); if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len, WMI_PDEV_SUSPEND_CMDID)) { adf_nbuf_free(wmibuf); return -1; } - vos_event_reset(&wma_handle->target_suspend); - return vos_wait_single_event(&wma_handle->target_suspend, - WMA_TGT_SUSPEND_COMPLETE_TIMEOUT); + if (vos_wait_single_event(&wma_handle->target_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) + != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to suspend target"); + return -1; + } + HTCCancelDeferredTargetSleep(vos_get_context(VOS_MODULE_ID_HIF, + wma_handle->vos_context)); + return 0; } void wma_target_suspend_complete(void *context) @@ -14580,3 +15665,336 @@ static int wma_update_tdls_peer_state(WMA_HANDLE handle, } #endif /* FEATURE_WLAN_TDLS */ +/* + * Attach DFS methods to the umac state. + */ +struct ieee80211com* wma_dfs_attach(struct ieee80211com *dfs_ic) +{ + /*Allocate memory for dfs_ic before passing it up to dfs_attach()*/ + dfs_ic = (struct ieee80211com *) + OS_MALLOC(NULL, sizeof(struct ieee80211com), GFP_ATOMIC); + if (dfs_ic == NULL) + { + WMA_LOGE("%s:Allocation of dfs_ic failed %zu", + __func__, sizeof(struct ieee80211com)); + return NULL; + } + OS_MEMZERO(dfs_ic, sizeof (struct ieee80211com)); + /* DFS pattern matching hooks */ + dfs_ic->ic_dfs_attach = ol_if_dfs_attach; + dfs_ic->ic_dfs_disable = ol_if_dfs_disable; + dfs_ic->ic_find_channel = ieee80211_find_channel; + dfs_ic->ic_dfs_enable = ol_if_dfs_enable; + dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz; + + /* Hardware facing hooks */ + dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy; + dfs_ic->ic_get_mib_cycle_counts_pct = + ol_if_dfs_get_mib_cycle_counts_pct; + dfs_ic->ic_get_TSF64 = ol_if_get_tsf64; + + /* NOL related hooks */ + dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol; + /* + * Hooks from wma/dfs/ back + * into the PE/SME + * and shared DFS code + */ + dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs; + + /* Initializes DFS Data Structures and queues*/ + dfs_attach(dfs_ic); + + return dfs_ic; +} + +/* + * Configures Radar Filters during + * vdev start/channel change/regulatory domain + * change.This Configuration enables to program + * the DFS pattern matching module. + */ +void +wma_dfs_configure(struct ieee80211com *ic) +{ + struct ath_dfs_radar_tab_info rinfo; + int dfsdomain; + if(ic == NULL) + { + WMA_LOGE("%s: DFS ic is Invalid\n",__func__); + return; + } + + dfsdomain = ic->current_dfs_regdomain; + + /* Fetch current radar patterns from the lmac */ + OS_MEMZERO(&rinfo, sizeof(rinfo)); + + /* + * Look up the current DFS + * regulatory domain and decide + * which radar pulses to use. + */ + switch (dfsdomain) + { + case DFS_FCC_DOMAIN: + WMA_LOGI("%s: DFS-FCC domain\n",__func__); + rinfo.dfsdomain = DFS_FCC_DOMAIN; + rinfo.dfs_radars = dfs_fcc_radars; + rinfo.numradars = ARRAY_LENGTH(dfs_fcc_radars); + rinfo.b5pulses = dfs_fcc_bin5pulses; + rinfo.numb5radars = ARRAY_LENGTH(dfs_fcc_bin5pulses); + break; + case DFS_ETSI_DOMAIN: + WMA_LOGI("%s: DFS-ETSI domain\n",__func__); + rinfo.dfsdomain = DFS_ETSI_DOMAIN; + rinfo.dfs_radars = dfs_etsi_radars; + rinfo.numradars = ARRAY_LENGTH(dfs_etsi_radars); + rinfo.b5pulses = NULL; + rinfo.numb5radars = 0; + break; + case DFS_MKK4_DOMAIN: + WMA_LOGI("%s: DFS-MKK4 domain\n",__func__); + rinfo.dfsdomain = DFS_MKK4_DOMAIN; + rinfo.dfs_radars = dfs_mkk4_radars; + rinfo.numradars = ARRAY_LENGTH(dfs_mkk4_radars); + rinfo.b5pulses = dfs_jpn_bin5pulses; + rinfo.numb5radars = ARRAY_LENGTH(dfs_jpn_bin5pulses); + break; + default: + WMA_LOGI("%s: DFS-UNINT domain\n",__func__); + rinfo.dfsdomain = DFS_UNINIT_DOMAIN; + rinfo.dfs_radars = NULL; + rinfo.numradars = 0; + rinfo.b5pulses = NULL; + rinfo.numb5radars = 0; + break; + } + + /* + * Set the regulatory domain, + * radar pulse table and enable + * radar events if required. + */ + dfs_radar_enable(ic, &rinfo); +} + +/* + * Set the Channel parameters in to DFS module + * Also,configure the DFS radar filters for + * matching the DFS phyerrors. + */ +struct ieee80211_channel * +wma_dfs_configure_channel(struct ieee80211com *dfs_ic, + wmi_channel *chan, + WLAN_PHY_MODE chanmode, + struct wma_vdev_start_req *req) +{ + if(dfs_ic == NULL) + { + WMA_LOGE("%s: DFS ic is Invalid\n",__func__); + return NULL; + } + dfs_ic->ic_curchan = (struct ieee80211_channel *) OS_MALLOC(NULL, + sizeof(struct ieee80211_channel), + GFP_ATOMIC); + if (dfs_ic->ic_curchan == NULL) + { + WMA_LOGE("allocation of dfs_ic->ic_curchan failed %zu \n", + __func__, + sizeof(struct ieee80211_channel)); + return NULL; + } + OS_MEMZERO(dfs_ic->ic_curchan, sizeof (struct ieee80211_channel)); + + dfs_ic->ic_curchan->ic_ieee = req->chan; + dfs_ic->ic_curchan->ic_freq = chan->mhz; + dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = chan->band_center_freq1; + dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = chan->band_center_freq2; + + if ( (dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) && + (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END) ) + { + dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ; + } + if(chanmode == MODE_11AC_VHT80) + { + dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80; + } + if (req->chan_offset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + { + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? + IEEE80211_CHAN_VHT40PLUS : IEEE80211_CHAN_HT40PLUS); + } + else if (req->chan_offset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + { + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? + IEEE80211_CHAN_VHT40MINUS : IEEE80211_CHAN_HT40MINUS); + } + else if (req->chan_offset == PHY_SINGLE_CHANNEL_CENTERED) + { + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? IEEE80211_CHAN_VHT20 : IEEE80211_CHAN_HT20); + } + dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS; + + if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) + { + dfs_ic->ic_opmode = IEEE80211_M_HOSTAP; + dfs_ic->vdev_id = req->vdev_id; + } + + /* + * Configuring the DFS with current channel and the radar filters + */ + wma_dfs_configure(dfs_ic); + WMA_LOGI("%s: DFS- CHANNEL CONFIGURED\n",__func__); + return dfs_ic->ic_curchan; +} +/* + * Configure the regulatory domain for DFS radar filter initialization + */ +void +wma_set_dfs_regdomain(tp_wma_handle wma) +{ + u_int8_t ctl; + u_int32_t regdmn = wma->reg_cap.eeprom_rd; + + if (regdmn < 0) + { + WMA_LOGE("%s:DFS-Invalid regdomain\n",__func__); + } + ctl = regdmn_get_ctl_for_regdmn(regdmn); + if (!ctl) + { + WMA_LOGI("%s:DFS-Invalid CTL\n",__func__); + } + if (ctl == FCC) + { + WMA_LOGI("%s:DFS- CTL = FCC\n",__func__); + wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN; + } + else if (ctl == ETSI) + { + WMA_LOGI("%s:DFS- CTL = ETSI\n",__func__); + wma->dfs_ic->current_dfs_regdomain = DFS_ETSI_DOMAIN; + } + else if (ctl == MKK) + { + WMA_LOGI("%s:DFS- CTL = MKK\n",__func__); + wma->dfs_ic->current_dfs_regdomain = DFS_MKK4_DOMAIN; + } + WMA_LOGI("%s: ****** Current Reg Domain: %d *******\n", __func__, + wma->dfs_ic->current_dfs_regdomain); +} + +/* + * Indicate Radar to SAP/HDD + */ +int +wma_dfs_indicate_radar(struct ieee80211com *ic, + struct ieee80211_channel *ichan) +{ + tp_wma_handle wma; + void *hdd_ctx; + struct wma_dfs_radar_indication *radar_event; + struct hdd_dfs_radar_ind hdd_radar_event; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + wma = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, vos_context); + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD,wma->vos_context); + + if (wma == NULL) + { + WMA_LOGE("%s:DFS- Invalid wma\n",__func__); + return (0); + } + if (wma->dfs_ic != ic) + { + WMA_LOGE("%s:DFS- Invalid WMA handle\n",__func__); + return (0); + } + radar_event = (struct wma_dfs_radar_indication *) + OS_MALLOC(NULL, + sizeof(struct wma_dfs_radar_indication), + GFP_ATOMIC); + if (radar_event == NULL) + { + WMA_LOGE("%s:DFS- Invalid radar_event\n",__func__); + return (0); + } + + /* + * Do not post multiple Radar events on the same channel. + */ + if ( ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan) ) + { + wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee; + /* Indicate the radar event to HDD to stop the netif Tx queues*/ + hdd_radar_event.ieee_chan_number = ichan->ic_ieee; + hdd_radar_event.chan_freq = ichan->ic_freq; + hdd_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND; + wma->dfs_radar_indication_cb(hdd_ctx,&hdd_radar_event); + WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD\n",__func__); + + /* + * Indicate to the radar event to SAP to + * select a new channel and set CSA IE + */ + radar_event->vdev_id = ic->vdev_id; + radar_event->ieee_chan_number = ichan->ic_ieee; + radar_event->chan_freq = ichan->ic_freq; + radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND; + radar_event->use_nol = ic->ic_dfs_usenol(ic); + wma_send_msg(wma, WDA_DFS_RADAR_IND, (void *)radar_event, 0); + WMA_LOGE("%s:DFS- WDA_DFS_RADAR_IND Message Posted\n",__func__); + } + return 1; +} + +static eHalStatus wma_set_smps_params(tp_wma_handle wma, tANI_U8 vdev_id, int value) +{ + int ret = eHAL_STATUS_SUCCESS; + wmi_sta_smps_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_sta_smps_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_smps_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_smps_param_cmd_fixed_param)); + + cmd->vdev_id = vdev_id; + cmd->value = value & WMA_SMPS_MASK_LOWER_16BITS; + cmd->param = (value >> WMA_SMPS_PARAM_VALUE_S) & WMA_SMPS_MASK_UPPER_3BITS; + + WMA_LOGD("Setting vdev %d value = %x param %x \n", vdev_id, cmd->value, cmd->param); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_STA_SMPS_PARAM_CMDID); + if (ret < 0) { + WMA_LOGE("Failed to send set Mimo PS ret = %d", ret); + wmi_buf_free(buf); + } + + return ret; +} + +VOS_STATUS WMA_GetWcnssSoftwareVersion(v_PVOID_t pvosGCtx, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize) +{ + + tp_wma_handle wma_handle; + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, pvosGCtx); + + snprintf(pVersion, versionBufferSize, "%x", (unsigned int)wma_handle->target_fw_version); + return VOS_STATUS_SUCCESS; +} diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 3644b87fbbe8..33560c9ebcc3 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -67,6 +67,7 @@ #include "sirMacProtDef.h" #include "wlan_qct_wda.h" #include "ol_txrx_types.h" +#include "wlan_qct_wda.h" #include <linux/workqueue.h> /* Platform specific configuration for max. no. of fragments */ @@ -134,12 +135,30 @@ #define WMA_HW_DEF_SCAN_MAX_DURATION 30000 /* 30 secs */ /* Max offchannel duration */ -#define WMA_SCAN_AP_PRESENT_MAX_OFFCHANNEL_NUM 5 -#define WMA_SCAN_MAX_OFFCHANNEL_NUM_ACTIVE 10 -#define WMA_SCAN_MAX_OFFCHANNEL_NUM_PASSIVE 4 +#define WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS 5 -#define WMA_INVALID_KEY_IDX 0xff +/* Roaming default values + * All time and period values are in milliseconds. + * All rssi values are in dB except for WMA_NOISE_FLOOR_DBM_DEFAULT. + */ + +#define WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME (3) +#define WMA_NOISE_FLOOR_DBM_DEFAULT (-96) +#define WMA_ROAM_RSSI_DIFF_DEFAULT (5) +#define WMA_ROAM_DWELL_TIME_ACTIVE_DEFAULT (100) +#define WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT (110) +#define WMA_ROAM_MIN_REST_TIME_DEFAULT (50) +#define WMA_ROAM_MAX_REST_TIME_DEFAULT (500) +#define WMA_ROAM_LOW_RSSI_TRIGGER_DEFAULT (20) +#define WMA_ROAM_LOW_RSSI_TRIGGER_VERYLOW (10) +#define WMA_ROAM_RSSI_THRESH_DIFF_DEFAULT (30) +#define WMA_ROAM_RSSI_CHANGE_RESCAN_DEFAULT (5) +#define WMA_ROAM_BEACON_WEIGHT_DEFAULT (14) +#define WMA_ROAM_OPP_SCAN_PERIOD_DEFAULT (120000) +#define WMA_ROAM_OPP_SCAN_AGING_PERIOD_DEFAULT (WMA_ROAM_OPP_SCAN_PERIOD_DEFAULT * 5) +#define WMA_INVALID_KEY_IDX 0xff +#define WMA_DFS_RADAR_FOUND 1 typedef struct { HTC_ENDPOINT_ID endpoint_id; }t_cfg_nv_param; @@ -266,6 +285,13 @@ struct pps { v_BOOL_t rssi_chk; }; +struct qpower_params { + u_int32_t max_ps_poll_cnt; + u_int32_t max_tx_before_wake; + u_int32_t spec_ps_poll_wake_interval; + u_int32_t max_spec_nodata_ps_poll; +}; + typedef struct { u_int32_t ani_enable; u_int32_t ani_poll_len; @@ -278,6 +304,8 @@ typedef struct { u_int32_t txpow2g; u_int32_t txpow5g; u_int32_t pwrgating; + u_int32_t burst_enable; + u_int32_t burst_dur; } pdev_cli_config_t; typedef struct { @@ -292,6 +320,7 @@ typedef struct { u_int32_t ampdu; u_int32_t amsdu; struct pps pps_params; + struct qpower_params qpower_params; } vdev_cli_config_t; #define WMA_WOW_PTRN_MASK_VALID 0xFF @@ -325,6 +354,17 @@ struct wma_wow { v_BOOL_t bmiss_enable; v_BOOL_t gtk_err_enable; }; +#ifdef WLAN_FEATURE_11W +#define CMAC_IPN_LEN 6 +typedef struct { + u_int16_t key_length; + u_int8_t key[CSR_AES_KEY_LEN]; + u_int8_t ipn[CMAC_IPN_LEN]; +} wma_igtk_key_t; +#endif + +#define WMA_BSS_STATUS_STARTED 0x1 +#define WMA_BSS_STATUS_STOPPED 0x2 struct wma_txrx_node { u_int8_t addr[ETH_ALEN]; @@ -354,6 +394,17 @@ struct wma_txrx_node { v_BOOL_t vdev_up; u_int64_t tsfadjust; void *addBssStaContext; + tANI_U8 aid; + /* Robust Management Frame (RMF) enabled/disabled */ + tANI_U8 rmfEnabled; +#ifdef WLAN_FEATURE_11W + wma_igtk_key_t key; +#endif /* WLAN_FEATURE_11W */ + u_int32_t uapsd_cached_val; + tAniGetPEStatsRsp *stats_rsp; + tANI_U8 fw_stats_set; + void *del_staself_req; + tANI_U8 bss_status; }; #if defined(QCA_WIFI_FTM) && !defined(QCA_WIFI_ISOC) @@ -430,6 +481,8 @@ typedef struct { struct wma_mem_chunk mem_chunks[MAX_MEM_CHUNKS]; #endif wda_tgt_cfg_cb tgt_cfg_update_cb; + /*Callback to indicate radar to HDD*/ + wda_dfs_radar_indication_cb dfs_radar_indication_cb; HAL_REG_CAPABILITIES reg_cap; u_int32_t scan_id; struct wma_txrx_node *interfaces; @@ -461,6 +514,7 @@ typedef struct { v_BOOL_t ptrn_match_enable_all_vdev; void* pGetRssiReq; u_int32_t roam_offload_vdev_id; + v_BOOL_t roam_offload_enabled; /* Here ol_ini_info is used to store ini * status of arp offload, ns offload @@ -471,6 +525,14 @@ typedef struct { u_int8_t ol_ini_info; u_int8_t ibss_started; tSetBssKeyParams ibsskey_info; + + /*DFS umac interface information*/ + struct ieee80211com *dfs_ic; +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_t pno_wake_lock; +#endif + vos_wake_lock_t wow_wake_lock; + }t_wma_handle, *tp_wma_handle; struct wma_target_cap { @@ -990,6 +1052,15 @@ VOS_STATUS wma_update_vdev_tbl(tp_wma_handle wma_handle, u_int8_t vdev_id, ol_txrx_vdev_handle tx_rx_vdev_handle, u_int8_t *mac, u_int32_t vdev_type, bool add_del); +#ifndef QCA_WIFI_ISOC +int32_t regdmn_get_regdmn_for_country(u_int8_t *alpha2); +void regdmn_get_ctl_info(struct regulatory *reg, u_int32_t modesAvail, + u_int32_t modeSelect); + +/*get the ctl from regdomain*/ +u_int8_t regdmn_get_ctl_for_regdmn(u_int32_t reg_dmn); +#endif + #define WMA_FW_PHY_STATS 0x1 #define WMA_FW_RX_REORDER_STATS 0x2 #define WMA_FW_RX_RC_STATS 0x3 @@ -1012,6 +1083,7 @@ struct wma_tx_ack_work_ctx { #define WMA_TARGET_REQ_TYPE_VDEV_START 0x1 #define WMA_TARGET_REQ_TYPE_VDEV_STOP 0x2 +#define WMA_TARGET_REQ_TYPE_VDEV_DEL 0x3 struct wma_target_req { vos_timer_t event_timeout; @@ -1100,6 +1172,8 @@ VOS_STATUS wma_send_snr_request(tp_wma_handle wma_handle, void *pGetRssiReq); /* Default rssi threshold defined in CFG80211 */ #define WMA_RSSI_THOLD_DEFAULT -300 +#define WMA_PNO_WAKE_LOCK_TIMEOUT (30 * 1000) /* in msec */ + #endif /* U-APSD maximum service period of peer station */ @@ -1229,6 +1303,7 @@ typedef enum { #define WMA_DEFAULT_QPOWER_MAX_PSPOLL_BEFORE_WAKE 1 #define WMA_DEFAULT_QPOWER_TX_WAKE_THRESHOLD 2 +#define WMA_DEFAULT_SIFS_BURST_DURATION 8160 #define WMA_VHT_PPS_PAID_MATCH 1 #define WMA_VHT_PPS_GID_MATCH 2 @@ -1260,4 +1335,47 @@ typedef struct { #endif /* FEATURE_WLAN_TDLS */ +/* + * Structure to indicate RADAR + */ + +struct wma_dfs_radar_indication { + /* unique id identifying the VDEV */ + A_UINT32 vdev_id; + /*Channel number on which the RADAR is present */ + u_int8_t ieee_chan_number; + /* Channel Frequency*/ + A_UINT32 chan_freq; + /* Flag to Indicate RADAR presence on the + * current operating channel + */ + u_int32_t dfs_radar_status; + /* Flag to indicate use NOL */ + int use_nol; +}; + +/* + * WMA-DFS Hooks + */ +int ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info); +u_int64_t ol_if_get_tsf64(struct ieee80211com *ic); +int ol_if_dfs_disable(struct ieee80211com *ic); +struct ieee80211_channel * ieee80211_find_channel(struct ieee80211com *ic, + int freq, u_int32_t flags); +int ol_if_dfs_enable(struct ieee80211com *ic, int *is_fastclk, void *pe); +u_int32_t ieee80211_ieee2mhz(u_int32_t chan, u_int32_t flags); +int ol_if_dfs_get_ext_busy(struct ieee80211com *ic); +int ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, + u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt); +u_int16_t ol_if_dfs_usenol(struct ieee80211com *ic); +void ieee80211_mark_dfs(struct ieee80211com *ic, + struct ieee80211_channel *ichan); +int wma_dfs_indicate_radar(struct ieee80211com *ic, + struct ieee80211_channel *ichan); +u_int16_t dfs_usenol(struct ieee80211com *ic); + +#define WMA_SMPS_MASK_LOWER_16BITS 0xFF +#define WMA_SMPS_MASK_UPPER_3BITS 0x7 +#define WMA_SMPS_PARAM_VALUE_S 29 + #endif diff --git a/CORE/SERVICES/WMA/wma_dfs_interface.c b/CORE/SERVICES/WMA/wma_dfs_interface.c new file mode 100644 index 000000000000..5fb437a77394 --- /dev/null +++ b/CORE/SERVICES/WMA/wma_dfs_interface.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + wma_dfs_interface.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + + +#include "wma.h" +#include "ath_dfs_structs.h" +#include "wma_dfs_interface.h" + +#ifndef ATH_SUPPORT_DFS +#define ATH_SUPPORT_DFS 1 +#endif + +int +ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info) +{ + struct ath_dfs_caps *pCap = (struct ath_dfs_caps *) ptr; + + adf_os_print("%s: called; ptr=%p, radar_info=%p\n", + __func__, ptr, radar_info); + + pCap->ath_chip_is_bb_tlv = 1; + pCap->ath_dfs_combined_rssi_ok = 0; + pCap->ath_dfs_ext_chan_ok = 0; + pCap->ath_dfs_use_enhancement = 0; + pCap->ath_strong_signal_diversiry = 0; + pCap->ath_fastdiv_val = 0; + + return(0); +} + +/* + * Place Holder API + * We get the tsf from Firmware. + */ +u_int64_t +ol_if_get_tsf64(struct ieee80211com *ic) +{ + return (0); +} + +/* + * ic_dfs_disable is just a place holder + * function since firmware takes care of + * disabling the dfs phyerrors disabling. + */ +int +ol_if_dfs_disable(struct ieee80211com *ic) +{ + return (0); +} + + +/* + * Locate a channel given a frequency+flags. We cache + * the previous lookup to optimize swithing between two + * channels--as happens with dynamic turbo. + * This verifies that found channels have not been excluded because of 11d. + */ +struct ieee80211_channel * +ieee80211_find_channel(struct ieee80211com *ic, int freq, u_int32_t flags) +{ + struct ieee80211_channel *c; + int i; + + flags &= IEEE80211_CHAN_ALLTURBO; + /* brute force search */ + for (i = 0; i < ic->ic_nchans; i++) + { + c = &ic->ic_channels[i]; + + if ((! IEEE80211_IS_CHAN_11D_EXCLUDED(c)) && + (c->ic_freq == freq) && + ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)) + { + return c; + } + } + + return NULL; +} + + +/* + * ic_dfs_enable - enable DFS + * For offload solutions, radar PHY errors will be enabled by the target + * firmware when DFS is requested for the current channel. + */ +int ol_if_dfs_enable(struct ieee80211com *ic, int *is_fastclk, void *pe) +{ + /* + * For peregrine, treat fastclk as the "oversampling" mode. + * It's on by default. This may change at some point, so + * we should really query the firmware to find out what + * the current configuration is. + */ + (* is_fastclk) = 1; + + return (0); +} + +/* + * Convert IEEE channel number to MHz frequency. + */ +u_int32_t +ieee80211_ieee2mhz(u_int32_t chan, u_int32_t flags) +{ + if (flags & IEEE80211_CHAN_2GHZ) + { + /* 2GHz band */ + if (chan == 14) + return 2484; + if (chan < 14) + return 2407 + chan*5; + else + return 2512 + ((chan-15)*20); + } + else if (flags & IEEE80211_CHAN_5GHZ) + { + /* 5Ghz band */ + return 5000 + (chan*5); + } + else + { + /* either, guess */ + if (chan == 14) + return 2484; + if (chan < 14) /* 0-13 */ + return 2407 + chan*5; + if (chan < 27) /* 15-26 */ + return 2512 + ((chan-15)*20); + return 5000 + (chan*5); + } +} + +/* + * Place holder function ic_get_ext_busy + */ +int +ol_if_dfs_get_ext_busy(struct ieee80211com *ic) +{ + return (0); +} + +/* + * ic_get_mib_cycle_counts_pct + */ +int +ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, + u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt) +{ + return (0); +} + +u_int16_t +ol_if_dfs_usenol(struct ieee80211com *ic) +{ +#if ATH_SUPPORT_DFS + return(dfs_usenol(ic)); +#else + return (0); +#endif /* ATH_SUPPORT_DFS */ + return 0; +} + +/* + * Function to indicate Radar on the current + * SAP operating channel.This indication will + * be posted to SAP to select a new channel + * randomly and issue a vdev restart to + * operate on the new channel. + */ +void +ieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan) +{ + int status; + status = wma_dfs_indicate_radar(ic, ichan); +} diff --git a/CORE/SERVICES/WMA/wma_stub.h b/CORE/SERVICES/WMA/wma_stub.h index bf911303e6f1..a0a2393ab8a8 100644 --- a/CORE/SERVICES/WMA/wma_stub.h +++ b/CORE/SERVICES/WMA/wma_stub.h @@ -62,12 +62,6 @@ static inline void WMA_disableCapablityFeature(tANI_U8 feature_index) { return; } -static inline VOS_STATUS WMA_GetWcnssSoftwareVersion(v_PVOID_t pvosGCtx, - tANI_U8 *pVersion, - tANI_U32 versionBufferSize){ - return VOS_STATUS_SUCCESS; -} - static inline VOS_STATUS WMA_HALDumpCmdReq(tpAniSirGlobal pMac, tANI_U32 cmd, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, tANI_U8 *pBuffer) { diff --git a/CORE/SERVICES/WMI/wmi_tlv_platform.c b/CORE/SERVICES/WMI/wmi_tlv_platform.c index 0f105096a10c..a859e214215b 100644 --- a/CORE/SERVICES/WMI/wmi_tlv_platform.c +++ b/CORE/SERVICES/WMI/wmi_tlv_platform.c @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013 Qualcomm Atheros,Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ /* * LMAC offload interface functions for WMI TLV Interface diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h index 3a4c852d004d..411391e22849 100644 --- a/CORE/SME/inc/csrApi.h +++ b/CORE/SME/inc/csrApi.h @@ -466,6 +466,13 @@ typedef enum eCSR_ROAM_CCX_ADJ_AP_REPORT_IND, eCSR_ROAM_CCX_BCN_REPORT_IND, #endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */ + + // Radar indication from lower layers + eCSR_ROAM_DFS_RADAR_IND, + eCSR_ROAM_SET_CHANNEL_RSP, + + // Channel sw update notification + eCSR_ROAM_DFS_CHAN_SW_NOTIFY }eRoamCmdStatus; @@ -559,6 +566,12 @@ typedef enum eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED, #endif #endif + + eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND, + eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS, + eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE, + eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS, + eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE, }eCsrRoamResult; @@ -889,6 +902,8 @@ typedef struct tagCsrRoamProfile #endif tVOS_CON_MODE csrPersona; + tANI_U8 disableDFSChSwitch; + }tCsrRoamProfile; @@ -1203,6 +1218,8 @@ typedef struct tagCsrRoamInfo tANI_U8* assocReqPtr; tANI_S8 rxRssi; + tSirSmeDfsEventInd dfs_event; + tSirChanChangeResponse *channelChangeRespEvent; }tCsrRoamInfo; diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h index 53d3d50cf91d..4c0cf4cbe865 100644 --- a/CORE/SME/inc/csrInternal.h +++ b/CORE/SME/inc/csrInternal.h @@ -63,6 +63,7 @@ #define CSR_SCAN_RETURN_AFTER_EITHER_BAND_11d_FOUND ( CSR_SCAN_RETURN_AFTER_5_BAND_11d_FOUND | CSR_SCAN_RETURN_AFTER_24_BAND_11d_FOUND ) #define CSR_NUM_RSSI_CAT 15 #define CSR_MAX_STATISTICS_REQ 10 +#define CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME 3 //Support for multiple session #define CSR_SESSION_ID_INVALID 0xFF // session ID invalid @@ -838,6 +839,7 @@ typedef struct tagCsrPeStatsReqInfo tpAniSirGlobal pMac; /* To remember if the peStats timer is stopped successfully or not */ tANI_BOOLEAN timerStopFailed; + tANI_U8 sessionId; }tCsrPeStatsReqInfo; @@ -854,6 +856,7 @@ typedef struct tagCsrStatsClientReqInfo vos_timer_t timer; tANI_BOOLEAN timerExpired; tpAniSirGlobal pMac; // TODO: Confirm this change BTAMP + tANI_U8 sessionId; }tCsrStatsClientReqInfo; typedef struct tagCsrTlStatsReqInfo @@ -1212,14 +1215,15 @@ eHalStatus csrRoamRegisterLinkQualityIndCallback(tpAniSirGlobal pMac, \param cache - If requester is happy with cached stats \param staId - The station ID for which the stats is requested for \param pContext - user context to be passed back along with the callback - + \param sessionId - sme session Id. \return eHalStatus ---------------------------------------------------------------------------*/ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requesterId, tANI_U32 statsMask, tCsrStatsCallback callback, tANI_U32 periodicity, tANI_BOOLEAN cache, - tANI_U8 staId, void *pContext); + tANI_U8 staId, void *pContext, + tANI_U8 sessionId); /* --------------------------------------------------------------------------- \fn csrGetTLSTAState @@ -1422,4 +1426,16 @@ eHalStatus csrHandoffRequest(tpAniSirGlobal pMac, tCsrHandoffRequest *pHandoffIn tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId); #endif + +/* Post Channel Change Indication */ +eHalStatus csrRoamChannelChangeReq( tpAniSirGlobal pMac, + tANI_U32 sessionId, tANI_U8 targetChannel); + +/* Post Beacon Tx Start Indication */ +eHalStatus csrRoamStartBeaconReq( tpAniSirGlobal pMac, + tANI_U32 sessionId, tANI_U8 dfsCacWaitStatus); + +eHalStatus +csrRoamSendChanSwIERequest(tpAniSirGlobal pMac, tANI_U8 sessionId, + tANI_U8 targetChannel, tANI_U8 csaIeReqd); #endif diff --git a/CORE/SME/inc/pmcApi.h b/CORE/SME/inc/pmcApi.h index 79db57192625..0a7be56c2561 100644 --- a/CORE/SME/inc/pmcApi.h +++ b/CORE/SME/inc/pmcApi.h @@ -627,5 +627,8 @@ eHalStatus pmcOffloadSetTdlsProhibitBmpsStatus(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t val); #endif + +tANI_BOOLEAN pmcOffloadIsPowerSaveEnabled (tHalHandle hHal, tANI_U32 sessionId, + tPmcPowerSavingMode psMode); #endif diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index 548834fa4287..93d62b0c047b 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -849,13 +849,14 @@ eHalStatus sme_GetConfigParam(tHalHandle hHal, tSmeConfigParams *pParam); \param cache - If requester is happy with cached stats \param staId - The station ID for which the stats is requested for \param pContext - user context to be passed back along with the callback + \param sessionId - sme session interface \return eHalStatus ---------------------------------------------------------------------------*/ eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId, tANI_U32 statsMask, tCsrStatsCallback callback, tANI_U32 periodicity, tANI_BOOLEAN cache, - tANI_U8 staId, void *pContext); + tANI_U8 staId, void *pContext, tANI_U8 sessionId); /* --------------------------------------------------------------------------- \fn smeGetTLSTAState @@ -1099,11 +1100,13 @@ extern eHalStatus sme_QueryPowerState ( \brief Checks if the device is able to enter a particular power save mode This does not imply that the device is in a particular PS mode \param hHal - The handle returned by macOpen. + \param sessionId - sme sessionid \param psMode - the power saving mode \return eHalStatus ---------------------------------------------------------------------------*/ -extern tANI_BOOLEAN sme_IsPowerSaveEnabled( +extern tANI_BOOLEAN sme_IsPowerSaveEnabled ( tHalHandle hHal, + tANI_U32 sessionId, tPmcPowerSavingMode psMode); /* --------------------------------------------------------------------------- @@ -2854,18 +2857,6 @@ eHalStatus sme_SetCcxRoamScanChannelList(tHalHandle hHal, #endif /*-------------------------------------------------------------------------- - \brief csrUpdateBgScanConfigIniChannelList() - Update bgscan roam cache - This is a synchronuous call - \param hHal - The handle returned by macOpen. - \return eHAL_STATUS_SUCCESS - SME update config successful. - Other status means SME is failed to update - \sa - --------------------------------------------------------------------------*/ -eHalStatus sme_UpdateBgScanConfigIniChannelList(tHalHandle hHal, - eCsrBand eBand); - - -/*-------------------------------------------------------------------------- \brief sme_getRoamScanChannelList() - get roam scan channel list This is a synchronuous call \param hHal - The handle returned by macOpen. @@ -3288,4 +3279,21 @@ eHalStatus sme_AddChAvoidCallback void (*pCallbackfn)(void *hdd_context, void *indi_param) ); #endif /* FEATURE_WLAN_CH_AVOID */ + +eHalStatus sme_RoamChannelChangeReq( tHalHandle hHal, + tANI_U8 sessionId, tANI_U8 targetChannel); + +eHalStatus sme_RoamStartBeaconReq( tHalHandle hHal, + tANI_U8 sessionId, tANI_U8 dfsCacWaitStatus); +/* ------------------------------------------------------------------------- + \fn sme_RoamCsaIeRequest + \brief API to request CSA IE transmission from PE + \param hHal - The handle returned by macOpen + \param sessionId - session ID + \param pDfsCsaReq - CSA IE request + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamCsaIeRequest(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 targetChannel, tANI_U8 csaIeReqd); + #endif //#if !defined( __SME_API_H ) diff --git a/CORE/SME/inc/sme_Trace.h b/CORE/SME/inc/sme_Trace.h index 35cdf8ccef8b..c370b5fc9dfd 100644 --- a/CORE/SME/inc/sme_Trace.h +++ b/CORE/SME/inc/sme_Trace.h @@ -31,12 +31,6 @@ \author Kiran Kumar Reddy CH L V - Copyright (c) 2013 Qualcomm Atheros, Inc. - - All Rights Reserved. - - Qualcomm Atheros Confidential and Proprietary. - ========================================================================*/ #ifndef __SME_TRACE_H__ diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c index 776b9bff9ac2..34c33b88a57b 100644 --- a/CORE/SME/src/csr/csrApiRoam.c +++ b/CORE/SME/src/csr/csrApiRoam.c @@ -218,7 +218,8 @@ VOS_STATUS csrRoamVccTriggerRssiIndCallback(tHalHandle hHal, void * context); static void csrRoamLinkDown(tpAniSirGlobal pMac, tANI_U32 sessionId); void csrRoamVccTrigger(tpAniSirGlobal pMac); -eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U8 staId); +eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, + tANI_U8 staId, tANI_U8 sessionId); /* pStaEntry is no longer invalid upon the return of this function. */ @@ -230,7 +231,10 @@ tCsrStatsClientReqInfo * csrRoamInsertEntryIntoList( tpAniSirGlobal pMac, tCsrStatsClientReqInfo *pStaEntry); void csrRoamStatsClientTimerHandler(void *pv); tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask, - tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId); + tANI_U32 periodicity, + tANI_BOOLEAN *pFound, + tANI_U8 staId, + tANI_U8 sessionId); void csrRoamReportStatistics(tpAniSirGlobal pMac, tANI_U32 statsMask, tCsrStatsCallback callback, tANI_U8 staId, void *pContext); void csrRoamSaveStatsFromTl(tpAniSirGlobal pMac, WLANTL_TRANSFER_STA_TYPE *pTlStats); @@ -1399,7 +1403,8 @@ eHalStatus csrSetBand(tHalHandle hHal, eCsrBand eBand) pMac->roam.configParam.bandCapability = eBand; csrScanGetSupportedChannels( pMac ); #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - csrUpdateBgScanConfigIniChannelList( pMac, eBand ); + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) + csrUpdateBgScanConfigIniChannelList( pMac, eBand ); #endif status = csrInitGetChannels( pMac ); if (eHAL_STATUS_SUCCESS == status) @@ -8530,6 +8535,12 @@ eHalStatus csrRoamProcessSetKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); WLAN_VOS_DIAG_EVENT_DEF(setKeyEvent, vos_event_wlan_security_payload_type); + + if(NULL == pSession){ + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + if(eSIR_ED_NONE != edType) { vos_mem_set(&setKeyEvent, @@ -8612,6 +8623,12 @@ eHalStatus csrRoamProcessRemoveKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pComman #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); WLAN_VOS_DIAG_EVENT_DEF(removeKeyEvent, vos_event_wlan_security_payload_type); + + if(NULL == pSession){ + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + vos_mem_set(&removeKeyEvent, sizeof(vos_event_wlan_security_payload_type),0); removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_REQ; @@ -9826,11 +9843,16 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) } #endif //FEATURE_WLAN_DIAG_SUPPORT_CSR smsLog(pMac, LOGW, "CSR: Peer departed notification from LIM"); - roamInfo.staId = (tANI_U8)pIbssPeerInd->staId; - roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig; - roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig; - vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, - sizeof(tCsrBssid)); + if(pIbssPeerInd) + { + roamInfo.staId = (tANI_U8)pIbssPeerInd->staId; + roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig; + roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig; + vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, + sizeof(tCsrBssid)); + } + else + smsLog(pMac, LOGE, "CSR: departed peer info is NULL"); csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED); } @@ -11277,9 +11299,9 @@ tANI_U8 csrRoamGetIbssStartChannelNumber50( tpAniSirGlobal pMac ) { for ( idxValidChannels = 0; idxValidChannels < len ; idxValidChannels++ ) { - if ( CSR_IS_CHANNEL_5GHZ(pMac->roam.validChannelList[ idx ]) ) // the max channel# in 11g is 14 + if ( CSR_IS_CHANNEL_5GHZ(pMac->roam.validChannelList[ idxValidChannels ]) ) // the max channel# in 11g is 14 { - channel = csrStartIbssChannels50[ idx ]; + channel = csrStartIbssChannels50[ idxValidChannels ]; break; } } @@ -14595,7 +14617,8 @@ void csrRoamPeStatsTimerHandler(void *pv) if(!pPeStatsReqListEntry->rspPending) { status = csrSendMBStatsReqMsg(pMac, pPeStatsReqListEntry->statsMask & ~(1 << eCsrGlobalClassDStats), - pPeStatsReqListEntry->staId); + pPeStatsReqListEntry->staId, + pPeStatsReqListEntry->sessionId); if(!HAL_STATUS_SUCCESS(status)) { smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:failed to send down stats req to PE")); @@ -14663,7 +14686,8 @@ void csrRoamStatsClientTimerHandler(void *pv) -eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U8 staId) +eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, + tANI_U8 staId, tANI_U8 sessionId) { tAniGetPEStatsReq *pMsg; eHalStatus status = eHAL_STATUS_SUCCESS; @@ -14678,6 +14702,7 @@ eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U pMsg->msgLen = (tANI_U16)sizeof(tAniGetPEStatsReq); pMsg->staId = staId; pMsg->statsMask = statsMask; + pMsg->sessionId = sessionId; status = palSendMBMessage(pMac->hHdd, pMsg ); if(!HAL_STATUS_SUCCESS(status)) { @@ -15270,7 +15295,8 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste tANI_U32 statsMask, tCsrStatsCallback callback, tANI_U32 periodicity, tANI_BOOLEAN cache, - tANI_U8 staId, void *pContext) + tANI_U8 staId, void *pContext, + tANI_U8 sessionId) { tCsrStatsClientReqInfo staEntry; tCsrStatsClientReqInfo *pStaEntry = NULL; @@ -15365,6 +15391,7 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste staEntry.staId = staId; staEntry.pMac = pMac; staEntry.timerExpired = FALSE; + staEntry.sessionId = sessionId; //if periodic report requested with non cached result from PE/TL @@ -15377,7 +15404,8 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste //check if same request made already & waiting for rsp pPeStaEntry = csrRoamCheckPeStatsReqList(pMac, statsMask & ~(1 << eCsrGlobalClassDStats), - periodicity, &found, staId); + periodicity, &found, staId, + sessionId); if(!pPeStaEntry) { //bail out, maxed out on number of req for PE @@ -15462,7 +15490,10 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste if(statsMask & ~(1 << eCsrGlobalClassDStats)) { //send down a req - status = csrSendMBStatsReqMsg(pMac, statsMask & ~(1 << eCsrGlobalClassDStats), staId); + status = csrSendMBStatsReqMsg(pMac, + statsMask & ~(1 << eCsrGlobalClassDStats), + staId, + sessionId); if(!HAL_STATUS_SUCCESS(status)) { smsLog(pMac, LOGE, FL("csrGetStatistics:failed to send down stats req to PE")); @@ -15675,6 +15706,7 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reas eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrChannelInfo currChannelListInfo; tANI_U32 host_channels = 0; + eCsrBand eBand; tANI_U8 ChannelCacheStr[128] = {0}; currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; @@ -15772,27 +15804,47 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reas currChannelListInfo->numOfChannels == 0) { - /*Retreive the Channel Cache either from ini or from the Occupied Channels list. + /*Retrieve the Channel Cache either from ini or from the Occupied Channels list. * Give Preference to INI Channels.*/ if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) { ChannelList = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList; + /* The INI channels need to be filtered with respect to the current + * band that is supported. + */ + eBand = pMac->roam.configParam.bandCapability; + if ((eCSR_BAND_24 != eBand) && (eCSR_BAND_5G != eBand) && (eCSR_BAND_ALL != eBand)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Invalid band, No operation carried out (Band %d)", eBand); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } for (i=0; i<pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels ;i++) + { + if (((eCSR_BAND_24 == eBand) && CSR_IS_CHANNEL_24GHZ(*ChannelList)) || + ((eCSR_BAND_5G == eBand) && CSR_IS_CHANNEL_5GHZ(*ChannelList)) || + (eCSR_BAND_ALL == eBand)) { - if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) - { - pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; - } - ChannelList++; + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && + csrRoamIsChannelValid(pMac, *ChannelList) && + *ChannelList && (num_channels < SIR_ROAM_MAX_CHANNELS)) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; } - pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; - pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; } - else{ + else + { ChannelList = pMac->scan.occupiedChannels.channelList; for(i=0; i<pMac->scan.occupiedChannels.numChannels; i++) { - if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && + *ChannelList && (num_channels < SIR_ROAM_MAX_CHANNELS)) { pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; } @@ -15880,6 +15932,21 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reas pRequestBuf->HomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime; + /* Home Away Time should be at least equal to (MaxDwell time + (2*RFS)), + * where RFS is the RF Switching time. It is twice RFS to consider the + * time to go off channel and return to the home channel. */ + if (pRequestBuf->HomeAwayTime < (pRequestBuf->NeighborScanChannelMaxTime + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)" + " Hence enforcing home away time to disable (0)", + __func__, pRequestBuf->HomeAwayTime, + (pRequestBuf->NeighborScanChannelMaxTime + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME) + )); + pRequestBuf->HomeAwayTime = 0; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,"HomeAwayTime:%d",pRequestBuf->HomeAwayTime); + /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); @@ -15930,8 +15997,12 @@ eHalStatus csrRoamOffloadScanRspHdlr(tpAniSirGlobal pMac, tANI_U8 reason) } #endif -tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask, - tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId) +tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, + tANI_U32 statsMask, + tANI_U32 periodicity, + tANI_BOOLEAN *pFound, + tANI_U8 staId, + tANI_U8 sessionId) { tANI_BOOLEAN found = FALSE; eHalStatus status = eHAL_STATUS_SUCCESS; @@ -15968,6 +16039,7 @@ tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 s staEntry.staId = staId; staEntry.statsMask = statsMask; staEntry.timerRunning = FALSE; + staEntry.sessionId = sessionId; pTempStaEntry = csrRoamInsertEntryIntoPeStatsReqList(pMac, &pMac->roam.peStatsReqList, &staEntry); if(!pTempStaEntry) { @@ -15997,7 +16069,10 @@ tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 s if(!pTempStaEntry->rspPending && !pTempStaEntry->periodicity) { - status = csrSendMBStatsReqMsg(pMac, statsMask & ~(1 << eCsrGlobalClassDStats), staId); + status = csrSendMBStatsReqMsg(pMac, + statsMask & ~(1 << eCsrGlobalClassDStats), + staId, + sessionId); if(!HAL_STATUS_SUCCESS(status)) { smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:failed to send down stats req to PE")); @@ -17166,6 +17241,7 @@ VOS_STATUS csrSetCCKMIe(tpAniSirGlobal pMac, const tANI_U8 sessionId, pSession->suppCckmIeInfo.cckmIeLen = ccKmIeLen; return status; } + /* --------------------------------------------------------------------------- \fn csrRoamReadTSF \brief This function reads the TSF; and also add the time elapsed since @@ -17196,3 +17272,122 @@ VOS_STATUS csrRoamReadTSF(tpAniSirGlobal pMac, tANI_U8 *pTimestamp) return status; } #endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */ + +/* + * Post Channel Change Request to LIM + * This API is primarily used to post + * Channel Change Req for SAP + */ +eHalStatus +csrRoamChannelChangeReq( tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_U8 targetChannel) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirChanChangeRequest *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL + ( " Session does not exist for session id %d" ), sessionId); + return eHAL_STATUS_FAILURE; + } + + pMsg = vos_mem_malloc( sizeof(tSirChanChangeRequest) ); + if (!pMsg) + { + return ( eHAL_STATUS_FAILURE ); + } + + vos_mem_set((void *)pMsg, sizeof( tSirChanChangeRequest ), 0); + + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_CHANNEL_CHANGE_REQ); + pMsg->messageLen = sizeof(tSirChanChangeRequest); + pMsg->sessionId = pSession->sessionId; + pMsg->targetChannel = targetChannel; + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return ( status ); +} + +/* + * Post Beacon Tx Start request to LIM + * immediately after SAP CAC WAIT is + * completed without any RADAR indications. + */ +eHalStatus csrRoamStartBeaconReq( tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_U8 dfsCacWaitStatus) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirStartBeaconIndication *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL + ( " Session does not exist for session id %d" ), sessionId); + return eHAL_STATUS_FAILURE; + } + + pMsg = vos_mem_malloc(sizeof(tSirStartBeaconIndication)); + + if (!pMsg) + { + return eHAL_STATUS_FAILURE; + } + + vos_mem_set((void *)pMsg, sizeof( tSirStartBeaconIndication ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_START_BEACON_REQ); + pMsg->messageLen = sizeof(tSirStartBeaconIndication); + pMsg->sessionId = pSession->sessionId; + pMsg->beaconStartStatus = dfsCacWaitStatus; + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return ( status ); +} + +/*---------------------------------------------------------------------------- + \fn csrRoamSendChanSwIERequest + \brief This function sends request to transmit channel switch announcement + IE to lower layers + \param pMac - pMac global structure + \param sessionId - SME session id + \param pDfsCacInd - CAC indication data to PE/LIM + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus +csrRoamSendChanSwIERequest(tpAniSirGlobal pMac, tANI_U8 sessionId, + tANI_U8 targetChannel, tANI_U8 csaIeReqd) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirDfsCsaIeRequest *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL + ( " Session does not exist for session id %d" ), sessionId); + return eHAL_STATUS_FAILURE; + } + + pMsg = vos_mem_malloc(sizeof(tSirDfsCsaIeRequest)); + if (!pMsg) + { + return eHAL_STATUS_FAILURE; + } + + vos_mem_set((void *)pMsg, sizeof(tSirDfsCsaIeRequest), 0); + pMsg->msgType = + pal_cpu_to_be16((tANI_U16)eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ); + pMsg->msgLen = sizeof(tSirDfsCsaIeRequest); + + pMsg->sessionId = pSession->sessionId; + pMsg->targetChannel = targetChannel; + pMsg->csaIeRequired = csaIeReqd; + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return status; +} diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c index bff7305a1322..015e89870bbf 100644 --- a/CORE/SME/src/csr/csrApiScan.c +++ b/CORE/SME/src/csr/csrApiScan.c @@ -2203,7 +2203,7 @@ eHalStatus csrScanGetResult(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter, /* re-assign preference value based on modified rssi bucket */ pBssDesc->preferValue = csrGetBssPreferValue(pMac, (int)pBssDesc->Result.BssDescriptor.rssi); - smsLog(pMac, LOG2, FL("BSSID(%02X:%02X:%02X:%02X:%02X:%02X) Rssi(%d) Chnl(%d) PrefVal(%lu) SSID=%.*s"), + smsLog(pMac, LOG2, FL("BSSID(%02X:%02X:%02X:%02X:%02X:%02X) Rssi(%d) Chnl(%d) PrefVal(%u) SSID=%.*s"), pBssDesc->Result.BssDescriptor.bssId[0], pBssDesc->Result.BssDescriptor.bssId[1], pBssDesc->Result.BssDescriptor.bssId[2], diff --git a/CORE/SME/src/pmc/pmc.c b/CORE/SME/src/pmc/pmc.c index de1524dbecea..6fadfc62ba27 100644 --- a/CORE/SME/src/pmc/pmc.c +++ b/CORE/SME/src/pmc/pmc.c @@ -3317,7 +3317,6 @@ eHalStatus pmcOffloadEnterPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId { pmc->pmcState = UAPSD; pmc->uapsdStatus = PMC_UAPSD_ENABLED; - pmc->uapsdSessionRequired = FALSE; /* Call registered uapsd cbs */ pmcOffloadDoStartUapsdCallbacks(pMac, sessionId, eHAL_STATUS_SUCCESS); } @@ -3346,7 +3345,7 @@ eHalStatus pmcOffloadEnterPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId eHAL_STATUS_FAILURE); } } - else if(pmc->uapsdSessionRequired) + else if((UAPSD != pmc->pmcState) && pmc->uapsdSessionRequired) { if(eHAL_STATUS_FAILURE == pmcOffloadQueueStartUapsdRequest(pMac, sessionId)) @@ -3387,7 +3386,6 @@ eHalStatus pmcOffloadExitPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId) if(PMC_UAPSD_DISABLE_PENDING == pmc->uapsdStatus) { - pmc->uapsdSessionRequired = FALSE; pmc->uapsdStatus = PMC_UAPSD_DISABLED; } @@ -3458,7 +3456,7 @@ void pmcOffloadExitBmpsIndHandler(tpAniSirGlobal pMac, tSirSmeRsp *pMsg) else { smsLog(pMac, LOG1, - FL("Exit BMPS indication on session %lu, reason %d"), + FL("Exit BMPS indication on session %u, reason %d"), pExitBmpsInd->smeSessionId, pExitBmpsInd->exitBmpsReason); pmcOffloadQueueRequestFullPower(pMac, pExitBmpsInd->smeSessionId, pExitBmpsInd->exitBmpsReason); diff --git a/CORE/SME/src/pmc/pmcApi.c b/CORE/SME/src/pmc/pmcApi.c index 5d9691e849e8..eb7bc507ac00 100644 --- a/CORE/SME/src/pmc/pmcApi.c +++ b/CORE/SME/src/pmc/pmcApi.c @@ -4260,3 +4260,48 @@ eHalStatus pmcOffloadSetTdlsProhibitBmpsStatus(tHalHandle hHal, return eHAL_STATUS_SUCCESS; } #endif + +/****************************************************************************** +* +* Name: pmcOffloadIsPowerSaveEnabled +* +* Description: +* Checks if the device is able to enter one of the power save modes. +* "Able to enter" means the power save mode is enabled for the device +* and the host is using the correct power source for entry into the +* power save mode. This routine does not indicate whether the device +* is actually in the power save mode at a particular point in time. +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode +* +* Returns: +* TRUE if device is able to enter the power save mode, FALSE otherwise +* +******************************************************************************/ +tANI_BOOLEAN pmcOffloadIsPowerSaveEnabled (tHalHandle hHal, tANI_U32 sessionId, + tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + pmcLog(pMac, LOG2, FL("Entering pmcIsPowerSaveEnabled, power save mode %d"), + psMode); + + /* Check ability to enter based on the specified power saving mode. */ + switch (psMode) + { + case ePMC_BEACON_MODE_POWER_SAVE: + return pMac->pmcOffloadInfo.staPsEnabled; + + case ePMC_UAPSD_MODE_POWER_SAVE: + return pmc->UapsdEnabled; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + PMC_ABORT; + return FALSE; + } +} + diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index f701be8cde88..af6b33cdff84 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -114,6 +114,14 @@ eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm ); #endif +/* Message processor for events from DFS */ +eHalStatus dfsMsgProcessor(tpAniSirGlobal pMac, + v_U16_t msg_type,void *pMsgBuf); + +/* Channel Change Response Indication Handler */ +eHalStatus sme_ProcessChannelChangeResp(tpAniSirGlobal pMac, + v_U16_t msg_type,void *pMsgBuf); + //Internal SME APIs eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme) { @@ -1898,6 +1906,65 @@ eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, } #endif +/*------------------------------------------------------------------ + * + * Handle the DFS Radar Event and indicate it to the SAP + * + *------------------------------------------------------------------*/ +eHalStatus dfsMsgProcessor(tpAniSirGlobal pMac, v_U16_t msgType, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo roamInfo = {0}; + tSirSmeDfsEventInd *dfs_event; + tANI_U32 sessionId = 0; + eRoamCmdStatus roamStatus; + eCsrRoamResult roamResult; + + switch (msgType) + { + case eWNI_SME_DFS_RADAR_FOUND: + { + /* Radar found !! */ + dfs_event = (tSirSmeDfsEventInd *)pMsgBuf; + if (NULL == dfs_event) + { + smsLog(pMac, LOGE, + "%s: pMsg is NULL for eWNI_SME_DFS_RADAR_FOUND message", + __func__); + return eHAL_STATUS_FAILURE; + } + sessionId = dfs_event->sessionId; + roamInfo.dfs_event.sessionId = sessionId; + roamInfo.dfs_event.ieee_chan_number = dfs_event->ieee_chan_number; + roamInfo.dfs_event.chan_freq = dfs_event->chan_freq; + roamInfo.dfs_event.dfs_radar_status = dfs_event->dfs_radar_status; + roamInfo.dfs_event.use_nol = dfs_event->use_nol; + + roamStatus = eCSR_ROAM_DFS_RADAR_IND; + roamResult = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND; + break; + } + case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: + { + roamStatus = eCSR_ROAM_DFS_CHAN_SW_NOTIFY; + roamResult = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS; + break; + } + default: + { + smsLog(pMac, LOG1, "%s: Invalid DFS message = 0x%x", __func__, + msgType); + status = eHAL_STATUS_FAILURE; + return status; + } + } + + /* Indicate Radar Event to SAP */ + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + roamStatus, roamResult); + return status; +} + #if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD) /*------------------------------------------------------------------ * @@ -2417,6 +2484,28 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) break; #endif /* FEATURE_WLAN_CH_AVOID */ + case eWNI_SME_DFS_RADAR_FOUND: + case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: + { + status = dfsMsgProcessor(pMac, pMsg->type, pMsg->bodyptr); + vos_mem_free( pMsg->bodyptr ); + } + break; + + case eWNI_SME_CHANNEL_CHANGE_RSP: + if (pMsg->bodyptr) + { + status = sme_ProcessChannelChangeResp(pMac, + pMsg->type, pMsg->bodyptr); + vos_mem_free( pMsg->bodyptr ); + } + else + { + smsLog( pMac, LOGE, + "Empty rsp message for (eWNI_SME_CHANNEL_CHANGE_RSP)," + "nothing to process"); + } + break ; default: if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN ) @@ -4091,10 +4180,13 @@ eHalStatus sme_QueryPowerState ( \brief Checks if the device is able to enter a particular power save mode This does not imply that the device is in a particular PS mode \param hHal - The handle returned by macOpen. + \param sessionId - sme session id \param psMode - the power saving mode \return eHalStatus ---------------------------------------------------------------------------*/ -tANI_BOOLEAN sme_IsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode) +tANI_BOOLEAN sme_IsPowerSaveEnabled (tHalHandle hHal, + tANI_U32 sessionId, + tPmcPowerSavingMode psMode) { eHalStatus status = eHAL_STATUS_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); @@ -4105,7 +4197,10 @@ tANI_BOOLEAN sme_IsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode status = sme_AcquireGlobalLock( &pMac->sme ); if ( HAL_STATUS_SUCCESS( status ) ) { - result = pmcIsPowerSaveEnabled(hHal, psMode); + if(!pMac->psOffloadEnabled) + result = pmcIsPowerSaveEnabled(hHal, psMode); + else + result = pmcOffloadIsPowerSaveEnabled(hHal, sessionId, psMode); sme_ReleaseGlobalLock( &pMac->sme ); return result; } @@ -4786,13 +4881,15 @@ eHalStatus sme_GetTsmStats(tHalHandle hHal, \param cache - If requester is happy with cached stats \param staId - The station ID for which the stats is requested for \param pContext - user context to be passed back along with the callback + \param sessionId - sme session interface \return eHalStatus ---------------------------------------------------------------------------*/ eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId, tANI_U32 statsMask, tCsrStatsCallback callback, tANI_U32 periodicity, tANI_BOOLEAN cache, - tANI_U8 staId, void *pContext) + tANI_U8 staId, void *pContext, + tANI_U8 sessionId) { eHalStatus status = eHAL_STATUS_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); @@ -4801,7 +4898,8 @@ eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId if ( HAL_STATUS_SUCCESS( status ) ) { status = csrGetStatistics( pMac, requesterId , statsMask, callback, - periodicity, cache, staId, pContext); + periodicity, cache, staId, pContext, + sessionId ); sme_ReleaseGlobalLock( &pMac->sme ); } @@ -9404,26 +9502,20 @@ eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, } csrFlushCfgBgScanRoamChannelList(pMac); csrCreateBgScanRoamChannelList(pMac, pChannelList, numChannels); - status = csrUpdateBgScanConfigIniChannelList(pMac, csrGetCurrentBand(hHal)); - - if ( HAL_STATUS_SUCCESS( status )) + sme_SetRoamScanControl(hHal, 1); + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { - sme_SetRoamScanControl(hHal, 1); - if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + j = 0; + for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) { - j = 0; - for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) - { - j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", - pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); - } + j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); } - - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", - newChannelList, oldChannelList, - pMac->roam.neighborRoamInfo.neighborRoamState); } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", + newChannelList, oldChannelList, + pMac->roam.neighborRoamInfo.neighborRoamState); sme_ReleaseGlobalLock( &pMac->sme ); } #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD @@ -9506,21 +9598,6 @@ eHalStatus sme_SetCcxRoamScanChannelList(tHalHandle hHal, #endif /*-------------------------------------------------------------------------- - \brief csrUpdateBgScanConfigIniChannelList() - Update bgscan roam cache - This is a synchronous call - \param hHal - The handle returned by macOpen. - \return eHAL_STATUS_SUCCESS - SME update config successful. - Other status means SME is failed to update - \sa - --------------------------------------------------------------------------*/ -eHalStatus sme_UpdateBgScanConfigIniChannelList(tHalHandle hHal, - eCsrBand eBand) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - return csrUpdateBgScanConfigIniChannelList(pMac, eBand); -} - -/*-------------------------------------------------------------------------- \brief sme_getRoamScanChannelList() - get roam scan channel list This is a synchronous call \param hHal - The handle returned by macOpen. @@ -10830,3 +10907,129 @@ eHalStatus sme_AddChAvoidCallback } #endif /* FEATURE_WLAN_CH_AVOID */ +/* ------------------------------------------------------------------------- + \fn sme_RoamChannelChangeReq + \brief API to Indicate Channel change to new target channel + \param hHal - The handle returned by macOpen + \param sessionId - session ID + \param targetChannel - New Channel to move the SAP to. + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamChannelChangeReq( tHalHandle hHal, + tANI_U8 sessionId, tANI_U8 targetChannel ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamChannelChangeReq( pMac, sessionId, targetChannel); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* ------------------------------------------------------------------------- + \fn sme_ProcessChannelChangeResp + \brief API to Indicate Channel change response message to SAP. + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_ProcessChannelChangeResp(tpAniSirGlobal pMac, + v_U16_t msg_type, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = {0}; + eCsrRoamResult roamResult; + tpSwitchChannelParams pChnlParams = (tpSwitchChannelParams) pMsgBuf; + tANI_U32 SessionId = pChnlParams->peSessionId; + + pRoamInfo.channelChangeRespEvent = + (tSirChanChangeResponse *)vos_mem_malloc( + sizeof(tSirChanChangeResponse)); + if (NULL == pRoamInfo.channelChangeRespEvent) + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, "Channel Change Event Allocation Failed: %d\n", + status); + return status; + } + if (msg_type == eWNI_SME_CHANNEL_CHANGE_RSP) + { + pRoamInfo.channelChangeRespEvent->sessionId = SessionId; + pRoamInfo.channelChangeRespEvent->newChannelNumber = + pChnlParams->channelNumber; + pRoamInfo.channelChangeRespEvent->secondaryChannelOffset = + pChnlParams->secondaryChannelOffset; + + if (pChnlParams->status == eHAL_STATUS_SUCCESS) + { + pRoamInfo.channelChangeRespEvent->channelChangeStatus = 1; + roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS; + } + else + { + pRoamInfo.channelChangeRespEvent->channelChangeStatus = 0; + roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE; + } + + csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, + eCSR_ROAM_SET_CHANNEL_RSP, roamResult); + + } + else + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, "Invalid Channel Change Resp Message: %d\n", + status); + } + return status; +} + +/* ------------------------------------------------------------------------- + \fn sme_RoamStartBeaconReq + \brief API to Indicate LIM to start Beacon Tx + \after SAP CAC Wait is completed. + \param hHal - The handle returned by macOpen + \param sessionId - session ID + \param dfsCacWaitStatus - CAC WAIT status flag + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamStartBeaconReq( tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 dfsCacWaitStatus) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamStartBeaconReq( pMac, sessionId, dfsCacWaitStatus); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* ------------------------------------------------------------------------- + \fn sme_RoamCsaIeRequest + \brief API to request CSA IE transmission from PE + \param hHal - The handle returned by macOpen + \param sessionId - session ID + \param pDfsCsaReq - CSA IE request + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamCsaIeRequest(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 targetChannel, tANI_U8 csaIeReqd) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamSendChanSwIERequest(pMac, sessionId, + targetChannel, csaIeReqd); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + diff --git a/CORE/SME/src/sme_common/sme_Trace.c b/CORE/SME/src/sme_common/sme_Trace.c index 72196d934aba..aa6a872d9fbc 100644 --- a/CORE/SME/src/sme_common/sme_Trace.c +++ b/CORE/SME/src/sme_common/sme_Trace.c @@ -31,12 +31,6 @@ \author Kiran Kumar Reddy CH L V - Copyright (c) 2013 Qualcomm Atheros, Inc. - - All Rights Reserved. - - Qualcomm Atheros Confidential and Proprietary. - ========================================================================*/ #include "aniGlobal.h" //for tpAniSirGlobal #include "smsDebug.h" diff --git a/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c b/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c index c6fb96df19f5..13b600c2998f 100644 --- a/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c +++ b/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c @@ -196,24 +196,24 @@ static void ptt_proc_quarky_msg(tAniNlHdr *wnl, tAniHdr *wmsg, int radio) { case PTT_MSG_READ_REGISTER: reg_addr = *(v_U32_t*) ((char*)wmsg + 8); - PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_READ_REGISTER [0x%08lX]\n", + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_READ_REGISTER [0x%08X]\n", __func__, reg_addr); vosStatus = sme_DbgReadRegister(pAdapterHandle->hHal, reg_addr, ®_val); *(v_U32_t*) ((char*)wmsg + 12) = reg_val; if(vosStatus != VOS_STATUS_SUCCESS) - PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Read Register [0x%08lX] failed!!\n", + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Read Register [0x%08X] failed!!\n", __func__, reg_addr); ptt_sock_send_msg_to_app(wmsg, 0, ANI_NL_MSG_PUMAC, wnl->nlh.nlmsg_pid); break; case PTT_MSG_WRITE_REGISTER: reg_addr = *(v_U32_t*) ((const unsigned char*)wmsg + 8); reg_val = *(v_U32_t*)((const unsigned char*)wmsg + 12); - PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_WRITE_REGISTER Addr [0x%08lX] value [0x%08lX]\n", + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_WRITE_REGISTER Addr [0x%08X] value [0x%08X]\n", __func__, reg_addr, reg_val); vosStatus = sme_DbgWriteRegister(pAdapterHandle->hHal, reg_addr, reg_val); if(vosStatus != VOS_STATUS_SUCCESS) { - PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Write Register [0x%08lX] value [0x%08lX] failed!!\n", + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Write Register [0x%08X] value [0x%08X] failed!!\n", __func__, reg_addr, reg_val); } //send message to the app @@ -222,12 +222,12 @@ static void ptt_proc_quarky_msg(tAniNlHdr *wnl, tAniHdr *wmsg, int radio) case PTT_MSG_READ_MEMORY: reg_addr = *(v_U32_t*) ((char*)wmsg + 8); len_payload = *(v_U32_t*) ((char*)wmsg + 12); - PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_READ_MEMORY addr [0x%08lX] bytes [0x%08lX]\n", + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_READ_MEMORY addr [0x%08X] bytes [0x%08X]\n", __func__, reg_addr, len_payload); buf = (v_U8_t*)wmsg + 16; vosStatus = sme_DbgReadMemory(pAdapterHandle->hHal, reg_addr, buf, len_payload); if(vosStatus != VOS_STATUS_SUCCESS) { - PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Memory read failed for [0x%08lX]!!\n", + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Memory read failed for [0x%08X]!!\n", __func__, reg_addr); } ptt_sock_swap_32(buf, len_payload); @@ -237,14 +237,14 @@ static void ptt_proc_quarky_msg(tAniNlHdr *wnl, tAniHdr *wmsg, int radio) case PTT_MSG_WRITE_MEMORY: reg_addr = *(v_U32_t*) ((char*)wmsg + 8); len_payload = *(v_U32_t*) ((char*)wmsg + 12); - PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_DBG_WRITE_MEMORY addr [0x%08lX] bytes [0x%08lX]\n", + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: PTT_MSG_DBG_WRITE_MEMORY addr [0x%08X] bytes [0x%08X]\n", __func__, reg_addr, len_payload); buf = (v_U8_t*)wmsg + 16; ptt_sock_swap_32(buf, len_payload); vosStatus = sme_DbgWriteMemory(pAdapterHandle->hHal, reg_addr, buf, len_payload); if(vosStatus != VOS_STATUS_SUCCESS) { - PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Memory write failed for addr [0x%08lX]!!\n", + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Memory write failed for addr [0x%08X]!!\n", __func__, reg_addr); } //send message to the app diff --git a/CORE/SYS/common/src/wlan_qct_sys.c b/CORE/SYS/common/src/wlan_qct_sys.c index 328ec951319e..ff5a8bec0e37 100644 --- a/CORE/SYS/common/src/wlan_qct_sys.c +++ b/CORE/SYS/common/src/wlan_qct_sys.c @@ -380,16 +380,12 @@ VOS_STATUS sysMcProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) case SYS_MSG_ID_MC_TIMER: { - vos_timer_callback_t timerCB; - // hummmm... note says... - // invoke the timer callback and the user data stick - // into the bodyval; no body to free. I think this is - // what that means. - timerCB = (vos_timer_callback_t)pMsg->bodyptr; - - // make the callback to the timer routine... - timerCB( (v_VOID_t *)pMsg->bodyval ); + vos_timer_callback_t timerCB = pMsg->callback; + if (NULL != timerCB) + { + timerCB(pMsg->bodyptr); + } break; } case SYS_MSG_ID_FTM_RSP: @@ -469,17 +465,12 @@ VOS_STATUS sysTxProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) case SYS_MSG_ID_TX_TIMER: { - vos_timer_callback_t timerCB; - - // hummmm... note says... - // invoke the timer callback and the user data stick - // into the bodyval; no body to free. I think this is - // what that means. - timerCB = (vos_timer_callback_t)pMsg->bodyptr; - - // make the callback to the timer routine... - timerCB( (v_VOID_t *)pMsg->bodyval ); + vos_timer_callback_t timerCB = pMsg->callback; + if (NULL != timerCB) + { + timerCB(pMsg->bodyptr); + } break; } @@ -526,17 +517,12 @@ VOS_STATUS sysRxProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) { case SYS_MSG_ID_RX_TIMER: { - vos_timer_callback_t timerCB; - - // hummmm... note says... - // invoke the timer callback and the user data stick - // into the bodyval; no body to free. I think this is - // what that means. - timerCB = (vos_timer_callback_t)pMsg->bodyptr; - - // make the callback to the timer routine... - timerCB( (v_VOID_t *)pMsg->bodyval ); + vos_timer_callback_t timerCB = pMsg->callback; + if (NULL != timerCB) + { + timerCB(pMsg->bodyptr); + } break; } diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h index dc54fd115627..898c6ce1df20 100644 --- a/CORE/TL/inc/wlan_qct_tl.h +++ b/CORE/TL/inc/wlan_qct_tl.h @@ -1298,39 +1298,6 @@ adf_nbuf_t WLANTL_SendSTA_DataFrame(v_PVOID_t pvosGCtx, v_U8_t ucSTAId, adf_nbuf_t buf); #endif -#ifdef IPA_OFFLOAD -/*=========================================================================== - - FUNCTION WLANTL_SendIPA_DataFrame - - DESCRIPTION - - HDD will call this API when there is a packet to be transmitted from IPA - - DEPENDENCIES - - A station must have been registered before sending packet to txrx layer - - - PARAMETERS - - vos_ctx: pointer to the global vos context; a handle to TL's - control block can be extracted from its context - vdev: virtual device - buf: packet given by uppler layer for tx - - RETURN VALUE - - On success it will return NULL. On failure it will be the - passed buf pointer so that the caller will be able to free - up the buffer. - -============================================================================*/ -adf_nbuf_t WLANTL_SendIPA_DataFrame(void *vos_ctx, void *vdev, - adf_nbuf_t buf); -#endif - - /*========================================================================== FUNCTION WLANTL_SetSTAPriority diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index e68f1926e0c4..5e90b7593a6b 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -5846,7 +5846,7 @@ WLANTL_RxFrames broadcast = VOS_FALSE; #else vosStatus = WLANTL_ReadRSSI(pvosGCtx, pvBDHeader, ucSTAId); -#endif /*FEATURE_WLAN_GEN6_ROAMING*/ +#endif if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, @@ -6148,7 +6148,7 @@ WLANTL_RxCachedFrames broadcast = VOS_FALSE; #else vosStatus = WLANTL_ReadRSSI(vos_get_global_context(VOS_MODULE_ID_TL,pTLCb), pvBDHeader, ucSTAId); -#endif /*FEATURE_WLAN_GEN6_ROAMING*/ +#endif if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, diff --git a/CORE/TL/src/wlan_qct_tl_hosupport.c b/CORE/TL/src/wlan_qct_tl_hosupport.c index 911acde7f863..6d7007bb48f6 100644 --- a/CORE/TL/src/wlan_qct_tl_hosupport.c +++ b/CORE/TL/src/wlan_qct_tl_hosupport.c @@ -2031,4 +2031,4 @@ VOS_STATUS WLANTL_HSSerializeTlIndication return status; } -#endif //FEATURE_WLAN_GEN6_ROAMING || WLAN_FEATURE_NEIGHBOR_ROAMING +#endif //WLAN_FEATURE_NEIGHBOR_ROAMING diff --git a/CORE/TL/src/wlan_qct_tl_hosupport.h b/CORE/TL/src/wlan_qct_tl_hosupport.h index e75aefd697ed..72ac18473985 100644 --- a/CORE/TL/src/wlan_qct_tl_hosupport.h +++ b/CORE/TL/src/wlan_qct_tl_hosupport.h @@ -301,6 +301,6 @@ VOS_STATUS WLANTL_StatHandleTXFrame WLANTL_MetaInfoType *txMetaInfo ); -#endif //FEATURE_WLAN_GEN6_ROAMING +#endif #endif /* WLAN_QCT_TL_HOSUPPORT_H */ diff --git a/CORE/UTILS/FWLOG/dbglog_host.c b/CORE/UTILS/FWLOG/dbglog_host.c index d04931d536fb..d8163120798c 100644 --- a/CORE/UTILS/FWLOG/dbglog_host.c +++ b/CORE/UTILS/FWLOG/dbglog_host.c @@ -24,21 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ -/* - * Copyright (c) 2013, Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ /* Host Debug log implementation */ @@ -513,8 +498,24 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "COEX_MWS_REMOTE_EVENT", "COEX_MWS_OTHER", "COEX_MWS_ERROR", - "COEX_MWS_ANT_DIVERSITY", - "COEX_DEBUG_ID_END" + "COEX_MWS_ANT_DIVERSITY", //237 + "COEX_P2P_GO", + "COEX_P2P_CLIENT", + "COEX_SCC_1", + "COEX_SCC_2", + "COEX_MCC_1", + "COEX_MCC_2", + "COEX_TRF_SHAPE_NOA", + "COEX_NOA_ONESHOT", + "COEX_NOA_PERIODIC", + "COEX_LE_1", + "COEX_LE_2", + "COEX_ANT_1", + "COEX_ANT_2", + "COEX_ENTER_NOA", + "COEX_EXIT_NOA", + "COEX_BT_SCAN_PROTECT", // 253 + "COEX_DEBUG_ID_END" // 254 }, { "ROAM_DBGID_DEFINITION_START", @@ -645,6 +646,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "VDEV_MGR_VDEV_PAUSE_DELAY_UPDATE", "VDEV_MGR_VDEV_PAUSE_FAIL", "VDEV_MGR_GEN_PERIODIC_NOA", + "VDEV_MGR_OFF_CHAN_GO_CH_REQ_SETUP", "VDEV_MGR_DEFINITION_END", }, { @@ -896,6 +898,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "P2P_GO_GET_NOA_INFO", "P2P_GO_ADD_ONE_SHOT_NOA", "P2P_GO_GET_NOA_IE", + "P2P_GO_BCN_TX_COMP", "P2P_DBGID_DEFINITION_END", }, { diff --git a/CORE/VOSS/inc/i_vos_packet.h b/CORE/VOSS/inc/i_vos_packet.h index 9e390736c0c8..0bdb3d572de9 100644 --- a/CORE/VOSS/inc/i_vos_packet.h +++ b/CORE/VOSS/inc/i_vos_packet.h @@ -62,6 +62,7 @@ typedef struct u_int8_t offloadScanLearn:1; u_int8_t roamCandidateInd:1; u_int8_t scan:1; + u_int8_t dpuFeedback; }t_packetmeta, *tp_packetmeta; /* implementation specific vos packet type */ diff --git a/CORE/VOSS/inc/packet.h b/CORE/VOSS/inc/packet.h deleted file mode 100644 index 18af00f8c804..000000000000 --- a/CORE/VOSS/inc/packet.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - -/**======================================================================== - - \file packet.h - \brief - - ========================================================================*/ -/**========================================================================= - EDIT HISTORY FOR FILE - - - This section contains comments describing changes made to the module. - Notice that changes are listed in reverse chronological order. - - $Header:$ $DateTime: $ $Author: $ - - - when who what, where, why - -------- --- ----------------------------------------- - 26/03/2013 Ganesh Created module for Packet Handling - Babu - ==========================================================================*/ -#ifndef _PACKET_H_ -#define _PACKET_H_ -#include "adf_os_types.h" - -/* - * Rx Packet Struct - */ -typedef struct -{ - u_int8_t channel; - u_int8_t snr; - u_int32_t rssi; - u_int32_t timestamp; - u_int8_t *mpdu_hdr_ptr; - u_int8_t *mpdu_data_ptr; - u_int32_t mpdu_len; - u_int32_t mpdu_hdr_len; - u_int32_t mpdu_data_len; -}t_rxpacketmeta, *tp_rxpacketmeta; - -typedef struct -{ - /* Rx Packet Meta Information */ - t_rxpacketmeta rxpktmeta; - - /* Pointer to Rx Packet */ - void *rx_nbuf; - -}t_rxpacket, *tp_rxpacket; - -/** - * voss_rx_packet_free Free the Rx Packet - * @ Rx Packet - */ -void voss_rx_packet_free(void* rxpacket); - -#endif //_PACKET_H_ - diff --git a/CORE/VOSS/inc/vos_mq.h b/CORE/VOSS/inc/vos_mq.h index ac7b150e7212..7654aa80f89d 100644 --- a/CORE/VOSS/inc/vos_mq.h +++ b/CORE/VOSS/inc/vos_mq.h @@ -77,9 +77,15 @@ typedef struct vos_msg_s * Messages should use either bodyptr or bodyval; not both !!!. */ void *bodyptr; - - v_U32_t bodyval; - + + v_U32_t bodyval; + + /* + * Some messages provide a callback function. The function signature + * must be agreed upon between the two entities exchanging the message + */ + void *callback; + } vos_msg_t; diff --git a/CORE/VOSS/inc/vos_utils.h b/CORE/VOSS/inc/vos_utils.h index c3f0aba1cc33..1ddf2dcb8000 100644 --- a/CORE/VOSS/inc/vos_utils.h +++ b/CORE/VOSS/inc/vos_utils.h @@ -168,4 +168,9 @@ VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */ v_U32_t vos_chan_to_freq(v_U8_t chan); v_U8_t vos_freq_to_chan(v_U32_t freq); +#ifdef WLAN_FEATURE_11W +v_BOOL_t vos_is_mmie_valid(v_U8_t *key, v_U8_t *ipn, + v_U8_t* frm, v_U8_t* efrm); +v_U8_t vos_get_mmie_size(void); +#endif /* WLAN_FEATURE_11W */ #endif // #if !defined __VOSS_UTILS_H diff --git a/CORE/VOSS/inc/wcnss_api.h b/CORE/VOSS/inc/wcnss_api.h index b5bc45e02506..197841ea2f5b 100644 --- a/CORE/VOSS/inc/wcnss_api.h +++ b/CORE/VOSS/inc/wcnss_api.h @@ -86,44 +86,6 @@ static inline unsigned int wcnss_get_serial_number(void) { return 0; } - -static inline void *wcnss_wlan_crypto_alloc_ahash(const char *alg_name, - unsigned int type, - unsigned int mask) -{ - return NULL; -} - -static inline int wcnss_wlan_crypto_ahash_digest(void *req) -{ - return 0; -} - -static inline void wcnss_wlan_crypto_free_ahash(void *tfm) -{ -} - -static inline int wcnss_wlan_crypto_ahash_setkey(void *tfm, - const u8 *key, - unsigned int keylen) -{ - return 0; -} - -static inline void *wcnss_wlan_crypto_alloc_ablkcipher(const char *alg_name, - u32 type, u32 mask) -{ - return NULL; -} - -static inline void wcnss_wlan_ablkcipher_request_free(void *req) -{ -} - -static inline void wcnss_wlan_crypto_free_ablkcipher(void *tfm) -{ -} - static inline int req_riva_power_on_lock(char *driver_name) { return 0; diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index ca735ecaa54f..9d0e324e4f08 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -405,6 +405,7 @@ VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ) #if defined (QCA_WIFI_2_0) && \ !defined (QCA_WIFI_ISOC) hdd_update_tgt_cfg, + hdd_dfs_indicate_radar, #else NULL, #endif @@ -425,6 +426,11 @@ VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ) #if defined (QCA_WIFI_2_0) && \ !defined (QCA_WIFI_ISOC) + /* This macOpenParams.maxStation has value incremented by 1 for PeerIdx logic. + * So here we are decrementing by 1 to assign in the ini.With this change + * there is no ned to define gSoftApMaxPeers ini for Rome >= 1.3 + */ + pHddCtx->cfg_ini->maxNumberOfPeers = macOpenParms.maxStation - 1; if (HTCWaitTarget(vos_get_context(VOS_MODULE_ID_HTC, gpVosContext))) { VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, "%s: Failed to complete BMI phase", __func__); diff --git a/CORE/VOSS/src/vos_getBin.c b/CORE/VOSS/src/vos_getBin.c index 036ea5699f8c..0c147c97c643 100644 --- a/CORE/VOSS/src/vos_getBin.c +++ b/CORE/VOSS/src/vos_getBin.c @@ -28,9 +28,6 @@ vos_getBin.c \brief Description... - Copyright (c) 2012-2013 Qualcomm Atheros, Inc. - All Rights Reserved. - Qualcomm Atheros Confidential and Proprietary. ==============================================================================*/ /* $HEADER$ */ /**----------------------------------------------------------------------------- diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index 184e8f7240a1..ea2599edea0f 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3081,160 +3081,6 @@ VOS_STATUS vos_nv_getRegDomainFromCountryCode( v_REGDOMAIN_t *pRegDomain, } -/* create_crda_regulatory_entry_from_regd should be called during init time */ -static int create_linux_regulatory_entry_from_regd(struct wiphy *wiphy, - struct regulatory_request *request, - v_U8_t nBandCapability) -{ - int i, j, n, domain_id; - int bw20_start_channel_index, bw20_end_channel_index; - int bw40_start_channel_index, bw40_end_channel_index; - v_CONTEXT_t pVosContext = NULL; - hdd_context_t *pHddCtx = NULL; - - if (wiphy->regd == NULL) - { - wiphy_dbg(wiphy, "error: wiphy->regd is NULL\n"); - return -1; - } - pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - - if (NULL != pVosContext) - { - pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); - if (NULL == pHddCtx) - { - VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - ("Invalid pHddCtx pointer") ); - } - else - { - pHddCtx->isVHT80Allowed = 0; - } - } - else - { - VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - ("Invalid pVosContext pointer") ); - } - - domain_id = temp_reg_domain; - - for (n = 0; n < NUM_RF_CHANNELS; n++) - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[n].enabled = NV_CHANNEL_DISABLE; - - for (i = 0; i < wiphy->regd->n_reg_rules; i++) - { - - wiphy_dbg(wiphy, "info: crda rule %d --------------------------------------------\n", i); - bw20_start_channel_index = - bw20_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz); - bw20_end_channel_index = - bw20_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz); - - if (bw20_start_channel_index == -1 || bw20_end_channel_index == -1) - { - wiphy_dbg(wiphy, "error: crda freq not supported, start freq (KHz) %d end freq %d\n", - wiphy->regd->reg_rules[i].freq_range.start_freq_khz, - wiphy->regd->reg_rules[i].freq_range.end_freq_khz); - continue; // skip this rull, but continue to next rule - } - - wiphy_dbg(wiphy, "20MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n", - wiphy->regd->reg_rules[i].freq_range.start_freq_khz, - wiphy->regd->reg_rules[i].freq_range.end_freq_khz, - bw20_start_channel_index, bw20_end_channel_index); - - for (j=bw20_start_channel_index;j<=bw20_end_channel_index;j++) - { - if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE) - { - wiphy_dbg(wiphy, "info: CH %d is not in capable band\n", - rfChannels[j].channelNum); - continue; // skip this channel, continue to next - } - - if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS) - { - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS; - wiphy_dbg(wiphy, "info: CH %d is DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum, - wiphy->regd->reg_rules[i].power_rule.max_eirp); - } - else - { - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE; - wiphy_dbg(wiphy, "info: CH %d is enabled, no DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum, - wiphy->regd->reg_rules[i].power_rule.max_eirp); - } - - /* max_eirp is in mBm (= 100 * dBm) unit */ - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit = - (tANI_S8) ((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100); - } - - /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is - real gain which should be provided by the real design */ - if (wiphy->regd->reg_rules[i].freq_range.max_bandwidth_khz >= 40000) - { - if (wiphy->regd->reg_rules[i].freq_range.max_bandwidth_khz >= 80000) - { - wiphy_dbg(wiphy, "info: 80MHz (channel bonding) is allowed\n"); - if (NULL == pHddCtx) - { - VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - ("Invalid pHddCtx pointer") ); - } - else - { - pHddCtx->isVHT80Allowed = 1; - } - - - } - else - { - wiphy_dbg(wiphy, "info: ONLY 40MHz (channel bonding) is allowed\n"); - } - bw40_start_channel_index = - bw40_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz); - bw40_end_channel_index = - bw40_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz); - if (bw40_start_channel_index == -1 || bw40_end_channel_index == -1) - { - wiphy_dbg(wiphy, "error: crda freq not supported, start_freq_khz %d end_freq_khz %d\n", - wiphy->regd->reg_rules[i].freq_range.start_freq_khz, - wiphy->regd->reg_rules[i].freq_range.end_freq_khz); - continue; // skip this rull, but continue to next rule - } - - wiphy_dbg(wiphy, "40MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n", - wiphy->regd->reg_rules[i].freq_range.start_freq_khz, - wiphy->regd->reg_rules[i].freq_range.end_freq_khz, - bw40_start_channel_index, bw40_end_channel_index); - for (j=bw40_start_channel_index;j<=bw40_end_channel_index;j++) - { - if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE) - continue; // skip this channel, continue to next - if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS) - { - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS; - wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is DFS\n", rfChannels[j].channelNum); - } - else - { - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE; - wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is enabled, no DFS\n", rfChannels[j].channelNum); - } - /* set 40MHz channel power as half (- 3 dB) of 20MHz */ - pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit = - (tANI_S8) (((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100)-3); - } - } - } - - return 0; -} - /* create_linux_regulatory_entry to populate internal structures from wiphy */ static int create_linux_regulatory_entry(struct wiphy *wiphy, v_U8_t nBandCapability) @@ -3351,6 +3197,7 @@ static int create_linux_regulatory_entry(struct wiphy *wiphy, pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = NV_CHANNEL_DISABLE; } + /* nv cannot distinguish between DFS and passive channels */ else if (wiphy->bands[i]->channels[j].flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)) @@ -3358,9 +3205,21 @@ static int create_linux_regulatory_entry(struct wiphy *wiphy, pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].enabled = NV_CHANNEL_DFS; + /* This is a temporary change for getting the SAP functional on DFS channels + * If the driver is using linux regulatory domain, the hostapd + cfg8211 + * reserve the right to allow whether the BSS can be started or not depending + * on the current country, whether the radar is present on the channel and/or + * also the DFS state of the current channel. This is done if the driver supplies + * PASSIVE and DFS flags for DFS channels + * Currently we will not advertise these capabilities until the fix is cleanly + * done the hostapd and cfg80211 + */ + wiphy->bands[i]->channels[j].flags &= ~(IEEE80211_CHAN_RADAR); + wiphy->bands[i]->channels[j].flags &= ~(IEEE80211_CHAN_PASSIVE_SCAN); + /* max_power is in mBm = 100 * dBm */ pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit = - (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100); + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)); if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0) { pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = @@ -3368,7 +3227,7 @@ static int create_linux_regulatory_entry(struct wiphy *wiphy, /* 40MHz channel power is half of 20MHz (-3dB) ?? */ pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].pwrLimit = - (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3); + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power))-3); } if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_80MHZ) == 0) { @@ -3390,14 +3249,14 @@ static int create_linux_regulatory_entry(struct wiphy *wiphy, /* max_power is in dBm */ pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit = - (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100); + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)); if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0) { pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = NV_CHANNEL_ENABLE; /* 40MHz channel power is half of 20MHz (-3dB) */ pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].pwrLimit = - (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3); + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power))-3); } if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_80MHZ) == 0) { diff --git a/CORE/VOSS/src/vos_timer.c b/CORE/VOSS/src/vos_timer.c index 8f6c1bdcc602..77081365b0cb 100644 --- a/CORE/VOSS/src/vos_timer.c +++ b/CORE/VOSS/src/vos_timer.c @@ -187,8 +187,9 @@ static void vos_linux_timer_callback (unsigned long data) //Serialize to the Tx thread sysBuildMessageHeader( SYS_MSG_ID_TX_TIMER, &msg ); - msg.bodyptr = callback; - msg.bodyval = (v_U32_t)userData; + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; if(vos_tx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; @@ -200,8 +201,9 @@ static void vos_linux_timer_callback (unsigned long data) //Serialize to the Rx thread sysBuildMessageHeader( SYS_MSG_ID_RX_TIMER, &msg ); - msg.bodyptr = callback; - msg.bodyval = (v_U32_t)userData; + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; if(vos_rx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; @@ -213,8 +215,9 @@ static void vos_linux_timer_callback (unsigned long data) // Serialize to the MC thread sysBuildMessageHeader( SYS_MSG_ID_MC_TIMER, &msg ); - msg.bodyptr = callback; - msg.bodyval = (v_U32_t)userData; + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; if(vos_mq_post_message( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; diff --git a/CORE/VOSS/src/vos_utils.c b/CORE/VOSS/src/vos_utils.c index 20b04d26cda0..598cd06fbfe4 100644 --- a/CORE/VOSS/src/vos_utils.c +++ b/CORE/VOSS/src/vos_utils.c @@ -66,12 +66,20 @@ #include <linux/crypto.h> #include <linux/scatterlist.h> #include <linux/completion.h> +#include <linux/ieee80211.h> #include <crypto/hash.h> +#include <crypto/aes.h> #include <wcnss_api.h> +#include <linux/qcomwlan_secif.h> +#include "ieee80211_common.h" /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ +#define AAD_LEN 20 +#define IV_SIZE_AES_128 16 +#define CMAC_IPN_LEN 6 + /*---------------------------------------------------------------------------- * Type Declarations @@ -113,7 +121,7 @@ VOS_STATUS vos_crypto_init( v_U32_t *phCryptProv ) VOS_STATUS uResult = VOS_STATUS_E_FAILURE; // This implementation doesn't require a crypto context - *phCryptProv = (v_U32_t)NULL; + *phCryptProv = 0; uResult = VOS_STATUS_SUCCESS; return ( uResult ); } @@ -178,6 +186,129 @@ VOS_STATUS vos_rand_get_bytes( v_U32_t cryptHandle, v_U8_t *pbBuf, v_U32_t numBy } +#ifdef WLAN_FEATURE_11W +v_U8_t vos_get_mmie_size() +{ + return sizeof(struct ieee80211_mmie); +} + +v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn, + v_U8_t* frm, v_U8_t* efrm) +{ + struct ieee80211_mmie *mmie; + struct ieee80211_frame *wh; + v_U8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input; + v_U16_t nBytes = 0; + int ret = 0; + struct crypto_cipher *tfm; + + /* Check if frame is invalid length */ + if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "Invalid frame length"); + return VOS_FALSE; + } + + mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie)); + + /* Check Element ID */ + if ((mmie->element_id != IEEE80211_ELEMID_MMIE) || + (mmie->length != (sizeof(*mmie)-2))) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "IE is not Mgmt MIC IE or Invalid length"); + /* IE is not Mgmt MIC IE or invalid length */ + return VOS_FALSE; + } + + /* Validate IPN */ + rx_ipn = mmie->sequence_number; + if (OS_MEMCMP(rx_ipn, ipn, CMAC_IPN_LEN) <= 0) + { + /* Replay error */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + " mmie ipn %02X %02X %02X %02X %02X %02X" + " drvr ipn %02X %02X %02X %02X %02X %02X", + rx_ipn[0], rx_ipn[1], rx_ipn[2], rx_ipn[3], rx_ipn[4], rx_ipn[5], + ipn[0], ipn[1], ipn[2], ipn[3], ipn[4], ipn[5]); + return VOS_FALSE; + } + + tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, + "crypto_alloc_cipher failed (%d)", ret); + goto err_tfm; + } + + ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128); + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, + "crypto_cipher_setkey failed (%d)", ret); + goto err_tfm; + } + + /* Construct AAD */ + wh = (struct ieee80211_frame *)frm; + + /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */ + + /* FC type/subtype */ + aad[0] = wh->i_fc[0]; + /* Mask FC Retry, PwrMgt, MoreData flags to zero */ + aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT | + IEEE80211_FC1_MORE_DATA); + /* A1 || A2 || A3 */ + vos_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN); + + /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ + nBytes = AAD_LEN + (efrm - (v_U8_t*)(wh+1)); + input = (v_U8_t *)vos_mem_malloc(nBytes); + if (NULL == input) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "Memory allocation failed"); + ret = VOS_STATUS_E_NOMEM; + goto err_tfm; + } + + /* Copy the AAD, MMIE with 8 bit MIC zeroed out */ + vos_mem_zero(input, nBytes); + vos_mem_copy(input, aad, AAD_LEN); + vos_mem_copy(input+AAD_LEN, (v_U8_t*)(wh+1), nBytes - AAD_LEN - CMAC_TLEN); + + wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic); + vos_mem_free(input); + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X", + mic[0], mic[1], mic[2], mic[3], + mic[4], mic[5], mic[6], mic[7]); + + if (OS_MEMCMP(mic, mmie->mic, CMAC_TLEN) != 0) { + /* MMIE MIC mismatch */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "BC/MC MGMT frame MMIE MIC check Failed" + " rmic %02X %02X %02X %02X %02X %02X %02X %02X" + " cmic %02X %02X %02X %02X %02X %02X %02X %02X", + mmie->mic[0], mmie->mic[1], mmie->mic[2], mmie->mic[3], + mmie->mic[4], mmie->mic[5], mmie->mic[6], mmie->mic[7], + mic[0], mic[1], mic[2], mic[3], + mic[4], mic[5], mic[6], mic[7]); + return VOS_FALSE; + } + + /* Update IPN */ + vos_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN); + +err_tfm: + if (tfm) + wcnss_wlan_crypto_free_cipher(tfm); + + return !ret?VOS_TRUE:VOS_FALSE; +} + +#endif /* WLAN_FEATURE_11W */ /** * vos_sha1_hmac_str * @@ -532,16 +663,11 @@ static void ecb_aes_complete(struct crypto_async_request *req, int err) ( *** return value not considered yet ) --------------------------------------------------------------------------*/ -#define IV_SIZE_AES_128 16 -#define KEY_SIZE_AES_128 16 -#define AES_BLOCK_SIZE 16 - VOS_STATUS vos_encrypt_AES(v_U32_t cryptHandle, /* Handle */ v_U8_t *pPlainText, /* pointer to data stream */ v_U8_t *pCiphertext, v_U8_t *pKey) /* pointer to authentication key */ { -// VOS_STATUS uResult = VOS_STATUS_E_FAILURE; struct ecb_aes_result result; struct ablkcipher_request *req; struct crypto_ablkcipher *tfm; @@ -572,7 +698,7 @@ VOS_STATUS vos_encrypt_AES(v_U32_t cryptHandle, /* Handle */ crypto_ablkcipher_clear_flags(tfm, ~0); - ret = crypto_ablkcipher_setkey(tfm, pKey, KEY_SIZE_AES_128); + ret = crypto_ablkcipher_setkey(tfm, pKey, AES_KEYSIZE_128); if (ret) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_cipher_setkey failed"); goto err_setkey; @@ -668,7 +794,7 @@ VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */ crypto_ablkcipher_clear_flags(tfm, ~0); - ret = crypto_ablkcipher_setkey(tfm, pKey, KEY_SIZE_AES_128); + ret = crypto_ablkcipher_setkey(tfm, pKey, AES_KEYSIZE_128); if (ret) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_cipher_setkey failed"); goto err_setkey; diff --git a/CORE/WDA/inc/legacy/halMsgApi.h b/CORE/WDA/inc/legacy/halMsgApi.h index 35b5675fdd33..2fb9a6aa051a 100644 --- a/CORE/WDA/inc/legacy/halMsgApi.h +++ b/CORE/WDA/inc/legacy/halMsgApi.h @@ -1000,7 +1000,7 @@ typedef struct tANI_U16 smpsMode; - + tANI_U8 isDfsChannel; }tSwitchChannelParams, *tpSwitchChannelParams; typedef struct CSAOffloadParams { diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index 7eaac1377c3f..223af8f972e7 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -353,6 +353,13 @@ typedef eHalStatus (*pWDAAckFnTxComp)(tpAniSirGlobal, tANI_U32); /* generic callback for updating parameters from target to UMAC */ typedef void (*wda_tgt_cfg_cb) (void *context, void *param); +/* + * callback for Indicating Radar to HDD and disable Tx Queues + * to stop accepting data Tx packets from netif as radar is + * found on the current operating channel + */ +typedef void (*wda_dfs_radar_indication_cb) (void *context, void *param); + typedef struct { tANI_U16 ucValidStaIndex ; @@ -491,8 +498,15 @@ VOS_STATUS WDA_TxPacket(void *pWDA, * open WDA context */ +#ifndef QCA_WIFI_ISOC +VOS_STATUS WDA_open(v_PVOID_t pVosContext, v_PVOID_t pOSContext, + wda_tgt_cfg_cb pTgtUpdCB, + wda_dfs_radar_indication_cb radar_ind_cb, + tMacOpenParameters *pMacParams ) ; +#else VOS_STATUS WDA_open(v_PVOID_t pVosContext, v_PVOID_t pOSContext, wda_tgt_cfg_cb pTgtUpdCB, tMacOpenParameters *pMacParams ) ; +#endif #ifdef QCA_WIFI_2_0 #define WDA_start wma_start @@ -644,7 +658,8 @@ tANI_U8 WDA_MapChannel(tANI_U8); #define WDA_GET_RX_FT_DONE(pRxMeta) 0 -#define WDA_GET_RX_DPU_FEEDBACK(pRxMeta) 0 +#define WDA_GET_RX_DPU_FEEDBACK(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->dpuFeedback) #define WDA_GET_RX_BEACON_SENT(pRxMeta) 0 @@ -1296,6 +1311,14 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #endif #endif +/* Message to Indicate Radar Presence on SAP Channel */ +#define WDA_DFS_RADAR_IND SIR_HAL_DFS_RADAR_IND + +/* Message to indicate beacon tx completion after beacon template update + * beacon offload case + */ +#define WDA_DFS_BEACON_TX_SUCCESS_IND SIR_HAL_BEACON_TX_SUCCESS_IND + tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 7e91b0382708..e5dcda792e24 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -13832,7 +13832,7 @@ void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData) { /* free the mem and return */ VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "Failed to post the rsp to UMAC" ,__func__); + "%s: Failed to post the rsp to UMAC", __func__); } return ; diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h index 6cbeea8f10ba..7eceb18262a2 100644 --- a/CORE/WDI/CP/inc/wlan_qct_wdi.h +++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h @@ -10176,7 +10176,7 @@ wpt_uint8 WDI_getHostWlanFeatCaps(wpt_uint8 feat_enum_value); #ifdef QCA_WIFI_2_0 static inline wpt_uint8 WDI_getFwWlanFeatCaps(wpt_uint8 feat_enum_value) { - return 0; + return 1; } #else wpt_uint8 WDI_getFwWlanFeatCaps(wpt_uint8 feat_enum_value); @@ -50,7 +50,8 @@ endif # To enable CCX upload, dependent config # CONFIG_QCOM_CCX must be enabled. -CONFIG_QCOM_CCX_UPLOAD := n +CONFIG_QCOM_CCX := y +CONFIG_QCOM_CCX_UPLOAD := y # Feature flags which are not (currently) configurable via Kconfig @@ -357,6 +358,26 @@ SAP_OBJS := $(SAP_SRC_DIR)/sapApiLinkCntl.o \ $(SAP_SRC_DIR)/sapFsm.o \ $(SAP_SRC_DIR)/sapModule.o +############ DFS ############ 350 +DFS_DIR := CORE/SERVICES/DFS +DFS_INC_DIR := $(DFS_DIR)/inc +DFS_SRC_DIR := $(DFS_DIR)/src + +DFS_INC := -I$(WLAN_ROOT)/$(DFS_INC_DIR) \ + -I$(WLAN_ROOT)/$(DFS_SRC_DIR) + +DFS_OBJS := $(DFS_SRC_DIR)/dfs_bindetects.o \ + $(DFS_SRC_DIR)/dfs.o \ + $(DFS_SRC_DIR)/dfs_debug.o\ + $(DFS_SRC_DIR)/dfs_fcc_bin5.o\ + $(DFS_SRC_DIR)/dfs_init.o\ + $(DFS_SRC_DIR)/dfs_misc.o\ + $(DFS_SRC_DIR)/dfs_nol.o\ + $(DFS_SRC_DIR)/dfs_phyerr_tlv.o\ + $(DFS_SRC_DIR)/dfs_process_phyerr.o\ + $(DFS_SRC_DIR)/dfs_process_radarevent.o\ + $(DFS_SRC_DIR)/dfs_staggered.o + ############ SME ############ SME_DIR := CORE/SME SME_INC_DIR := $(SME_DIR)/inc @@ -614,7 +635,8 @@ WMA_DIR := CORE/SERVICES/WMA WMA_INC := -I$(WLAN_ROOT)/$(WMA_DIR) -WMA_OBJS := $(WMA_DIR)/wma.o +WMA_OBJS := $(WMA_DIR)/wma.o \ + $(WMA_DIR)/wma_dfs_interface.o ifeq ($(CONFIG_QCA_WIFI_ISOC), 1) WMA_OBJS += $(WMA_DIR)/wma_isoc.o @@ -714,7 +736,8 @@ INCS := $(BAP_INC) \ $(TL_INC) \ $(VOSS_INC) \ $(WDA_INC) \ - $(WDI_INC) + $(WDI_INC) \ + $(DFS_INC) ifeq ($(CONFIG_QCA_WIFI_2_0), 0) INCS += $(DXE_INC) @@ -728,7 +751,8 @@ INCS += $(WMA_INC) \ $(TXRX_INC) \ $(PKTLOG_INC) \ $(HTT_INC) \ - $(HTC_INC) + $(HTC_INC) \ + $(DFS_INC) ifeq ($(CONFIG_QCA_WIFI_ISOC), 0) INCS += $(HIF_INC) \ @@ -753,7 +777,8 @@ OBJS := $(BAP_OBJS) \ $(SYS_OBJS) \ $(VOSS_OBJS) \ $(WDA_OBJS) \ - $(WDI_OBJS) + $(WDI_OBJS) \ + $(DFS_OBJS) ifeq ($(CONFIG_QCA_WIFI_2_0), 0) OBJS += $(DXE_OBJS) \ @@ -765,7 +790,8 @@ OBJS += $(WMA_OBJS) \ $(WMI_OBJS) \ $(FWLOG_OBJS) \ $(HTC_OBJS) \ - $(ADF_OBJS) + $(ADF_OBJS) \ + $(DFS_OBJS) ifeq ($(CONFIG_QCA_WIFI_ISOC), 0) OBJS += $(HIF_OBJS) \ @@ -367,6 +367,25 @@ SAP_OBJS := $(SAP_SRC_DIR)/sapApiLinkCntl.o \ $(SAP_SRC_DIR)/sapFsm.o \ $(SAP_SRC_DIR)/sapModule.o +############ DFS ############ +DFS_DIR := CORE/SERVICES/DFS +DFS_INC_DIR := $(DFS_DIR)/inc +DFS_SRC_DIR := $(DFS_DIR)/src +DFS_INC := -I$(WLAN_ROOT)/$(DFS_INC_DIR) \ + -I$(WLAN_ROOT)/$(DFS_SRC_DIR) + +DFS_OBJS := $(DFS_SRC_DIR)/dfs_bindetects.o \ + $(DFS_SRC_DIR)/dfs.o \ + $(DFS_SRC_DIR)/dfs_debug.o\ + $(DFS_SRC_DIR)/dfs_fcc_bin5.o\ + $(DFS_SRC_DIR)/dfs_init.o\ + $(DFS_SRC_DIR)/dfs_misc.o\ + $(DFS_SRC_DIR)/dfs_nol.o\ + $(DFS_SRC_DIR)/dfs_phyerr_tlv.o\ + $(DFS_SRC_DIR)/dfs_process_phyerr.o\ + $(DFS_SRC_DIR)/dfs_process_radarevent.o\ + $(DFS_SRC_DIR)/dfs_staggered.o + ############ SME ############ SME_DIR := CORE/SME SME_INC_DIR := $(SME_DIR)/inc @@ -626,8 +645,8 @@ WMA_DIR := CORE/SERVICES/WMA WMA_INC := -I$(WLAN_ROOT)/$(WMA_DIR) -WMA_OBJS := $(WMA_DIR)/wma.o - +WMA_OBJS := $(WMA_DIR)/wma.o \ + $(WMA_DIR)/wma_dfs_interface.o ifeq ($(CONFIG_QCA_WIFI_ISOC), 1) WMA_OBJS += $(WMA_DIR)/wma_isoc.o else @@ -726,7 +745,8 @@ INCS := $(BAP_INC) \ $(TL_INC) \ $(VOSS_INC) \ $(WDA_INC) \ - $(WDI_INC) + $(WDI_INC) \ + $(DFS_INC) ifeq ($(CONFIG_QCA_WIFI_2_0), 0) INCS += $(DXE_INC) @@ -765,7 +785,8 @@ OBJS := $(BAP_OBJS) \ $(SYS_OBJS) \ $(VOSS_OBJS) \ $(WDA_OBJS) \ - $(WDI_OBJS) + $(WDI_OBJS)\ + $(DFS_OBJS) ifeq ($(CONFIG_QCA_WIFI_2_0), 0) OBJS += $(DXE_OBJS) \ diff --git a/firmware_bin/WCNSS_qcom_cfg.ini b/firmware_bin/WCNSS_qcom_cfg.ini index 21c3c00794d3..2c16e9926623 100644 --- a/firmware_bin/WCNSS_qcom_cfg.ini +++ b/firmware_bin/WCNSS_qcom_cfg.ini @@ -97,7 +97,7 @@ gEnableTCPChkSumOffld=0 #Flag to enable HostNSOffload feature or not -hostNSOffload=0 +hostNSOffload=1 #Flag to enable IPChkSumOffld feature or not diff --git a/tools/fwdebuglog/cld-fwlog-netlink.c b/tools/fwdebuglog/cld-fwlog-netlink.c index 6fea2298ab5a..0781441d0f52 100644 --- a/tools/fwdebuglog/cld-fwlog-netlink.c +++ b/tools/fwdebuglog/cld-fwlog-netlink.c @@ -53,12 +53,14 @@ #define LOGFILE_FLAG 0x01 #define CONSOLE_FLAG 0x02 #define QXDM_FLAG 0x04 +#define SILENT_FLAG 0x08 const char options[] = "Options:\n\ -f, --logfile=<Output log file> [Mandotory]\n\ -r, --reclimit=<Maximum number of records before the log rolls over> [Optional]\n\ -c, --console (prints the logs in the console)\n\ +-s, --silent (No print will come when logging)\n\ -q, --qxdm (prints the logs in the qxdm)\n\ The options can also be given in the abbreviated form --option=x or -o x. The options can be given in any order"; @@ -77,7 +79,7 @@ const char *progname; char dbglogoutfile[PATH_MAX]; int optionflag; -int rec_limit = 1000000; /* Million records is a good default */ +int rec_limit = 100000000; /* Million records is a good default */ static void usage(void) @@ -91,7 +93,7 @@ extern int parser_init(); extern int -dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len); +dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len, u_int16_t dropped); static unsigned int get_le32(const unsigned char *pos) { @@ -178,11 +180,12 @@ int main(int argc, char *argv[]) {"reclimit", 1, NULL, 'r'}, {"console", 0, NULL, 'c'}, {"qxdm", 0, NULL, 'q'}, + {"silent", 0, NULL, 's'}, { 0, 0, 0, 0} }; while (1) { - c = getopt_long (argc, argv, "f:cq:r:", long_options, &option_index); + c = getopt_long (argc, argv, "f:scq:r:", long_options, &option_index); if (c == -1) break; switch (c) { @@ -205,12 +208,15 @@ int main(int argc, char *argv[]) rec_limit = strtoul(optarg, NULL, 0); break; + case 's': + optionflag |= SILENT_FLAG; + break; default: usage(); } } - if (!(optionflag & (LOGFILE_FLAG | CONSOLE_FLAG | QXDM_FLAG))) { + if (!(optionflag & (LOGFILE_FLAG | CONSOLE_FLAG | QXDM_FLAG | SILENT_FLAG))) { usage(); return -1; } @@ -274,8 +280,10 @@ int main(int argc, char *argv[]) /* Read message from kernel */ while ((res = recvmsg(sock_fd, &msg, 0)) > 0) { buf = (unsigned char *)NLMSG_DATA(nlh); - printf("Read record timestamp=%u length=%u \n", - get_le32(&buf[0]), get_le32(&buf[4])); + if (!((optionflag & SILENT_FLAG) == SILENT_FLAG)) { + printf("Read record timestamp=%u length=%u fw dropped=%u\n", + get_le32(&buf[0]), get_le32(&buf[4]), get_le32(&buf[8])); + } fseek(log_out, record * RECLEN, SEEK_SET); if ((res = fwrite(buf, RECLEN, 1, log_out)) != 1){ perror("fwrite"); @@ -296,7 +304,7 @@ int main(int argc, char *argv[]) while ((res = recvmsg(sock_fd, &msg, 0)) > 0) { buf = (unsigned char *)NLMSG_DATA(nlh); - dbglog_parse_debug_logs(&buf[8], get_le32(&buf[4])); + dbglog_parse_debug_logs(&buf[12], get_le32(&buf[4]), get_le32(&buf[8])); } close(sock_fd); } diff --git a/tools/fwdebuglog/cld-fwlog-parser.c b/tools/fwdebuglog/cld-fwlog-parser.c index 4a916d769634..28c24a2449e9 100644 --- a/tools/fwdebuglog/cld-fwlog-parser.c +++ b/tools/fwdebuglog/cld-fwlog-parser.c @@ -185,11 +185,20 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WMI_CMD_PARAMS", "WMI_EVENT_ALLOC_FAILURE", "WMI_DBGID_DCS_PARAM_CMD", + "WMI_SEND_EVENT_WRONG_TLV", + "WMI_SEND_EVENT_NO_TLV_DEF", "WMI_DBGID_DEFNITION_END", }, { "PS_STA_DEFINITION_START", "PS_STA_PM_ARB_REQUEST", + "PS_STA_DELIVER_EVENT", + "PS_STA_PSPOLL_SEQ_DONE", + "PS_STA_COEX_MODE", + "PS_STA_PSPOLL_ALLOW", + "PS_STA_SET_PARAM", + "PS_STA_SPECPOLL_TIMER_STARTED", + "PS_STA_SPECPOLL_TIMER_STOPPED", }, { "WHAL_DBGID_DEFINITION_START", @@ -230,56 +239,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WHAL_ERROR_INTERRUPT_BB_PANIC", "WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW", "WHAL_ERROR_QCU_HW_PAUSE_MISMATCH", - "WHAL_COEX_RESET", - "WHAL_COEX_SELF_GEN_MASK", - "WHAL_ERROR_COEX_MCI_ISR", - "WHAL_COEX_MCI_ISR_IntRaw", - "WHAL_COEX_MCI_ISR_Int1Raw", - "WHAL_COEX_MCI_ISR_RxMsgRaw", - "WHAL_COEX_SENDMSG_QUEUE", - "WHAL_COEX_TX_MCI_REMOTE_RESET", - "WHAL_COEX_TX_MCI_TYPE_UNKNOWN", - "WHAL_COEX_TX_MCI_SYS_SLEEPING", - "WHAL_COEX_TX_MCI_REQ_WAKE", - "WHAL_COEX_TX_MCI_SYS_WAKING", - "WHAL_COEX_TX_MCI_LNA_TAKE", - "WHAL_COEX_TX_MCI_LNA_TRANS", - "WHAL_COEX_TX_MCI_GPM_UNKNOWN", - "WHAL_COEX_TX_MCI_GPM_WLAN_SET_ACL_INACTIVITY", - "WHAL_COEX_TX_MCI_GPM_BT_PAUSE_PROFILE", - "WHAL_COEX_TX_MCI_GPM_WLAN_PRIO", - "WHAL_COEX_TX_MCI_GPM_BT_STATUS_UPDATE", - "WHAL_COEX_TX_MCI_GPM_BT_UPDATE_FLAGS", - "WHAL_COEX_TX_MCI_GPM_VERSION_QUERY", - "WHAL_COEX_TX_MCI_GPM_VERSION_RESPONSE", - "WHAL_COEX_TX_MCI_GPM_STATUS_QUERY", - "WHAL_COEX_TX_MCI_GPM_HALT_BT_GPM", - "WHAL_COEX_TX_MCI_GPM_WLAN_CHANNELS", - "WHAL_COEX_TX_MCI_GPM_BT_PROFILE_INFO", - "WHAL_COEX_TX_MCI_GPM_BT_CAL_REQ ", - "WHAL_COEX_TX_MCI_GPM_BT_CAL_GRANT", - "WHAL_COEX_TX_MCI_GPM_BT_CAL_DONE", - "WHAL_COEX_TX_MCI_GPM_WLAN_CAL_REQ", - "WHAL_COEX_TX_MCI_GPM_WLAN_CAL_GRANT", - "WHAL_COEX_TX_MCI_GPM_WLAN_CAL_DONE", - "WHAL_COEX_TX_MCI_GPM_BT_DEBUG", - "WHAL_COEX_WHAL_MCI_RESET", - "WHAL_COEX_POLL_BT_CAL_DONE_TIMEOUT", - "WHAL_COEX_WHAL_PAUSE", - "WHAL_COEX_RX_MCI_GPM_BT_CAL_REQ", - "WHAL_COEX_RX_MCI_GPM_BT_CAL_DONE", - "WHAL_COEX_RX_MCI_GPM_BT_CAL_GRANT", - "WHAL_COEX_WLAN_CAL_START", - "WHAL_COEX_WLAN_CAL_RESULT ", - "WHAL_COEX_BtMciState", - "WHAL_COEX_BtCalState", - "WHAL_COEX_WlanCalState", - "WHAL_COEX_RxReqWakeCount", - "WHAL_COEX_RxRemoteResetCount", - "WHAL_COEX_RESTART_CAL", - "WHAL_COEX_WHAL_COEX_RESET", - "WHAL_COEX_SELF_GEN_MASK", - "WHAL_DBGID_DEFINITION_END" + "WHAL_DBGID_DEFINITION_END", }, { "COEX_DEBUGID_START", @@ -482,20 +442,61 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "COEX_PSP_STAT_2", // 197 "COEX_PSP_RX_STATUS_STATE_2", // 198 "COEX_PSP_ERROR", // 199 - "COEX_T2BT", // 200 - "COEX_BT_DURATION", // 201 - "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG", // 202 - "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG_RSP", // 203 - "COEX_TX_MCI_GPM_SCAN_OP", // 204 - "COEX_TX_MCI_GPM_BT_PAUSE_GPM_TX", // 205 - "COEX_CTS2S_SEND", // 206 - "COEX_CTS2S_RESULT", // 207 - "COEX_ENTER_OCS", // 208 - "COEX_EXIT_OCS", // 209 - "COEX_UPDATE_OCS", // 210 - "COEX_STATUS_OCS", // 211 - "COEX_STATS_BT", // 212 - "COEX_DEBUG_MESSAGE_END" + "COEX_T2BT", // 200 + "COEX_BT_DURATION", // 201 + "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG", // 202 + "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG_RSP", // 203 + "COEX_TX_MCI_GPM_SCAN_OP", // 204 + "COEX_TX_MCI_GPM_BT_PAUSE_GPM_TX", // 205 + "COEX_CTS2S_SEND", // 206 + "COEX_CTS2S_RESULT", // 207 + "COEX_ENTER_OCS", // 208 + "COEX_EXIT_OCS", // 209 + "COEX_UPDATE_OCS", // 210 + "COEX_STATUS_OCS", // 211 + "COEX_STATS_BT", // 212 + "COEX_MWS_WLAN_INIT", + "COEX_MWS_WBTMR_SYNC", + "COEX_MWS_TYPE2_RX", + "COEX_MWS_TYPE2_TX", + "COEX_MWS_WLAN_CHAVD", + "COEX_MWS_WLAN_CHAVD_INSERT", + "COEX_MWS_WLAN_CHAVD_MERGE", + "COEX_MWS_WLAN_CHAVD_RPT", + "COEX_MWS_CP_MSG_SEND", + "COEX_MWS_CP_ESCAPE", + "COEX_MWS_CP_UNFRAME", + "COEX_MWS_CP_SYNC_UPDATE", + "COEX_MWS_CP_SYNC", + "COEX_MWS_CP_WLAN_STATE_IND", + "COEX_MWS_CP_SYNCRESP_TIMEOUT", + "COEX_MWS_SCHEME_UPDATE", + "COEX_MWS_WLAN_EVENT", + "COEX_MWS_UART_UNESCAPE", + "COEX_MWS_UART_ENCODE_SEND", + "COEX_MWS_UART_RECV_DECODE", + "COEX_MWS_UL_HDL", + "COEX_MWS_REMOTE_EVENT", + "COEX_MWS_OTHER", + "COEX_MWS_ERROR", + "COEX_MWS_ANT_DIVERSITY", //237 + "COEX_P2P_GO", + "COEX_P2P_CLIENT", + "COEX_SCC_1", + "COEX_SCC_2", + "COEX_MCC_1", + "COEX_MCC_2", + "COEX_TRF_SHAPE_NOA", + "COEX_NOA_ONESHOT", + "COEX_NOA_PERIODIC", + "COEX_LE_1", + "COEX_LE_2", + "COEX_ANT_1", + "COEX_ANT_2", + "COEX_ENTER_NOA", + "COEX_EXIT_NOA", + "COEX_BT_SCAN_PROTECT", // 253 + "COEX_DEBUG_ID_END" // 254 }, { "ROAM_DBGID_DEFINITION_START", @@ -626,6 +627,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "VDEV_MGR_VDEV_PAUSE_DELAY_UPDATE", "VDEV_MGR_VDEV_PAUSE_FAIL", "VDEV_MGR_GEN_PERIODIC_NOA", + "VDEV_MGR_OFF_CHAN_GO_CH_REQ_SETUP", "VDEV_MGR_DEFINITION_END", }, { @@ -642,7 +644,16 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "SCAN_FWLOG_EVENT_RESTARTED", "SCAN_FWLOG_EVENT_COMPLETED", }, - { "" /* Rate ctrl*/ + { + "RATECTRL_DBGID_DEFINITION_START", /* Rate ctrl*/ + "RATECTRL_DBGID_ASSOC", + "RATECTRL_DBGID_NSS_CHANGE", + "RATECTRL_DBGID_CHAINMASK_ERR", + "RATECTRL_DBGID_UNEXPECTED_FRAME", + "RATECTRL_DBGID_WAL_RCQUERY", + "RATECTRL_DBGID_WAL_RCUPDATE", + "RATECTRL_DBGID_GTX_UPDATE", + "RATECTRL_DBGID_DEFINITION_END" }, { "AP_PS_DBGID_DEFINITION_START", @@ -662,6 +673,8 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "AP_PS_DBGID_UAPSD_RESPONSE", "AP_PS_DBGID_SEND_COMPLETE", "AP_PS_DBGID_SEND_N_COMPLETE", + "AP_PS_DBGID_DETECT_OUT_OF_SYNC_STA", + "AP_PS_DBGID_DELIVER_CAB", }, { "" /* Block Ack */ @@ -766,7 +779,28 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "" /* pcie lp */ }, { - "" /* RTT */ + /* RTT */ + "RTT_CALL_FLOW", + "RTT_REQ_SUB_TYPE", + "RTT_MEAS_REQ_HEAD", + "RTT_MEAS_REQ_BODY", + "", + "", + "RTT_INIT_GLOBAL_STATE", + "", + "RTT_REPORT", + "", + "RTT_ERROR_REPORT", + "RTT_TIMER_STOP", + "RTT_SEND_TM_FRAME", + "RTT_V3_RESP_CNT", + "RTT_V3_RESP_FINISH", + "RTT_CHANNEL_SWITCH_REQ", + "RTT_CHANNEL_SWITCH_GRANT", + "RTT_CHANNEL_SWITCH_COMPLETE", + "RTT_CHANNEL_SWITCH_PREEMPT", + "RTT_CHANNEL_SWITCH_STOP", + "RTT_TIMER_START", }, { /* RESOURCE */ "RESOURCE_DBGID_DEFINITION_START", @@ -787,7 +821,24 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "" }, { /* ANI */ - "" + "ANI_DBGID_POLL", + "ANI_DBGID_CONTROL", + "ANI_DBGID_OFDM_PARAMS", + "ANI_DBGID_CCK_PARAMS", + "ANI_DBGID_RESET", + "ANI_DBGID_RESTART", + "ANI_DBGID_OFDM_LEVEL", + "ANI_DBGID_CCK_LEVEL", + "ANI_DBGID_FIRSTEP", + "ANI_DBGID_CYCPWR", + "ANI_DBGID_MRC_CCK", + "ANI_DBGID_SELF_CORR_LOW", + "ANI_DBGID_ENABLE", + "ANI_DBGID_CURRENT_LEVEL", + "ANI_DBGID_POLL_PERIOD", + "ANI_DBGID_LISTEN_PERIOD", + "ANI_DBGID_OFDM_LEVEL_CFG", + "ANI_DBGID_CCK_LEVEL_CFG" }, { "P2P_DBGID_DEFINITION_START", @@ -828,6 +879,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "P2P_GO_GET_NOA_INFO", "P2P_GO_ADD_ONE_SHOT_NOA", "P2P_GO_GET_NOA_IE", + "P2P_GO_BCN_TX_COMP", "P2P_DBGID_DEFINITION_END", }, { @@ -844,6 +896,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "CSA_OFFLOAD_WMI_EVENT_ERROR", "CSA_OFFLOAD_WMI_EVENT_SENT", "CSA_OFFLOAD_WMI_CHANSWITCH_RECV", + "CSA_DBGID_DEFINITION_END", }, { /* NLO offload */ "" @@ -872,6 +925,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WOW_INIT", "WOW_RECV_MAGIC_PKT", "WOW_RECV_BITMAP_PATTERN", + "WOW_DBGID_DEFINITION_END", }, { /* WAL_VDEV */ "" @@ -884,7 +938,16 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "TP_LOCAL_SEND", }, { /* STA SMPS */ - "" + "STA_SMPS_DBGID_DEFINITION_START", + "STA_SMPS_DBGID_CREATE_PDEV_INSTANCE", + "STA_SMPS_DBGID_CREATE_VIRTUAL_CHAN_INSTANCE", + "STA_SMPS_DBGID_DELETE_VIRTUAL_CHAN_INSTANCE", + "STA_SMPS_DBGID_CREATE_STA_INSTANCE", + "STA_SMPS_DBGID_DELETE_STA_INSTANCE", + "STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_START", + "STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_STOP", + "STA_SMPS_DBGID_SEND_SMPS_ACTION_FRAME", + "SMPS_DBGID_DEFINITION_END", }, { /* SWBMISS */ "SWBMISS_DBGID_DEFINITION_START", @@ -917,6 +980,45 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "TDLS_DBGID_PEER_EVT_DISCOVER", "TDLS_DBGID_PEER_EVT_DELETE", }, + { /* HB */ + "WLAN_HB_DBGID_DEFINITION_START", + "WLAN_HB_DBGID_INIT", + "WLAN_HB_DBGID_TCP_GET_TXBUF_FAIL", + "WLAN_HB_DBGID_TCP_SEND_FAIL", + "WLAN_HB_DBGID_BSS_PEER_NULL", + "WLAN_HB_DBGID_UDP_GET_TXBUF_FAIL", + "WLAN_HB_DBGID_UDP_SEND_FAIL", + "WLAN_HB_DBGID_WMI_CMD_INVALID_PARAM", + "WLAN_HB_DBGID_WMI_CMD_INVALID_OP", + "WLAN_HB_DBGID_WOW_NOT_ENTERED", + "WLAN_HB_DBGID_ALLOC_SESS_FAIL", + "WLAN_HB_DBGID_CTX_NULL", + "WLAN_HB_DBGID_CHKSUM_ERR", + "WLAN_HB_DBGID_UDP_TX", + "WLAN_HB_DBGID_TCP_TX", + "WLAN_HB_DBGID_DEFINITION_END", + }, + { /* TXBF */ + "TXBFEE_DBGID_START", + "TXBFEE_DBGID_NDPA_RECEIVED", + "TXBFEE_DBGID_HOST_CONFIG_TXBFEE_TYPE", + "TXBFER_DBGID_SEND_NDPA", + "TXBFER_DBGID_GET_NDPA_BUF_FAIL", + "TXBFER_DBGID_SEND_NDPA_FAIL", + "TXBFER_DBGID_GET_NDP_BUF_FAIL", + "TXBFER_DBGID_SEND_NDP_FAIL", + "TXBFER_DBGID_GET_BRPOLL_BUF_FAIL", + "TXBFER_DBGID_SEND_BRPOLL_FAIL", + "TXBFER_DBGID_HOST_CONFIG_CMDID", + "TXBFEE_DBGID_HOST_CONFIG_CMDID", + "TXBFEE_DBGID_ENABLED_ENABLED_UPLOAD_H", + "TXBFEE_DBGID_UPLOADH_CV_TAG", + "TXBFEE_DBGID_UPLOADH_H_TAG", + "TXBFEE_DBGID_CAPTUREH_RECEIVED", + "TXBFEE_DBGID_PACKET_IS_STEERED", + "TXBFEE_UPLOADH_EVENT_ALLOC_MEM_FAIL", + "TXBFEE_DBGID_END", + }, }; static char * @@ -1077,8 +1179,8 @@ dbglog_print_raw_data(A_UINT32 *buffer, A_UINT32 length) } -int -dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len) +static int +dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len, u_int16_t dropped) { A_UINT32 count=0; A_UINT32 timestamp=0; @@ -1092,6 +1194,9 @@ dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len) buffer = (A_UINT32 *)datap; length = (len >> 2); + if(dropped > 0) + printf("%d log buffer got dropped in firmware \n", dropped); + while ((count + 2) < length) { timestamp = DBGLOG_GET_TIME_STAMP(buffer[count]); @@ -1385,6 +1490,24 @@ A_BOOL dbglog_ratectrl_print_handler( case RATECTRL_DBGID_WAL_RCUPDATE: dbglog_printf(timestamp, vap_id, "ratectrl_dbgid_wal_rcupdate [numelems %d ppduflag 0x%x] ", args[0], args[1]); + break; + case RATECTRL_DBGID_GTX_UPDATE: + { + switch (args[0]) { + case 255: + dbglog_printf(timestamp, vap_id, "GtxInitPwrCfg [bw[last %d|cur %d] rtcode 0x%x tpc %d tpc_init_pwr_cfg %d] ", + args[1] >> 8, args[1] & 0xff, args[2], args[3], args[4]); + break; + case 254: + dbglog_printf(timestamp, vap_id, "gtx_cfg_addr [RTMask0@0x%x PERThreshold@0x%x gtxTPCMin@0x%x userGtxMask@0x%x] ", + args[1], args[2], args[3], args[4]); + break; + default: + dbglog_printf(timestamp, vap_id, "gtx_update [act %d bw %d rix 0x%x tpc %d per %d lastrssi %d] ", + args[0], args[1], args[2], args[3], args[4], args[5]); + } + } + break; } return TRUE; } @@ -2430,7 +2553,7 @@ int main(int argc, char *argv[]) while ((res = fread(buf, RECLEN, 1, log_in)) == 1) { - dbglog_parse_debug_logs(&buf[8], get_le32(&buf[4])); + dbglog_parse_debug_logs(&buf[12], get_le32(&buf[4]), get_le32(&buf[8])); } fclose(log_in); diff --git a/tools/fwdebuglog/cld-fwlog-record.c b/tools/fwdebuglog/cld-fwlog-record.c index 28477a680d4c..138df43b3cea 100644 --- a/tools/fwdebuglog/cld-fwlog-record.c +++ b/tools/fwdebuglog/cld-fwlog-record.c @@ -56,8 +56,8 @@ static size_t capture(FILE *out_log, FILE *in_log) size_t res; while ((res = fread(buf, RECLEN, 1, in_log)) == 1) { - printf("Read record timestamp=%u length=%u\n", - get_le32(buf), get_le32(&buf[4])); + printf("Read record timestamp=%u length=%u no. fw dropped=%u\n", + get_le32(buf), get_le32(&buf[4]), get_le32(&buf[8])); fseek(out_log, record * RECLEN, SEEK_SET); if (fwrite(buf, RECLEN, res, out_log) != res) perror("fwrite"); diff --git a/tools/fwdebuglog/parser.c b/tools/fwdebuglog/parser.c index 6a68980af48f..f167c8c2a334 100644 --- a/tools/fwdebuglog/parser.c +++ b/tools/fwdebuglog/parser.c @@ -121,6 +121,8 @@ const char *dbglog_get_module_str(A_UINT32 module_id) return "STA_SMPS"; case WLAN_MODULE_TDLS: return "TDLS"; + case WLAN_MODULE_P2P: + return "P2P"; default: return "UNKNOWN"; } @@ -185,11 +187,20 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WMI_CMD_PARAMS", "WMI_EVENT_ALLOC_FAILURE", "WMI_DBGID_DCS_PARAM_CMD", + "WMI_SEND_EVENT_WRONG_TLV", + "WMI_SEND_EVENT_NO_TLV_DEF", "WMI_DBGID_DEFNITION_END", }, { "PS_STA_DEFINITION_START", "PS_STA_PM_ARB_REQUEST", + "PS_STA_DELIVER_EVENT", + "PS_STA_PSPOLL_SEQ_DONE", + "PS_STA_COEX_MODE", + "PS_STA_PSPOLL_ALLOW", + "PS_STA_SET_PARAM", + "PS_STA_SPECPOLL_TIMER_STARTED", + "PS_STA_SPECPOLL_TIMER_STOPPED", }, { "WHAL_DBGID_DEFINITION_START", @@ -230,56 +241,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WHAL_ERROR_INTERRUPT_BB_PANIC", "WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW", "WHAL_ERROR_QCU_HW_PAUSE_MISMATCH", - "WHAL_COEX_RESET", - "WHAL_COEX_SELF_GEN_MASK", - "WHAL_ERROR_COEX_MCI_ISR", - "WHAL_COEX_MCI_ISR_IntRaw", - "WHAL_COEX_MCI_ISR_Int1Raw", - "WHAL_COEX_MCI_ISR_RxMsgRaw", - "WHAL_COEX_SENDMSG_QUEUE", - "WHAL_COEX_TX_MCI_REMOTE_RESET", - "WHAL_COEX_TX_MCI_TYPE_UNKNOWN", - "WHAL_COEX_TX_MCI_SYS_SLEEPING", - "WHAL_COEX_TX_MCI_REQ_WAKE", - "WHAL_COEX_TX_MCI_SYS_WAKING", - "WHAL_COEX_TX_MCI_LNA_TAKE", - "WHAL_COEX_TX_MCI_LNA_TRANS", - "WHAL_COEX_TX_MCI_GPM_UNKNOWN", - "WHAL_COEX_TX_MCI_GPM_WLAN_SET_ACL_INACTIVITY", - "WHAL_COEX_TX_MCI_GPM_BT_PAUSE_PROFILE", - "WHAL_COEX_TX_MCI_GPM_WLAN_PRIO", - "WHAL_COEX_TX_MCI_GPM_BT_STATUS_UPDATE", - "WHAL_COEX_TX_MCI_GPM_BT_UPDATE_FLAGS", - "WHAL_COEX_TX_MCI_GPM_VERSION_QUERY", - "WHAL_COEX_TX_MCI_GPM_VERSION_RESPONSE", - "WHAL_COEX_TX_MCI_GPM_STATUS_QUERY", - "WHAL_COEX_TX_MCI_GPM_HALT_BT_GPM", - "WHAL_COEX_TX_MCI_GPM_WLAN_CHANNELS", - "WHAL_COEX_TX_MCI_GPM_BT_PROFILE_INFO", - "WHAL_COEX_TX_MCI_GPM_BT_CAL_REQ ", - "WHAL_COEX_TX_MCI_GPM_BT_CAL_GRANT", - "WHAL_COEX_TX_MCI_GPM_BT_CAL_DONE", - "WHAL_COEX_TX_MCI_GPM_WLAN_CAL_REQ", - "WHAL_COEX_TX_MCI_GPM_WLAN_CAL_GRANT", - "WHAL_COEX_TX_MCI_GPM_WLAN_CAL_DONE", - "WHAL_COEX_TX_MCI_GPM_BT_DEBUG", - "WHAL_COEX_WHAL_MCI_RESET", - "WHAL_COEX_POLL_BT_CAL_DONE_TIMEOUT", - "WHAL_COEX_WHAL_PAUSE", - "WHAL_COEX_RX_MCI_GPM_BT_CAL_REQ", - "WHAL_COEX_RX_MCI_GPM_BT_CAL_DONE", - "WHAL_COEX_RX_MCI_GPM_BT_CAL_GRANT", - "WHAL_COEX_WLAN_CAL_START", - "WHAL_COEX_WLAN_CAL_RESULT ", - "WHAL_COEX_BtMciState", - "WHAL_COEX_BtCalState", - "WHAL_COEX_WlanCalState", - "WHAL_COEX_RxReqWakeCount", - "WHAL_COEX_RxRemoteResetCount", - "WHAL_COEX_RESTART_CAL", - "WHAL_COEX_WHAL_COEX_RESET", - "WHAL_COEX_SELF_GEN_MASK", - "WHAL_DBGID_DEFINITION_END" + "WHAL_DBGID_DEFINITION_END", }, { "COEX_DEBUGID_START", @@ -482,53 +444,96 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "COEX_PSP_STAT_2", // 197 "COEX_PSP_RX_STATUS_STATE_2", // 198 "COEX_PSP_ERROR", // 199 - "COEX_T2BT", // 200 - "COEX_BT_DURATION", // 201 - "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG", // 202 - "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG_RSP", // 203 - "COEX_TX_MCI_GPM_SCAN_OP", // 204 - "COEX_TX_MCI_GPM_BT_PAUSE_GPM_TX", // 205 - "COEX_CTS2S_SEND", // 206 - "COEX_CTS2S_RESULT", // 207 - "COEX_ENTER_OCS", // 208 - "COEX_EXIT_OCS", // 209 - "COEX_UPDATE_OCS", // 210 - "COEX_STATUS_OCS", // 211 - "COEX_STATS_BT", // 212 - "COEX_DEBUG_MESSAGE_END" + "COEX_T2BT", // 200 + "COEX_BT_DURATION", // 201 + "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG", // 202 + "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG_RSP", // 203 + "COEX_TX_MCI_GPM_SCAN_OP", // 204 + "COEX_TX_MCI_GPM_BT_PAUSE_GPM_TX", // 205 + "COEX_CTS2S_SEND", // 206 + "COEX_CTS2S_RESULT", // 207 + "COEX_ENTER_OCS", // 208 + "COEX_EXIT_OCS", // 209 + "COEX_UPDATE_OCS", // 210 + "COEX_STATUS_OCS", // 211 + "COEX_STATS_BT", // 212 + "COEX_MWS_WLAN_INIT", + "COEX_MWS_WBTMR_SYNC", + "COEX_MWS_TYPE2_RX", + "COEX_MWS_TYPE2_TX", + "COEX_MWS_WLAN_CHAVD", + "COEX_MWS_WLAN_CHAVD_INSERT", + "COEX_MWS_WLAN_CHAVD_MERGE", + "COEX_MWS_WLAN_CHAVD_RPT", + "COEX_MWS_CP_MSG_SEND", + "COEX_MWS_CP_ESCAPE", + "COEX_MWS_CP_UNFRAME", + "COEX_MWS_CP_SYNC_UPDATE", + "COEX_MWS_CP_SYNC", + "COEX_MWS_CP_WLAN_STATE_IND", + "COEX_MWS_CP_SYNCRESP_TIMEOUT", + "COEX_MWS_SCHEME_UPDATE", + "COEX_MWS_WLAN_EVENT", + "COEX_MWS_UART_UNESCAPE", + "COEX_MWS_UART_ENCODE_SEND", + "COEX_MWS_UART_RECV_DECODE", + "COEX_MWS_UL_HDL", + "COEX_MWS_REMOTE_EVENT", + "COEX_MWS_OTHER", + "COEX_MWS_ERROR", + "COEX_MWS_ANT_DIVERSITY", //237 + "COEX_P2P_GO", + "COEX_P2P_CLIENT", + "COEX_SCC_1", + "COEX_SCC_2", + "COEX_MCC_1", + "COEX_MCC_2", + "COEX_TRF_SHAPE_NOA", + "COEX_NOA_ONESHOT", + "COEX_NOA_PERIODIC", + "COEX_LE_1", + "COEX_LE_2", + "COEX_ANT_1", + "COEX_ANT_2", + "COEX_ENTER_NOA", + "COEX_EXIT_NOA", + "COEX_BT_SCAN_PROTECT", // 253 + "COEX_DEBUG_ID_END" // 254 }, { - "RO_DBGID_DEFINITION_START", - "RO_REFRESH_ROAM_TABLE", - "RO_UPDATE_ROAM_CANDIDATE", - "RO_UPDATE_ROAM_CANDIDATE_CB", - "RO_UPDATE_ROAM_CANDIDATE_FINISH", - "RO_REFRESH_ROAM_TABLE_DONE", - "RO_PERIODIC_SEARCH_CB", - "RO_PERIODIC_SEARCH_TIMEOUT", - "RO_INIT", - "RO_BMISS_STATE1", - "RO_BMISS_STATE2", - "RO_SET_PERIODIC_SEARCH_ENABLE", - "RO_SET_PERIODIC_SEARCH_DISABLE", - "RO_ENABLE_SQ_THRESHOLD", - "RO_DISABLE_SQ_THRESHOLD", - "RO_ADD_BSS_TO_ROAM_TABLE", - "RO_SET_PERIODIC_SEARCH_MODE", - "RO_CONFIGURE_SQ_THRESHOLD1", - "RO_CONFIGURE_SQ_THRESHOLD2", - "RO_CONFIGURE_SQ_PARAMS", - "RO_LOW_SIGNAL_QUALITY_EVENT", - "RO_HIGH_SIGNAL_QUALITY_EVENT", - "RO_REMOVE_BSS_FROM_ROAM_TABLE", - "RO_UPDATE_CONNECTION_STATE_METRIC", - "RO_LOWRSSI_SCAN_PARAMS", - "RO_LOWRSSI_SCAN_START", - "RO_LOWRSSI_SCAN_END", - "RO_LOWRSSI_SCAN_CANCEL", - "RO_LOWRSSI_ROAM_CANCEL", - "RO_REFRESH_ROAM_CANDIDATE", - "RO_DBGID_DEFINITION_END" + "ROAM_DBGID_DEFINITION_START", + "ROAM_MODULE_INIT", + "ROAM_DEV_START", + "ROAM_CONFIG_RSSI_THRESH", + "ROAM_CONFIG_SCAN_PERIOD", + "ROAM_CONFIG_AP_PROFILE", + "ROAM_CONFIG_CHAN_LIST", + "ROAM_CONFIG_SCAN_PARAMS", + "ROAM_CONFIG_RSSI_CHANGE", + "ROAM_SCAN_TIMER_START", + "ROAM_SCAN_TIMER_EXPIRE", + "ROAM_SCAN_TIMER_STOP", + "ROAM_SCAN_STARTED", + "ROAM_SCAN_COMPLETE", + "ROAM_SCAN_CANCELLED", + "ROAM_CANDIDATE_FOUND", + "ROAM_RSSI_ACTIVE_SCAN", + "ROAM_RSSI_ACTIVE_ROAM", + "ROAM_RSSI_GOOD", + "ROAM_BMISS_FIRST_RECV", + "ROAM_DEV_STOP", + "ROAM_FW_OFFLOAD_ENABLE", + "ROAM_CANDIDATE_SSID_MATCH", + "ROAM_CANDIDATE_SECURITY_MATCH", + "ROAM_LOW_RSSI_INTERRUPT", + "ROAM_HIGH_RSSI_INTERRUPT", + "ROAM_SCAN_REQUESTED", + "ROAM_BETTER_CANDIDATE_FOUND", + "ROAM_BETTER_AP_EVENT", + "ROAM_CANCEL_LOW_PRIO_SCAN", + "ROAM_FINAL_BMISS_RECVD", + "ROAM_CONFIG_SCAN_MODE", + "ROAM_DBGID_DEFINITION_END" }, { "RESMGR_CHMGR_DEFINITION_START", @@ -537,6 +542,8 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "RESMGR_CHMGR_RESUME_COMPLETE", "RESMGR_CHMGR_VDEV_PAUSE", "RESMGR_CHMGR_VDEV_UNPAUSE", + "RESMGR_CHMGR_CTS2S_TX_COMP", + "RESMGR_CHMGR_CFEND_TX_COMP", "RESMGR_CHMGR_DEFINITION_END" }, { @@ -591,6 +598,15 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "RESMGR_VC_REG_UNREG_LINK", "RESMGR_VC_PRINT_LINK", "RESMGR_OCS_MISS_TOLERANCE", + "RESMGR_DYN_SCH_ALLOCRAM_SIZE", + "RESMGR_DYN_SCH_ENABLE", + "RESMGR_DYN_SCH_ACTIVE", + "RESMGR_DYN_SCH_CH_STATS_START", + "RESMGR_DYN_SCH_CH_SX_STATS", + "RESMGR_DYN_SCH_TOT_UTIL_PER", + "RESMGR_DYN_SCH_HOME_CH_QUOTA", + "RESMGR_OCS_REG_RECAL_QUOTA_NOTIF", + "RESMGR_OCS_DEREG_RECAL_QUOTA_NOTIF", "RESMGR_DEFINITION_END" }, { @@ -610,6 +626,10 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "VDEV_MGR_VDEV_START_OCS_HP_REQ_COMPLETE", "VDEV_MGR_VDEV_START_OCS_HP_REQ_STOP", "VDEV_MGR_HP_START_TIME", + "VDEV_MGR_VDEV_PAUSE_DELAY_UPDATE", + "VDEV_MGR_VDEV_PAUSE_FAIL", + "VDEV_MGR_GEN_PERIODIC_NOA", + "VDEV_MGR_OFF_CHAN_GO_CH_REQ_SETUP", "VDEV_MGR_DEFINITION_END", }, { @@ -626,7 +646,16 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "SCAN_FWLOG_EVENT_RESTARTED", "SCAN_FWLOG_EVENT_COMPLETED", }, - { "" /* Rate ctrl*/ + { + "RATECTRL_DBGID_DEFINITION_START", /* Rate ctrl*/ + "RATECTRL_DBGID_ASSOC", + "RATECTRL_DBGID_NSS_CHANGE", + "RATECTRL_DBGID_CHAINMASK_ERR", + "RATECTRL_DBGID_UNEXPECTED_FRAME", + "RATECTRL_DBGID_WAL_RCQUERY", + "RATECTRL_DBGID_WAL_RCUPDATE", + "RATECTRL_DBGID_GTX_UPDATE", + "RATECTRL_DBGID_DEFINITION_END" }, { "AP_PS_DBGID_DEFINITION_START", @@ -646,6 +675,8 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "AP_PS_DBGID_UAPSD_RESPONSE", "AP_PS_DBGID_SEND_COMPLETE", "AP_PS_DBGID_SEND_N_COMPLETE", + "AP_PS_DBGID_DETECT_OUT_OF_SYNC_STA", + "AP_PS_DBGID_DELIVER_CAB", }, { "" /* Block Ack */ @@ -737,6 +768,10 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WAL_DBGID_TX_MGMT_COMP_DESCID_STATUS", "WAL_DBGID_TX_DATA_COMP_MSDUID_STATUS", "WAL_DBGID_RESET_PCU_CYCLE_CNT", + "WAL_DBGID_SETUP_RSSI_INTERRUPTS", + "WAL_DBGID_BRSSI_CONFIG", + "WAL_DBGID_CURRENT_BRSSI_AVE", + "WAL_DBGID_BCN_TX_COMP", "WAL_DBGID_DEFINITION_END", }, { @@ -746,7 +781,28 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "" /* pcie lp */ }, { - "" /* RTT */ + /* RTT */ + "RTT_CALL_FLOW", + "RTT_REQ_SUB_TYPE", + "RTT_MEAS_REQ_HEAD", + "RTT_MEAS_REQ_BODY", + "", + "", + "RTT_INIT_GLOBAL_STATE", + "", + "RTT_REPORT", + "", + "RTT_ERROR_REPORT", + "RTT_TIMER_STOP", + "RTT_SEND_TM_FRAME", + "RTT_V3_RESP_CNT", + "RTT_V3_RESP_FINISH", + "RTT_CHANNEL_SWITCH_REQ", + "RTT_CHANNEL_SWITCH_GRANT", + "RTT_CHANNEL_SWITCH_COMPLETE", + "RTT_CHANNEL_SWITCH_PREEMPT", + "RTT_CHANNEL_SWITCH_STOP", + "RTT_TIMER_START", }, { /* RESOURCE */ "RESOURCE_DBGID_DEFINITION_START", @@ -767,7 +823,24 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "" }, { /* ANI */ - "" + "ANI_DBGID_POLL", + "ANI_DBGID_CONTROL", + "ANI_DBGID_OFDM_PARAMS", + "ANI_DBGID_CCK_PARAMS", + "ANI_DBGID_RESET", + "ANI_DBGID_RESTART", + "ANI_DBGID_OFDM_LEVEL", + "ANI_DBGID_CCK_LEVEL", + "ANI_DBGID_FIRSTEP", + "ANI_DBGID_CYCPWR", + "ANI_DBGID_MRC_CCK", + "ANI_DBGID_SELF_CORR_LOW", + "ANI_DBGID_ENABLE", + "ANI_DBGID_CURRENT_LEVEL", + "ANI_DBGID_POLL_PERIOD", + "ANI_DBGID_LISTEN_PERIOD", + "ANI_DBGID_OFDM_LEVEL_CFG", + "ANI_DBGID_CCK_LEVEL_CFG" }, { "P2P_DBGID_DEFINITION_START", @@ -806,6 +879,9 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "P2P_GO_NOA_NOTIF", "P2P_GO_TBTT_OFFSET", "P2P_GO_GET_NOA_INFO", + "P2P_GO_ADD_ONE_SHOT_NOA", + "P2P_GO_GET_NOA_IE", + "P2P_GO_BCN_TX_COMP", "P2P_DBGID_DEFINITION_END", }, { @@ -822,6 +898,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "CSA_OFFLOAD_WMI_EVENT_ERROR", "CSA_OFFLOAD_WMI_EVENT_SENT", "CSA_OFFLOAD_WMI_CHANSWITCH_RECV", + "CSA_DBGID_DEFINITION_END", }, { /* NLO offload */ "" @@ -834,6 +911,8 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WLAN_CHATTER_FILTER_MISS", "WLAN_CHATTER_FILTER_FULL", "WLAN_CHATTER_FILTER_TM_ADJ", + "WLAN_CHATTER_BUFFER_FULL", + "WLAN_CHATTER_TIMEOUT", "WLAN_CHATTER_DBGID_DEFINITION_END", }, { @@ -848,6 +927,7 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "WOW_INIT", "WOW_RECV_MAGIC_PKT", "WOW_RECV_BITMAP_PATTERN", + "WOW_DBGID_DEFINITION_END", }, { /* WAL_VDEV */ "" @@ -860,7 +940,16 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "TP_LOCAL_SEND", }, { /* STA SMPS */ - "" + "STA_SMPS_DBGID_DEFINITION_START", + "STA_SMPS_DBGID_CREATE_PDEV_INSTANCE", + "STA_SMPS_DBGID_CREATE_VIRTUAL_CHAN_INSTANCE", + "STA_SMPS_DBGID_DELETE_VIRTUAL_CHAN_INSTANCE", + "STA_SMPS_DBGID_CREATE_STA_INSTANCE", + "STA_SMPS_DBGID_DELETE_STA_INSTANCE", + "STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_START", + "STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_STOP", + "STA_SMPS_DBGID_SEND_SMPS_ACTION_FRAME", + "SMPS_DBGID_DEFINITION_END", }, { /* SWBMISS */ "SWBMISS_DBGID_DEFINITION_START", @@ -893,6 +982,45 @@ char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = "TDLS_DBGID_PEER_EVT_DISCOVER", "TDLS_DBGID_PEER_EVT_DELETE", }, + { /* HB */ + "WLAN_HB_DBGID_DEFINITION_START", + "WLAN_HB_DBGID_INIT", + "WLAN_HB_DBGID_TCP_GET_TXBUF_FAIL", + "WLAN_HB_DBGID_TCP_SEND_FAIL", + "WLAN_HB_DBGID_BSS_PEER_NULL", + "WLAN_HB_DBGID_UDP_GET_TXBUF_FAIL", + "WLAN_HB_DBGID_UDP_SEND_FAIL", + "WLAN_HB_DBGID_WMI_CMD_INVALID_PARAM", + "WLAN_HB_DBGID_WMI_CMD_INVALID_OP", + "WLAN_HB_DBGID_WOW_NOT_ENTERED", + "WLAN_HB_DBGID_ALLOC_SESS_FAIL", + "WLAN_HB_DBGID_CTX_NULL", + "WLAN_HB_DBGID_CHKSUM_ERR", + "WLAN_HB_DBGID_UDP_TX", + "WLAN_HB_DBGID_TCP_TX", + "WLAN_HB_DBGID_DEFINITION_END", + }, + { /* TXBF */ + "TXBFEE_DBGID_START", + "TXBFEE_DBGID_NDPA_RECEIVED", + "TXBFEE_DBGID_HOST_CONFIG_TXBFEE_TYPE", + "TXBFER_DBGID_SEND_NDPA", + "TXBFER_DBGID_GET_NDPA_BUF_FAIL", + "TXBFER_DBGID_SEND_NDPA_FAIL", + "TXBFER_DBGID_GET_NDP_BUF_FAIL", + "TXBFER_DBGID_SEND_NDP_FAIL", + "TXBFER_DBGID_GET_BRPOLL_BUF_FAIL", + "TXBFER_DBGID_SEND_BRPOLL_FAIL", + "TXBFER_DBGID_HOST_CONFIG_CMDID", + "TXBFEE_DBGID_HOST_CONFIG_CMDID", + "TXBFEE_DBGID_ENABLED_ENABLED_UPLOAD_H", + "TXBFEE_DBGID_UPLOADH_CV_TAG", + "TXBFEE_DBGID_UPLOADH_H_TAG", + "TXBFEE_DBGID_CAPTUREH_RECEIVED", + "TXBFEE_DBGID_PACKET_IS_STEERED", + "TXBFEE_UPLOADH_EVENT_ALLOC_MEM_FAIL", + "TXBFEE_DBGID_END", + }, }; static char * @@ -1041,7 +1169,7 @@ dbglog_print_raw_data(A_UINT32 *buffer, A_UINT32 length) } int -dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len) +dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len, u_int16_t dropped) { A_UINT32 count=0; A_UINT32 timestamp=0; @@ -1052,6 +1180,9 @@ dbglog_parse_debug_logs(u_int8_t *datap, u_int16_t len) A_UINT32 *buffer; A_UINT32 length = len >> 2; + if(dropped > 0) + printf("%d log buffer got dropped in firmware\n", dropped); + buffer = (A_UINT32 *)datap; length = (len >> 2); @@ -1281,6 +1412,11 @@ dbglog_sta_powersave_print_handler( { "RX_WAKE_POLICY", 0 }, { "DELAYED_PAUSE_RX_LEAK", 1 }, { "TXRX_INACTIVITY_BLOCKED_RETRY", 1 }, + { "SPEC_WAKE_INTERVAL", 1 }, + { "MAX_SPEC_NODATA_PSPOLL", 0 }, + { "ESTIMATED_PSPOLL_RESP_TIME", 1 }, + { "QPOWER_MAX_PSPOLL_BEFORE_WAKE", 0 }, + { "QPOWER_ENABLE", 0 }, }; A_UINT32 param = args[0]; A_UINT32 value = args[1]; @@ -1343,6 +1479,25 @@ A_BOOL dbglog_ratectrl_print_handler( case RATECTRL_DBGID_WAL_RCUPDATE: dbglog_printf(timestamp, vap_id, "ratectrl_dbgid_wal_rcupdate [numelems %d ppduflag 0x%x] ", args[0], args[1]); + break; + case RATECTRL_DBGID_GTX_UPDATE: + { + switch (args[0]) { + case 255: + dbglog_printf(timestamp, vap_id, "GtxInitPwrCfg [bw[last %d|cur %d] rtcode 0x%x tpc %d tpc_init_pwr_cfg %d] ", + args[1] >> 8, args[1] & 0xff, args[2], args[3], args[4]); + break; + case 254: + dbglog_printf(timestamp, vap_id, "gtx_cfg_addr [RTMask0@0x%x PERThreshold@0x%x gtxTPCMin@0x%x userGtxMask@0x%x] ", + args[1], args[2], args[3], args[4]); + break; + default: + dbglog_printf(timestamp, vap_id, "gtx_update [act %d bw %d rix 0x%x tpc %d per %d lastrssi %d] ", + args[0], args[1], args[2], args[3], args[4], args[5]); + } + } + break; + } return TRUE; } @@ -2273,6 +2428,88 @@ A_BOOL dbglog_smps_print_handler(A_UINT32 mod_id, return TRUE; } +A_BOOL +dbglog_p2p_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "ACTIVE", + "DOZE", + "TX_BCN", + "CTWIN", + "OPPPS", + }; + + static const char *events[] = { + "ONESHOT_NOA", + "CTWINDOW", + "PERIODIC_NOA", + "IDLE", + "NOA_CHANGED", + "TBTT", + "TX_BCN_CMP", + "OPPPS_OK", + "OPPPS_CHANGED", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "P2P GO PS", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL +dbglog_pcielp_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "STOP", + "TX", + "RX", + "SLEEP", + "SUSPEND", + }; + + static const char *events[] = { + "VDEV_UP", + "ALL_VDEV_DOWN", + "AWAKE", + "SLEEP", + "TX_ACTIVITY", + "TX_INACTIVITY", + "TX_AC_CHANGE", + "SUSPEND", + "RESUME", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "PCIELP", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + default: + return FALSE; + } + + return TRUE; +} + int parser_init() { /* Registering parser */ @@ -2286,6 +2523,8 @@ int parser_init() dbglog_reg_modprint(WLAN_MODULE_BEACON,dbglog_beacon_print_handler); dbglog_reg_modprint(WLAN_MODULE_DATA_TXRX,dbglog_data_txrx_print_handler); dbglog_reg_modprint(WLAN_MODULE_STA_SMPS, dbglog_smps_print_handler); + dbglog_reg_modprint(WLAN_MODULE_P2P, dbglog_p2p_print_handler); + dbglog_reg_modprint(WLAN_MODULE_PCIELP, dbglog_pcielp_print_handler); return 0; } |
