diff options
author | Srinivas Girigowda <sgirigow@codeaurora.org> | 2018-06-18 16:38:38 -0700 |
---|---|---|
committer | Srinivas Girigowda <sgirigow@codeaurora.org> | 2018-06-18 16:52:19 -0700 |
commit | f163c6090b9aa902742a7214489629ae67a55446 (patch) | |
tree | d291573ee256b26c3accc4d3cf402f8fb77073d0 | |
parent | 8c48a260cec777caf58f85316c25c3fa14a5bf60 (diff) | |
download | qcacld-f163c6090b9aa902742a7214489629ae67a55446.tar.gz |
qcacld-3.0: Release 5.3.1.1Q
1546cd7 Release 5.3.1.1Q
90fb661 qcacld-3.0: Fix invalid dereferencing of peer_id_to_obj_map for peer_ref
328a147 qcacld-3.0: OOB access may occur due to total numChannels exceeds max value
3820448 qcacld-3.0: Do not return if hdd_open_cesium_nl_sock fails during init
af391a4 qcacld-3.0: Update correct value for low power stats
c4706d2 qcacld-3.0: Add check for validity of COUNTRY driver cmd
e18a9cc Release 5.3.1.1P
aba1b5c qcacld-3.0: Check for minimum frame_len for action frames
3a1313a qcacld-3.0: Add suppport to forward GAS action frames to supplicant
14f6935 qcacld-3.0: Check for SAP restart after channel switch
569a17b qcacld-3.0: Use request manager for OCB
94b1bb4 qcacld-3.0: Pass correct channel in ch_in_pcl()
b6f35a0 qcacld-3.0: Fix OOB read in lim_process_deauth_frame
..................................
Bug: 110352942
Change-Id: Ie27e954d1cc51fc23244aec81f4fe3b0de188741
Signed-off-by: Srinivas Girigowda <sgirigow@codeaurora.org>
29 files changed, 763 insertions, 744 deletions
diff --git a/core/dp/htt/htt_fw_stats.c b/core/dp/htt/htt_fw_stats.c index a9c0a85644..966e645ebe 100644 --- a/core/dp/htt/htt_fw_stats.c +++ b/core/dp/htt/htt_fw_stats.c @@ -977,7 +977,7 @@ htt_t2h_tx_ppdu_log_print(struct ol_fw_tx_dbg_ppdu_msg_hdr *hdr, p8 = (uint8_t *) record; calculated_p8 = p8 + sizeof(struct ol_fw_tx_dbg_ppdu_base); if (calculated_p8 < p8) { - qdf_err("Overflow due to record %p", p8); + qdf_err("Overflow due to record %pK", p8); continue; } p8 = calculated_p8; diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index 247957225d..8837723556 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -506,6 +506,14 @@ static int htt_rx_ring_fill_n(struct htt_pdev_t *pdev, int num) idx = *(pdev->rx_ring.alloc_idx.vaddr); + if ((idx < 0) || (idx > pdev->rx_ring.size_mask) || + (num > pdev->rx_ring.size)) { + QDF_TRACE(QDF_MODULE_ID_HTT, + QDF_TRACE_LEVEL_ERROR, + "%s:rx refill failed!", __func__); + return filled; + } + if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled && pdev->rx_ring.smmu_map) ipa_smmu = true; diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 2db3a1ca25..a0c4b44014 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -283,33 +283,12 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg, } case HTT_T2H_MSG_TYPE_RX_ADDBA: { - uint16_t peer_id; - uint8_t tid; - uint8_t win_sz; - uint16_t start_seq_num; - - /* - * FOR NOW, the host doesn't need to know the initial - * sequence number for rx aggregation. - * Thus, any value will do - specify 0. - */ - start_seq_num = 0; - peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); - tid = HTT_RX_ADDBA_TID_GET(*msg_word); - win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); - ol_rx_addba_handler(pdev->txrx_pdev, peer_id, tid, - win_sz, start_seq_num, - 0 /* success */); + qdf_print("HTT_T2H_MSG_TYPE_RX_ADDBA not supported "); break; } case HTT_T2H_MSG_TYPE_RX_DELBA: { - uint16_t peer_id; - uint8_t tid; - - peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word); - tid = HTT_RX_DELBA_TID_GET(*msg_word); - ol_rx_delba_handler(pdev->txrx_pdev, peer_id, tid); + qdf_print("HTT_T2H_MSG_TYPE_RX_DELBA not supported "); break; } case HTT_T2H_MSG_TYPE_PEER_MAP: diff --git a/core/dp/ol/inc/ol_txrx_htt_api.h b/core/dp/ol/inc/ol_txrx_htt_api.h index c1b995978c..277569bbe5 100644 --- a/core/dp/ol/inc/ol_txrx_htt_api.h +++ b/core/dp/ol/inc/ol_txrx_htt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -502,47 +502,6 @@ ol_rx_sec_ind_handler(ol_txrx_pdev_handle pdev, enum htt_sec_type sec_type, int is_unicast, uint32_t *michael_key, uint32_t *rx_pn); -/** - * @brief Process an ADDBA message sent by the target. - * @details - * When the target notifies the host of an ADDBA event for a specified - * peer-TID, the host will set up the rx reordering state for the peer-TID. - * Specifically, the host will create a rx reordering array whose length - * is based on the window size specified in the ADDBA. - * - * @param pdev - data physical device handle - * (registered with HTT as a context pointer during attach time) - * @param peer_id - which peer the ADDBA event is for - * @param tid - which traffic ID within the peer the ADDBA event is for - * @param win_sz - how many sequence numbers are in the ARQ block ack window - * set up by the ADDBA event - * @param start_seq_num - the initial value of the sequence number during the - * block ack agreement, as specified by the ADDBA request. - * @param failed - indicate whether the target's ADDBA setup succeeded: - * 0 -> success, 1 -> fail - */ -void -ol_rx_addba_handler(ol_txrx_pdev_handle pdev, - uint16_t peer_id, - uint8_t tid, - uint8_t win_sz, uint16_t start_seq_num, uint8_t failed); - -/** - * @brief Process a DELBA message sent by the target. - * @details - * When the target notifies the host of a DELBA event for a specified - * peer-TID, the host will clean up the rx reordering state for the peer-TID. - * Specifically, the host will remove the rx reordering array, and will - * set the reorder window size to be 1 (stop and go ARQ). - * - * @param pdev - data physical device handle - * (registered with HTT as a context pointer during attach time) - * @param peer_id - which peer the ADDBA event is for - * @param tid - which traffic ID within the peer the ADDBA event is for - */ -void -ol_rx_delba_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id, uint8_t tid); - enum htt_rx_flush_action { htt_rx_flush_release, htt_rx_flush_discard, diff --git a/core/dp/txrx/ol_rx_reorder.c b/core/dp/txrx/ol_rx_reorder.c index 85be924ad4..ff6180d0e3 100644 --- a/core/dp/txrx/ol_rx_reorder.c +++ b/core/dp/txrx/ol_rx_reorder.c @@ -47,24 +47,12 @@ #include <ol_rx_defrag.h> /*=== data types and defines ===*/ -#define OL_RX_REORDER_ROUND_PWR2(value) g_log2ceil[value] + +/*---*/ /*=== global variables ===*/ -static char g_log2ceil[] = { - 1, /* 0 -> 1 */ - 1, /* 1 -> 1 */ - 2, /* 2 -> 2 */ - 4, 4, /* 3-4 -> 4 */ - 8, 8, 8, 8, /* 5-8 -> 8 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 9-16 -> 16 */ - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, /* 17-32 -> 32 */ - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, /* 33-64 -> 64 */ -}; +/*---*/ /*=== function definitions ===*/ @@ -528,91 +516,6 @@ ol_rx_reorder_peer_cleanup(struct ol_txrx_vdev_t *vdev, /* functions called by HTT */ void -ol_rx_addba_handler(ol_txrx_pdev_handle pdev, - uint16_t peer_id, - uint8_t tid, - uint8_t win_sz, uint16_t start_seq_num, uint8_t failed) -{ - uint8_t round_pwr2_win_sz; - unsigned int array_size; - struct ol_txrx_peer_t *peer; - struct ol_rx_reorder_t *rx_reorder; - - if (tid >= OL_TXRX_NUM_EXT_TIDS) { - ol_txrx_err("%s: invalid tid, %u\n", __FUNCTION__, tid); - WARN_ON(1); - return; - } - - peer = ol_txrx_peer_find_by_id(pdev, peer_id); - if (peer == NULL) - return; - - if (pdev->cfg.host_addba) { - ol_ctrl_rx_addba_complete(pdev->ctrl_pdev, - &peer->mac_addr.raw[0], tid, failed); - } - if (failed) - return; - - peer->tids_last_seq[tid] = IEEE80211_SEQ_MAX; /* invalid */ - rx_reorder = &peer->tids_rx_reorder[tid]; - - TXRX_ASSERT2(win_sz <= 64); - rx_reorder->win_sz = win_sz; - round_pwr2_win_sz = OL_RX_REORDER_ROUND_PWR2(win_sz); - array_size = - round_pwr2_win_sz * sizeof(struct ol_rx_reorder_array_elem_t); - rx_reorder->array = qdf_mem_malloc(array_size); - TXRX_ASSERT1(rx_reorder->array); - - rx_reorder->win_sz_mask = round_pwr2_win_sz - 1; - rx_reorder->num_mpdus = 0; - - peer->tids_next_rel_idx[tid] = - OL_RX_REORDER_IDX_INIT(start_seq_num, rx_reorder->win_sz, - rx_reorder->win_sz_mask); -} - -void -ol_rx_delba_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id, uint8_t tid) -{ - struct ol_txrx_peer_t *peer; - struct ol_rx_reorder_t *rx_reorder; - - if (tid >= OL_TXRX_NUM_EXT_TIDS) { - ol_txrx_err("%s: invalid tid, %u\n", __FUNCTION__, tid); - WARN_ON(1); - return; - } - - peer = ol_txrx_peer_find_by_id(pdev, peer_id); - if (peer == NULL) - return; - - peer->tids_next_rel_idx[tid] = INVALID_REORDER_INDEX; - rx_reorder = &peer->tids_rx_reorder[tid]; - - /* check that there really was a block ack agreement */ - TXRX_ASSERT1(rx_reorder->win_sz_mask != 0); - /* - * Deallocate the old rx reorder array. - * The call to ol_rx_reorder_init below - * will reset rx_reorder->array to point to - * the single-element statically-allocated reorder array - * used for non block-ack cases. - */ - if (rx_reorder->array != &rx_reorder->base) { - ol_txrx_dbg("%s, delete reorder array, tid:%d\n", - __func__, tid); - qdf_mem_free(rx_reorder->array); - } - - /* set up the TID with default parameters (ARQ window size = 1) */ - ol_rx_reorder_init(rx_reorder, tid); -} - -void ol_rx_flush_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id, uint8_t tid, diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 287bfd84dc..d02b180630 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -3522,6 +3522,9 @@ bool ol_txrx_is_peer_eligible_for_deletion(ol_txrx_peer_handle peer, for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) { peer_id = peer->peer_ids[i]; + if (peer_id == HTT_INVALID_PEER) + continue; + if (!pdev->peer_id_to_obj_map[peer_id].peer_ref) continue; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 554ab06d45..f936818f7b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -412,12 +412,6 @@ struct statsContext { unsigned int magic; }; -struct linkspeedContext { - struct completion completion; - hdd_adapter_t *pAdapter; - unsigned int magic; -}; - extern spinlock_t hdd_context_lock; extern struct mutex hdd_init_deinit_lock; @@ -425,9 +419,7 @@ extern struct mutex hdd_init_deinit_lock; #define PEER_INFO_CONTEXT_MAGIC 0x50494E46 /* PEER_INFO(PINF) */ #define POWER_CONTEXT_MAGIC 0x504F5752 /* POWR */ #define SNR_CONTEXT_MAGIC 0x534E5200 /* SNR */ -#define LINK_CONTEXT_MAGIC 0x4C494E4B /* LINKSPEED */ #define LINK_STATUS_MAGIC 0x4C4B5354 /* LINKSTATUS(LNST) */ -#define TEMP_CONTEXT_MAGIC 0x74656d70 /* TEMP (temperature) */ #define APF_CONTEXT_MAGIC 0x4575354 /* APF */ #define POWER_STATS_MAGIC 0x14111990 #define ACTION_FRAME_RANDOM_CONTEXT_MAGIC 0x87878787 @@ -1395,8 +1387,9 @@ struct hdd_adapter_s { struct net_device_stats stats; /** HDD statistics*/ hdd_stats_t hdd_stats; - /** linkspeed statistics */ - tSirLinkSpeedInfo ls_stats; + + /* estimated link speed */ + u32 estimated_linkspeed; /* SAP peer station info */ struct sir_peer_sta_info peer_sta_info; @@ -1565,14 +1558,8 @@ struct hdd_adapter_s { /* Time stamp for start RoC request */ uint64_t start_roc_ts; - /* State for synchronous OCB requests to WMI */ - struct sir_ocb_set_config_response ocb_set_config_resp; - struct sir_ocb_get_tsf_timer_response ocb_get_tsf_timer_resp; - struct sir_dcc_get_stats_response *dcc_get_stats_resp; - struct sir_dcc_update_ndl_response dcc_update_ndl_resp; - - /* MAC addresses used for OCB interfaces */ #ifdef WLAN_FEATURE_DSRC + /* MAC addresses used for OCB interfaces */ struct qdf_mac_addr ocb_mac_address[QDF_MAX_CONCURRENCY_PERSONA]; int ocb_mac_addr_count; #endif diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 7f20207947..775f76c8b7 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -374,8 +374,20 @@ extern int hdd_priv_get_data(struct iw_point *p_priv_data, extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len); -int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, - struct qdf_mac_addr mac_address); +/** + * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer + * @adapter: adapter upon which the peer is active + * @mac_address: MAC address of the peer + * @linkspeed: pointer to memory where returned link speed is to be placed + * + * This function will send a query to SME for the linkspeed of the + * given peer, and then wait for the callback to be invoked. + * + * Return: 0 if linkspeed data is available, negative errno otherwise + */ +int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter, + struct qdf_mac_addr *mac_address, + uint32_t *linkspeed); void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter); uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size, diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c index e0a65be053..adc3576e7d 100644 --- a/core/hdd/src/wlan_hdd_debugfs.c +++ b/core/hdd/src/wlan_hdd_debugfs.c @@ -602,7 +602,8 @@ static void hdd_power_debugstats_cb(struct power_stats_response *response, power_stats->cumulative_sleep_time_ms = response->cumulative_sleep_time_ms; power_stats->cumulative_total_on_time_ms - = response->cumulative_total_on_time_ms; + = response->cumulative_total_on_time_ms - + response->cumulative_sleep_time_ms; power_stats->deep_sleep_enter_counter = response->deep_sleep_enter_counter; power_stats->last_deep_sleep_enter_tstamp_ms diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index eee24657a1..d7811a8adb 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -3045,6 +3045,11 @@ static int hdd_extscan_start_fill_bucket_channel_spec( total_channels++; } + if (j != req_msg->buckets[bkt_index].numChannels) { + hdd_err("Input parameters didn't match"); + goto fail; + } + hdd_extscan_update_dwell_time_limits( req_msg, bkt_index, min_dwell_time_active_bucket, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index c2536968fb..40444746a1 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1614,6 +1614,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, tSap_StationDisassocCompleteEvent *disassoc_comp; hdd_station_info_t *stainfo; cds_context_type *cds_ctx; + hdd_adapter_t *sta_adapter; dev = (struct net_device *)usrDataForCallback; if (!dev) { @@ -1840,6 +1841,12 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, we_custom_event_generic = we_custom_start_event; cds_dump_concurrency_info(); + sta_adapter = hdd_get_adapter(pHddCtx, QDF_STA_MODE); + if (sta_adapter != NULL) { + hdd_debug("check for SAP restart"); + cds_check_concurrent_intf_and_restart_sap(sta_adapter); + } + if (cds_is_hw_mode_change_after_vdev_up()) { hdd_debug("check for possible hw mode change"); status = cds_set_hw_mode_on_channel_switch( @@ -5664,15 +5671,13 @@ int __iw_get_softap_linkspeed(struct net_device *dev, hdd_err("Invalid peer macaddress"); return -EINVAL; } - errno = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, - macAddress); - if (errno) { + rc = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, &macAddress, + &link_speed); + if (rc) { hdd_err("Unable to retrieve SME linkspeed: %d", errno); - return errno; + return rc; } - link_speed = pHostapdAdapter->ls_stats.estLinkSpeed; - /* linkspeed in units of 500 kbps */ link_speed = link_speed / 500; wrqu->data.length = len; diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 6e456eb4f7..bf521ae228 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -2973,7 +2973,26 @@ static int drv_cmd_country(hdd_adapter_t *adapter, char *country_code; int32_t cc_from_db; - country_code = command + 8; + country_code = strnchr(command, strlen(command), ' '); + /* no argument after the command*/ + if (!country_code) + return -EINVAL; + + /* no space after the command*/ + if (SPACE_ASCII_VALUE != *country_code) + return -EINVAL; + + country_code++; + + /* removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *country_code) && + ('\0' != *country_code)) + country_code++; + + /* no or less than 2 arguments followed by spaces*/ + if (*country_code == '\0' || *(country_code + 1) == '\0') + return -EINVAL; + if (!((country_code[0] == 'X' && country_code[1] == 'X') || (country_code[0] == '0' && country_code[1] == '0'))) { cc_from_db = cds_get_country_from_alpha2(country_code); diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index f35371cf2c..fe13fdeef2 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -6391,9 +6391,11 @@ static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context) if (iface_context == NULL) return; - if (hdd_validate_adapter(iface_context->adapter)) + if (hdd_validate_adapter(iface_context->adapter)) { HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Invalid adapter: 0x%pK", iface_context->adapter); + return; + } hdd_ipa_wdi_dereg_intf(iface_context->hdd_ipa, iface_context->adapter->dev->name); @@ -7200,11 +7202,13 @@ hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa, bool is_loading) qdf_list_remove_front(&hdd_ipa->pending_event, (qdf_list_node_t **)&pending_event); while (pending_event != NULL) { - if (pending_event->is_loading == is_loading) + if (pending_event->is_loading == is_loading && + !hdd_validate_adapter(pending_event->adapter)) { __hdd_ipa_wlan_evt(pending_event->adapter, pending_event->sta_id, pending_event->type, pending_event->mac_addr); + } qdf_mem_free(pending_event); pending_event = NULL; qdf_list_remove_front(&hdd_ipa->pending_event, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 91c9738d43..ace17b1c3a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -750,8 +750,7 @@ int hdd_validate_adapter(hdd_adapter_t *adapter) } if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) { - hdd_err("bad adapter magic: 0x%x (should be 0x%x)", - adapter->magic, WLAN_HDD_ADAPTER_MAGIC); + hdd_err("bad adapter magic"); return -EINVAL; } @@ -6186,10 +6185,8 @@ static int hdd_init_netlink_services(hdd_context_t *hdd_ctx) ptt_sock_activate_svc(); ret = hdd_open_cesium_nl_sock(); - if (ret) { + if (ret) hdd_err("hdd_open_cesium_nl_sock failed ret: %d", ret); - goto err_ptt_sock; - } ret = cnss_diag_activate_service(); if (ret) { @@ -6209,7 +6206,6 @@ err_cnss_diag: cnss_diag_deactivate_service(); err_close_cesium: hdd_close_cesium_nl_sock(); -err_ptt_sock: ptt_sock_deactivate_svc(); oem_deactivate_service(); err_nl_srv: diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index d3fc052271..3cc55703d8 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -36,6 +36,7 @@ #include "wlan_hdd_main.h" #include "wlan_hdd_ocb.h" #include "wlan_hdd_trace.h" +#include "wlan_hdd_request_manager.h" #include "target_if_def_config.h" #include "sch_api.h" #include "wma_api.h" @@ -50,20 +51,6 @@ /* Maximum time(ms) to wait for OCB operations */ #define WLAN_WAIT_TIME_OCB_CMD 1500 -#define HDD_OCB_MAGIC 0x489a154f - -/** - * struct hdd_ocb_ctxt - Context for OCB operations - * adapter: the ocb adapter - * completion_evt: the completion event - * status: status of the request - */ -struct hdd_ocb_ctxt { - uint32_t magic; - hdd_adapter_t *adapter; - struct completion completion_evt; - int status; -}; /** * hdd_set_dot11p_config() - Set 802.11p config flag @@ -348,6 +335,11 @@ fail: return NULL; } +struct hdd_ocb_set_config_priv { + int status; +}; + + /** * hdd_ocb_set_config_callback() - OCB set config callback function * @context_ptr: OCB call context @@ -358,47 +350,27 @@ fail: */ static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr) { - struct hdd_ocb_ctxt *context = context_ptr; - struct sir_ocb_set_config_response *resp = response_ptr; + struct hdd_request *hdd_request; + struct hdd_ocb_set_config_priv *priv; + struct sir_ocb_set_config_response *response = response_ptr; - if (!context) + hdd_request = hdd_request_get(context_ptr); + if (!hdd_request) { + hdd_err("Obsolete request"); return; + } + priv = hdd_request_priv(hdd_request); - if (resp && resp->status) - hdd_warn("Operation failed: %d", resp->status); - - spin_lock(&hdd_context_lock); - if (context->magic == HDD_OCB_MAGIC) { - hdd_adapter_t *adapter = context->adapter; + if (response && response->status) + hdd_warn("Operation failed: %d", response->status); - if (!resp) { - context->status = -EINVAL; - complete(&context->completion_evt); - spin_unlock(&hdd_context_lock); - return; - } - - context->adapter->ocb_set_config_resp = *resp; - spin_unlock(&hdd_context_lock); - if (!resp->status) { - /* - * OCB set config command successful. - * Open the TX data path - */ - if (!hdd_ocb_register_sta(adapter)) { - wlan_hdd_netif_queue_control(adapter, - WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, - WLAN_CONTROL_PATH); - } - } + if (response && (0 == response->status)) + priv->status = 0; + else + priv->status = -EINVAL; - spin_lock(&hdd_context_lock); - if (context->magic == HDD_OCB_MAGIC) - complete(&context->completion_evt); - spin_unlock(&hdd_context_lock); - } else { - spin_unlock(&hdd_context_lock); - } + hdd_request_complete(hdd_request); + hdd_request_put(hdd_request); } /** @@ -412,59 +384,70 @@ static int hdd_ocb_set_config_req(hdd_adapter_t *adapter, struct sir_ocb_config *config) { int rc; - QDF_STATUS qdf_status; - struct hdd_ocb_ctxt context = {0}; + QDF_STATUS status; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + void *cookie; + struct hdd_request *hdd_request; + struct hdd_ocb_set_config_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_OCB_CMD, + }; if (hdd_ocb_validate_config(adapter, config)) { hdd_err("The configuration is invalid"); return -EINVAL; } - init_completion(&context.completion_evt); - context.adapter = adapter; - context.magic = HDD_OCB_MAGIC; + hdd_request = hdd_request_alloc(¶ms); + if (!hdd_request) { + hdd_err("Request allocation failure"); + return -ENOMEM; + } + cookie = hdd_request_cookie(hdd_request); - hdd_info("Disabling queues"); + hdd_debug("Disabling queues"); wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH); - /* Call the SME API to set the config */ - qdf_status = sme_ocb_set_config( - ((hdd_context_t *)adapter->pHddCtx)->hHal, &context, - hdd_ocb_set_config_callback, config); - if (qdf_status != QDF_STATUS_SUCCESS) { - hdd_err("Error calling SME function."); - /* Convert from qdf_status to errno */ - return -EINVAL; + status = sme_ocb_set_config(hdd_ctx->hHal, cookie, + hdd_ocb_set_config_callback, + config); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to set channel config."); + /* Convert from eHalStatus to errno */ + rc = qdf_status_to_os_return(status); + goto end; } /* Wait for the function to complete. */ - rc = wait_for_completion_timeout(&context.completion_evt, - msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); - if (rc == 0) { - rc = -ETIMEDOUT; + rc = hdd_request_wait_for_response(hdd_request); + if (rc) { + hdd_err("Operation timed out"); goto end; } - rc = 0; - if (context.status) { - rc = context.status; + priv = hdd_request_priv(hdd_request); + rc = priv->status; + if (rc) { + hdd_err("Operation failed: %d", rc); goto end; } - if (adapter->ocb_set_config_resp.status) { - rc = -EINVAL; - goto end; - } + /* + * OCB set config command successful. + * Open the TX data path + */ + if (!hdd_ocb_register_sta(adapter)) + wlan_hdd_netif_queue_control(adapter, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); /* fall through */ end: - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); - if (rc) - hdd_err("Operation failed: %d", rc); + hdd_request_put(hdd_request); + return rc; } @@ -1314,6 +1297,11 @@ int wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, return ret; } +struct hdd_ocb_get_tsf_timer_priv { + struct sir_ocb_get_tsf_timer_response response; + int status; +}; + /** * hdd_ocb_get_tsf_timer_callback() - Callback to get TSF command * @context_ptr: request context @@ -1322,23 +1310,67 @@ int wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, static void hdd_ocb_get_tsf_timer_callback(void *context_ptr, void *response_ptr) { - struct hdd_ocb_ctxt *context = context_ptr; + struct hdd_request *hdd_request; + struct hdd_ocb_get_tsf_timer_priv *priv; struct sir_ocb_get_tsf_timer_response *response = response_ptr; - if (!context) + hdd_request = hdd_request_get(context_ptr); + if (!hdd_request) { + hdd_err("Obsolete request"); return; + } - spin_lock(&hdd_context_lock); - if (context->magic == HDD_OCB_MAGIC) { - if (response) { - context->adapter->ocb_get_tsf_timer_resp = *response; - context->status = 0; - } else { - context->status = -EINVAL; - } - complete(&context->completion_evt); + if (response) { + priv->response = *response; + priv->status = 0; + } else { + priv->status = -EINVAL; } - spin_unlock(&hdd_context_lock); + hdd_request_complete(hdd_request); + hdd_request_put(hdd_request); +} + +static int +hdd_ocb_get_tsf_timer_reply(struct wiphy *wiphy, + struct sir_ocb_get_tsf_timer_response *response) +{ + uint32_t nl_buf_len; + struct sk_buff *nl_resp; + int rc; + + /* Allocate the buffer for the response. */ + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += 2 * (NLA_HDRLEN + sizeof(uint32_t)); + nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len); + if (!nl_resp) { + hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); + return -ENOMEM; + } + + /* Populate the response. */ + rc = nla_put_u32(nl_resp, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH, + response->timer_high); + if (rc) + goto end; + rc = nla_put_u32(nl_resp, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW, + response->timer_low); + if (rc) + goto end; + + /* Send the response. */ + rc = cfg80211_vendor_cmd_reply(nl_resp); + nl_resp = NULL; + if (rc) { + hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc); + goto end; + } +end: + if (nl_resp) + kfree_skb(nl_resp); + + return rc; } /** @@ -1356,18 +1388,25 @@ __wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, const void *data, int data_len) { - struct sk_buff *nl_resp = 0; hdd_context_t *hdd_ctx = wiphy_priv(wiphy); struct net_device *dev = wdev->netdev; hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - int rc = -EINVAL; + int rc; struct sir_ocb_get_tsf_timer request = {0}; - struct hdd_ocb_ctxt context = {0}; + QDF_STATUS status; + void *cookie; + struct hdd_request *hdd_request; + struct hdd_ocb_get_tsf_timer_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_OCB_CMD, + }; ENTER_DEV(dev); - if (wlan_hdd_validate_context(hdd_ctx)) - return -EINVAL; + rc = wlan_hdd_validate_context(hdd_ctx); + if (rc) + return rc; if (adapter->device_mode != QDF_OCB_MODE) { hdd_err("Device not in OCB mode!"); @@ -1379,77 +1418,52 @@ __wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, return -EINVAL; } - /* Initialize the callback context */ - init_completion(&context.completion_evt); - context.adapter = adapter; - context.magic = HDD_OCB_MAGIC; + hdd_request = hdd_request_alloc(¶ms); + if (!hdd_request) { + hdd_err("Request allocation failure"); + return -ENOMEM; + } + cookie = hdd_request_cookie(hdd_request); request.vdev_id = adapter->sessionId; /* Call the SME function */ - rc = sme_ocb_get_tsf_timer(hdd_ctx->hHal, &context, - hdd_ocb_get_tsf_timer_callback, - &request); - if (rc) { - hdd_err("Error calling SME function"); - /* Need to convert from qdf_status to errno. */ - return -EINVAL; - } - - rc = wait_for_completion_timeout(&context.completion_evt, - msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); - if (rc == 0) { - hdd_err("Operation timed out"); - rc = -ETIMEDOUT; + status = sme_ocb_get_tsf_timer(hdd_ctx->hHal, cookie, + hdd_ocb_get_tsf_timer_callback, + &request); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to get tsf timer."); + rc = qdf_status_to_os_return(status); goto end; } - rc = 0; - if (context.status) { - hdd_err("Operation failed: %d", context.status); - rc = context.status; + rc = hdd_request_wait_for_response(hdd_request); + if (rc) { + hdd_err("Operation timed out"); goto end; } - /* Allocate the buffer for the response. */ - nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, - 2 * sizeof(uint32_t) + NLMSG_HDRLEN); - - if (!nl_resp) { - hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); - rc = -ENOMEM; + priv = hdd_request_priv(hdd_request); + rc = priv->status; + if (rc) { + hdd_err("Operation failed: %d", rc); goto end; } hdd_debug("Got TSF timer response, high=%d, low=%d", - adapter->ocb_get_tsf_timer_resp.timer_high, - adapter->ocb_get_tsf_timer_resp.timer_low); - - /* Populate the response. */ - rc = nla_put_u32(nl_resp, - QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH, - adapter->ocb_get_tsf_timer_resp.timer_high); - if (rc) - goto end; - rc = nla_put_u32(nl_resp, - QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW, - adapter->ocb_get_tsf_timer_resp.timer_low); - if (rc) - goto end; + priv->response.timer_high, + priv->response.timer_low); /* Send the response. */ - rc = cfg80211_vendor_cmd_reply(nl_resp); - nl_resp = NULL; + rc = hdd_ocb_get_tsf_timer_reply(wiphy, &priv->response); if (rc) { - hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc); + hdd_err("hdd_ocb_get_tsf_timer_reply failed: %d", rc); goto end; } + /* fall through */ end: - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); - if (nl_resp) - kfree_skb(nl_resp); + hdd_request_put(hdd_request); + return rc; } @@ -1477,6 +1491,19 @@ int wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, return ret; } +struct hdd_dcc_stats_priv { + struct sir_dcc_get_stats_response *response; + int status; +}; + +static void hdd_dcc_get_stats_dealloc(void *context_ptr) +{ + struct hdd_dcc_stats_priv *priv = context_ptr; + + qdf_mem_free(priv->response); + priv->response = NULL; +} + /** * hdd_dcc_get_stats_callback() - Callback to get stats command * @context_ptr: request context @@ -1484,46 +1511,86 @@ int wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, */ static void hdd_dcc_get_stats_callback(void *context_ptr, void *response_ptr) { - struct hdd_ocb_ctxt *context = context_ptr; + struct hdd_request *hdd_request; + struct hdd_dcc_stats_priv *priv; struct sir_dcc_get_stats_response *response = response_ptr; struct sir_dcc_get_stats_response *hdd_resp; - if (!context) + hdd_request = hdd_request_get(context_ptr); + if (!hdd_request) { + hdd_err("Obsolete request"); return; + } - spin_lock(&hdd_context_lock); - if (context->magic == HDD_OCB_MAGIC) { - if (response) { - /* - * If the response is hanging around from the previous - * request, delete it - */ - if (context->adapter->dcc_get_stats_resp) { - qdf_mem_free( - context->adapter->dcc_get_stats_resp); - } - context->adapter->dcc_get_stats_resp = - qdf_mem_malloc(sizeof( - *context->adapter->dcc_get_stats_resp) + - response->channel_stats_array_len); - if (context->adapter->dcc_get_stats_resp) { - hdd_resp = context->adapter->dcc_get_stats_resp; - *hdd_resp = *response; - hdd_resp->channel_stats_array = - (void *)hdd_resp + sizeof(*hdd_resp); - qdf_mem_copy(hdd_resp->channel_stats_array, - response->channel_stats_array, - response->channel_stats_array_len); - context->status = 0; - } else { - context->status = -ENOMEM; - } - } else { - context->status = -EINVAL; - } - complete(&context->completion_evt); + priv = hdd_request_priv(hdd_request); + if (!response) { + priv->status = -EINVAL; + goto end; } - spin_unlock(&hdd_context_lock); + + priv->response = qdf_mem_malloc(sizeof(*response) + + response->channel_stats_array_len); + if (!priv->response) { + priv->status = -ENOMEM; + goto end; + } + + hdd_resp = priv->response; + *hdd_resp = *response; + hdd_resp->channel_stats_array = (void *)hdd_resp + sizeof(*hdd_resp); + qdf_mem_copy(hdd_resp->channel_stats_array, + response->channel_stats_array, + response->channel_stats_array_len); + priv->status = 0; + +end: + hdd_request_complete(hdd_request); + hdd_request_put(hdd_request); +} + +static int +hdd_dcc_get_stats_send_reply(struct wiphy *wiphy, + struct sir_dcc_get_stats_response *response) +{ + uint32_t nl_buf_len; + struct sk_buff *nl_resp; + int rc; + + /* Allocate the buffer for the response. */ + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += NLA_HDRLEN + sizeof(uint32_t); + nl_buf_len += NLA_HDRLEN + response->channel_stats_array_len; + nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len); + if (!nl_resp) { + hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); + return -ENOMEM; + } + + /* Populate the response. */ + rc = nla_put_u32(nl_resp, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT, + response->num_channels); + if (rc) + goto end; + rc = nla_put(nl_resp, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY, + response->channel_stats_array_len, + response->channel_stats_array); + if (rc) + goto end; + + /* Send the response. */ + rc = cfg80211_vendor_cmd_reply(nl_resp); + nl_resp = NULL; + if (rc) { + hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc); + goto end; + } +end: + if (nl_resp) + kfree_skb(nl_resp); + + return rc; } /** @@ -1547,15 +1614,23 @@ static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, struct net_device *dev = wdev->netdev; hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX + 1]; - struct sk_buff *nl_resp = 0; - int rc = -EINVAL; + int rc; struct sir_dcc_get_stats request = {0}; - struct hdd_ocb_ctxt context = {0}; + QDF_STATUS status; + void *cookie; + struct hdd_request *hdd_request; + struct hdd_dcc_stats_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_OCB_CMD, + .dealloc = hdd_dcc_get_stats_dealloc, + }; ENTER_DEV(dev); - if (wlan_hdd_validate_context(hdd_ctx)) - return -EINVAL; + rc = wlan_hdd_validate_context(hdd_ctx); + if (rc) + return rc; if (adapter->device_mode != QDF_OCB_MODE) { hdd_err("Device not in OCB mode!"); @@ -1588,10 +1663,12 @@ static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, request_array = nla_data( tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]); - /* Initialize the callback context */ - init_completion(&context.completion_evt); - context.adapter = adapter; - context.magic = HDD_OCB_MAGIC; + hdd_request = hdd_request_alloc(¶ms); + if (!hdd_request) { + hdd_err("Request allocation failure"); + return -ENOMEM; + } + cookie = hdd_request_cookie(hdd_request); request.vdev_id = adapter->sessionId; request.channel_count = channel_count; @@ -1599,76 +1676,40 @@ static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, request.request_array = request_array; /* Call the SME function. */ - rc = sme_dcc_get_stats(hdd_ctx->hHal, &context, - hdd_dcc_get_stats_callback, - &request); - if (rc) { - hdd_err("Error calling SME function"); - /* Need to convert from qdf_status to errno. */ - return -EINVAL; - } - - /* Wait for the function to complete. */ - rc = wait_for_completion_timeout(&context.completion_evt, - msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); - if (rc == 0) { - hdd_err("Operation failed: %d", rc); - rc = -ETIMEDOUT; - goto end; - } - - if (context.status) { - hdd_err("There was error: %d", context.status); - rc = context.status; + status = sme_dcc_get_stats(hdd_ctx->hHal, cookie, + hdd_dcc_get_stats_callback, + &request); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Error calling SME function."); + rc = qdf_status_to_os_return(status); goto end; } - if (!adapter->dcc_get_stats_resp) { - hdd_err("The response was NULL"); - rc = -EINVAL; + /* Wait for the function to complete. */ + rc = hdd_request_wait_for_response(hdd_request); + if (rc) { + hdd_err("Operation timed out"); goto end; } - /* Allocate the buffer for the response. */ - nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(uint32_t) + - adapter->dcc_get_stats_resp->channel_stats_array_len + - NLMSG_HDRLEN); - if (!nl_resp) { - hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); - rc = -ENOMEM; + priv = hdd_request_priv(hdd_request); + rc = priv->status; + if (rc) { + hdd_err("Operation failed: %d", rc); goto end; } - /* Populate the response. */ - rc = nla_put_u32(nl_resp, - QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT, - adapter->dcc_get_stats_resp->num_channels); - if (rc) - goto end; - rc = nla_put(nl_resp, - QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY, - adapter->dcc_get_stats_resp->channel_stats_array_len, - adapter->dcc_get_stats_resp->channel_stats_array); - if (rc) - goto end; - /* Send the response. */ - rc = cfg80211_vendor_cmd_reply(nl_resp); - nl_resp = NULL; + rc = hdd_dcc_get_stats_send_reply(wiphy, priv->response); if (rc) { - hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc); + hdd_err("hdd_dcc_get_stats_send_reply failed: %d", rc); goto end; } /* fall through */ end: - spin_lock(&hdd_context_lock); - context.magic = 0; - qdf_mem_free(adapter->dcc_get_stats_resp); - adapter->dcc_get_stats_resp = NULL; - spin_unlock(&hdd_context_lock); - if (nl_resp) - kfree_skb(nl_resp); + hdd_request_put(hdd_request); + return rc; } @@ -1779,6 +1820,10 @@ int wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy, return ret; } +struct hdd_dcc_update_ndl_priv { + int status; +}; + /** * hdd_dcc_update_ndl_callback() - Callback to update NDL command * @context_ptr: request context @@ -1786,23 +1831,22 @@ int wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy, */ static void hdd_dcc_update_ndl_callback(void *context_ptr, void *response_ptr) { - struct hdd_ocb_ctxt *context = context_ptr; + struct hdd_request *hdd_request; + struct hdd_dcc_update_ndl_priv *priv; struct sir_dcc_update_ndl_response *response = response_ptr; - if (!context) + hdd_request = hdd_request_get(context_ptr); + if (!hdd_request) { + hdd_err("Obsolete request"); return; - - spin_lock(&hdd_context_lock); - if (context->magic == HDD_OCB_MAGIC) { - if (response) { - context->adapter->dcc_update_ndl_resp = *response; - context->status = 0; - } else { - context->status = -EINVAL; - } - complete(&context->completion_evt); } - spin_unlock(&hdd_context_lock); + priv = hdd_request_priv(hdd_request); + if (response && (0 == response->status)) + priv->status = 0; + else + priv->status = -EINVAL; + hdd_request_complete(hdd_request); + hdd_request_put(hdd_request); } /** @@ -1829,17 +1873,25 @@ static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, void *ndl_channel_array; uint32_t ndl_active_state_array_len; void *ndl_active_state_array; - int rc = -EINVAL; - struct hdd_ocb_ctxt context = {0}; + int rc; + QDF_STATUS status; + void *cookie; + struct hdd_request *hdd_request; + struct hdd_dcc_update_ndl_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_OCB_CMD, + }; ENTER_DEV(dev); - if (wlan_hdd_validate_context(hdd_ctx)) - goto end; + rc = wlan_hdd_validate_context(hdd_ctx); + if (rc) + return rc; if (adapter->device_mode != QDF_OCB_MODE) { hdd_err("Device not in OCB mode!"); - goto end; + return -EINVAL; } if (!wma_is_vdev_up(adapter->sessionId)) { @@ -1851,7 +1903,7 @@ static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, if (hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX, data, data_len, qca_wlan_vendor_dcc_update_ndl)) { hdd_err("Invalid ATTR"); - goto end; + return -EINVAL; } /* Verify that the parameter is present */ @@ -1873,10 +1925,12 @@ static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, ndl_active_state_array = nla_data( tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]); - /* Initialize the callback context */ - init_completion(&context.completion_evt); - context.adapter = adapter; - context.magic = HDD_OCB_MAGIC; + hdd_request = hdd_request_alloc(¶ms); + if (!hdd_request) { + hdd_err("Request allocation failure"); + return -ENOMEM; + } + cookie = hdd_request_cookie(hdd_request); /* Copy the parameters to the request structure. */ request.vdev_id = adapter->sessionId; @@ -1887,43 +1941,33 @@ static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, request.dcc_ndl_active_state_list = ndl_active_state_array; /* Call the SME function */ - rc = sme_dcc_update_ndl(hdd_ctx->hHal, &context, - hdd_dcc_update_ndl_callback, - &request); - if (rc) { + status = sme_dcc_update_ndl(hdd_ctx->hHal, cookie, + hdd_dcc_update_ndl_callback, + &request); + if (QDF_IS_STATUS_ERROR(status)) { hdd_err("Error calling SME function."); - /* Convert from qdf_status to errno */ - return -EINVAL; + rc = qdf_status_to_os_return(status); + goto end; } /* Wait for the function to complete. */ - rc = wait_for_completion_timeout(&context.completion_evt, - msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); - if (rc == 0) { + rc = hdd_request_wait_for_response(hdd_request); + if (rc) { hdd_err("Operation timed out"); - rc = -ETIMEDOUT; - goto end; - } - rc = 0; - - if (context.status) { - hdd_err("Operation failed: %d", context.status); - rc = context.status; goto end; } - if (adapter->dcc_update_ndl_resp.status) { - hdd_err("Operation returned: %d", - adapter->dcc_update_ndl_resp.status); - rc = -EINVAL; + priv = hdd_request_priv(hdd_request); + rc = priv->status; + if (rc) { + hdd_err("Operation failed: %d", rc); goto end; } /* fall through */ end: - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + hdd_request_put(hdd_request); + return rc; } diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 41c3577593..8b7fe10eae 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -95,6 +95,10 @@ struct nla_policy scan_policy[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE] = {.type = NLA_U64}, [QCA_WLAN_VENDOR_ATTR_SCAN_IE] = {.type = NLA_BINARY, .len = MAX_DEFAULT_SCAN_IE_LEN}, + [QCA_WLAN_VENDOR_ATTR_SCAN_MAC] = {.type = NLA_UNSPEC, + .len = QDF_MAC_ADDR_SIZE}, + [QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK] = {.type = NLA_UNSPEC, + .len = QDF_MAC_ADDR_SIZE}, }; /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 2dbb292176..d177e7b61f 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -52,6 +52,7 @@ #include <wlan_hdd_wmm.h> #include "utils_api.h" #include "wlan_hdd_p2p.h" +#include "wlan_hdd_request_manager.h" #ifdef FEATURE_WLAN_TDLS #include "wlan_hdd_tdls.h" #endif @@ -3694,139 +3695,92 @@ QDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr) return QDF_STATUS_SUCCESS; } -/** - * hdd_get_link_speed_cb() - Get link speed callback function - * @pLinkSpeed: pointer to the link speed record - * @pContext: pointer to the user context passed to SME - * - * This function is passed as the callback function to - * sme_get_link_speed() by wlan_hdd_get_linkspeed_for_peermac(). By - * agreement a &struct linkspeedContext is passed as @pContext. If - * the context is valid, then the contents of @pLinkSpeed are copied - * into the adapter record referenced by @pContext where they can be - * subsequently retrieved. If the context is invalid, then this - * function does nothing since it is assumed the caller has already - * timed-out and destroyed the context. - * - * Return: None. - */ +struct linkspeed_priv { + tSirLinkSpeedInfo linkspeed_info; +}; + static void -hdd_get_link_speed_cb(tSirLinkSpeedInfo *pLinkSpeed, void *pContext) +hdd_get_link_speed_cb(tSirLinkSpeedInfo *linkspeed_info, void *context) { - struct linkspeedContext *pLinkSpeedContext; - hdd_adapter_t *pAdapter; + struct hdd_request *request; + struct linkspeed_priv *priv; - if ((NULL == pLinkSpeed) || (NULL == pContext)) { - hdd_err("Bad param, pLinkSpeed [%pK] pContext [%pK]", - pLinkSpeed, pContext); + if (!linkspeed_info) { + hdd_err("NULL linkspeed"); return; } - spin_lock(&hdd_context_lock); - pLinkSpeedContext = pContext; - pAdapter = pLinkSpeedContext->pAdapter; - /* 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 use a spinlock to - * serialize these actions - */ - - if ((NULL == pAdapter) || - (LINK_CONTEXT_MAGIC != pLinkSpeedContext->magic)) { - /* the caller presumably timed out so there is nothing - * we can do - */ - spin_unlock(&hdd_context_lock); - hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]", - pAdapter, pLinkSpeedContext->magic); + request = hdd_request_get(context); + if (!request) { + hdd_err("Obsolete request"); return; } - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pLinkSpeedContext->magic = 0; - - /* copy over the stats. do so as a struct copy */ - pAdapter->ls_stats = *pLinkSpeed; - - /* notify the caller */ - complete(&pLinkSpeedContext->completion); - - /* serialization is complete */ - spin_unlock(&hdd_context_lock); + priv = hdd_request_priv(request); + priv->linkspeed_info = *linkspeed_info; + hdd_request_complete(request); + hdd_request_put(request); } -/** - * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer - * @pAdapter: adapter upon which the peer is active - * @macAddress: MAC address of the peer - * - * This function will send a query to SME for the linkspeed of the - * given peer, and then wait for the callback to be invoked. - * - * Return: Errno - */ -int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, - struct qdf_mac_addr macAddress) +int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter, + struct qdf_mac_addr *mac_address, + uint32_t *linkspeed) { + int ret; QDF_STATUS status; - int errno; - unsigned long rc; - static struct linkspeedContext context; - tSirLinkSpeedInfo *linkspeed_req; + void *cookie; + tSirLinkSpeedInfo *linkspeed_info; + struct hdd_request *request; + struct linkspeed_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; - if (NULL == pAdapter) { - hdd_err("pAdapter is NULL"); + if ((!adapter) || (!linkspeed)) { + hdd_err("NULL argument"); return -EINVAL; } - linkspeed_req = qdf_mem_malloc(sizeof(*linkspeed_req)); - if (NULL == linkspeed_req) { - hdd_err("Request Buffer Alloc Fail"); - return -ENOMEM; + request = hdd_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); + ret = -ENOMEM; + goto return_cached_value; } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = LINK_CONTEXT_MAGIC; + cookie = hdd_request_cookie(request); + priv = hdd_request_priv(request); - qdf_copy_macaddr(&linkspeed_req->peer_macaddr, &macAddress); - status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(pAdapter), - linkspeed_req, - &context, hdd_get_link_speed_cb); - qdf_mem_free(linkspeed_req); - errno = qdf_status_to_os_return(status); - if (errno) { + linkspeed_info = &priv->linkspeed_info; + qdf_copy_macaddr(&linkspeed_info->peer_macaddr, mac_address); + status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(adapter), + linkspeed_info, + cookie, hdd_get_link_speed_cb); + if (QDF_IS_STATUS_ERROR(status)) { hdd_err("Unable to retrieve statistics for link speed"); - } else { - rc = wait_for_completion_timeout - (&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (!rc) { - hdd_err("SME timed out while retrieving link speed"); - errno = -ETIMEDOUT; - } - } - - /* either we never sent a request, we sent a request and - * received a response or we sent a request and timed out. if - * we never sent a request or if we sent a request and got a - * response, we want to clear the magic out of paranoia. if - * we timed out 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 had not yet set the - * completion variable when a timeout occurred. we serialize - * these activities by invalidating the magic while holding a - * shared spinlock which will cause us to block if the - * callback is currently executing + ret = qdf_status_to_os_return(status); + goto cleanup; + } + ret = hdd_request_wait_for_response(request); + if (ret) { + hdd_err("SME timed out while retrieving link speed"); + goto cleanup; + } + adapter->estimated_linkspeed = linkspeed_info->estLinkSpeed; + +cleanup: + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * regardless we are done with the request. */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + hdd_request_put(request); - return errno; +return_cached_value: + *linkspeed = adapter->estimated_linkspeed; + + return ret; } /** @@ -3867,12 +3821,12 @@ int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed) qdf_copy_macaddr(&bssid, &hdd_stactx->conn_info.bssId); - errno = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid); + errno = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, &bssid, + link_speed); if (errno) { hdd_err("Unable to retrieve SME linkspeed: %d", errno); return errno; } - *link_speed = sta_adapter->ls_stats.estLinkSpeed; /* linkspeed in units of 500 kbps */ *link_speed = (*link_speed) / 500; } @@ -4888,7 +4842,8 @@ static int __iw_set_bitrate(struct net_device *dev, 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); - uint8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; + uint8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN + + WNI_CFG_SUPPORTED_RATES_11B_LEN]; uint32_t a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; uint32_t b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; uint32_t i, rate; @@ -4924,7 +4879,8 @@ static int __iw_set_bitrate(struct net_device *dev, &a_len) == QDF_STATUS_SUCCESS) && (sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter), - WNI_CFG_SUPPORTED_RATES_11B, supp_rates, + WNI_CFG_SUPPORTED_RATES_11B, + supp_rates + a_len, &b_len) == QDF_STATUS_SUCCESS)) { for (i = 0; i < (b_len + a_len); ++i) { /* supported rates returned is double @@ -7304,10 +7260,14 @@ free: return retval; } +struct temperature_priv { + int temperature; +}; + /** * hdd_get_temperature_cb() - "Get Temperature" callback function * @temperature: measured temperature - * @pContext: callback context + * @context: callback context * * This function is passed to sme_get_temperature() as the callback * function to be invoked when the temperature measurement is @@ -7315,30 +7275,24 @@ free: * * Return: None */ -static void hdd_get_temperature_cb(int temperature, void *pContext) +static void hdd_get_temperature_cb(int temperature, void *context) { - struct statsContext *pTempContext; - hdd_adapter_t *pAdapter; + struct hdd_request *request; + struct temperature_priv *priv; ENTER(); - if (NULL == pContext) { - hdd_err("pContext is NULL"); - return; - } - pTempContext = pContext; - pAdapter = pTempContext->pAdapter; - spin_lock(&hdd_context_lock); - if ((NULL == pAdapter) || (TEMP_CONTEXT_MAGIC != pTempContext->magic)) { - spin_unlock(&hdd_context_lock); - hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]", - pAdapter, pTempContext->magic); + + request = hdd_request_get(context); + if (!request) { + hdd_err("Obsolete request"); return; } - if (temperature != 0) - pAdapter->temperature = temperature; - complete(&pTempContext->completion); - spin_unlock(&hdd_context_lock); + priv = hdd_request_priv(request); + priv->temperature = temperature; + hdd_request_complete(request); + hdd_request_put(request); + EXIT(); } @@ -7351,35 +7305,54 @@ static void hdd_get_temperature_cb(int temperature, void *pContext) * returned, otherwise a negative errno is returned. * */ -int wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, int *temperature) +int wlan_hdd_get_temperature(hdd_adapter_t *p_adapter, int *temperature) { QDF_STATUS status; - static struct statsContext tempContext; - unsigned long rc; + int ret; + void *cookie; + struct hdd_request *request; + struct temperature_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; ENTER(); - if (NULL == pAdapter) { + if (!p_adapter) { hdd_err("pAdapter is NULL"); return -EPERM; } - init_completion(&tempContext.completion); - tempContext.pAdapter = pAdapter; - tempContext.magic = TEMP_CONTEXT_MAGIC; - status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(pAdapter), - &tempContext, hdd_get_temperature_cb); + + request = hdd_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); + return -ENOMEM; + } + cookie = hdd_request_cookie(request); + status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(p_adapter), + cookie, hdd_get_temperature_cb); if (QDF_STATUS_SUCCESS != status) { hdd_err("Unable to retrieve temperature"); } else { - rc = wait_for_completion_timeout(&tempContext.completion, - msecs_to_jiffies - (WLAN_WAIT_TIME_STATS)); - if (!rc) + ret = hdd_request_wait_for_response(request); + if (ret) { hdd_err("SME timed out while retrieving temperature"); + } else { + /* update the adapter with the fresh results */ + priv = hdd_request_priv(request); + if (priv->temperature) + p_adapter->temperature = priv->temperature; + } } - spin_lock(&hdd_context_lock); - tempContext.magic = 0; - spin_unlock(&hdd_context_lock); - *temperature = pAdapter->temperature; + + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * regardless we are done with the request. + */ + hdd_request_put(request); + + *temperature = p_adapter->temperature; EXIT(); return 0; } @@ -11523,6 +11496,38 @@ int wlan_hdd_set_filter(hdd_context_t *hdd_ctx, } /** + * validate_packet_filter_params_size() - Validate the size of the params rcvd + * @priv_data: Pointer to the priv data from user space + * @request: Pointer to the struct containing the copied data from user space + * + * Return: False on invalid length, true otherwise + */ +static bool validate_packet_filter_params_size(struct pkt_filter_cfg *request, + uint16_t length) +{ + int max_params_size, rcvd_params_size; + + max_params_size = HDD_MAX_CMP_PER_PACKET_FILTER * + sizeof(struct pkt_filter_param_cfg); + + if (length < sizeof(struct pkt_filter_cfg) - max_params_size) { + hdd_err("Less than minimum number of arguments needed"); + return false; + } + + rcvd_params_size = request->num_params * + sizeof(struct pkt_filter_param_cfg); + + if (length != sizeof(struct pkt_filter_cfg) - + max_params_size + rcvd_params_size) { + hdd_err("Arguments do not match the number of params provided"); + return false; + } + + return true; +} + +/** * __iw_set_packet_filter_params() - set packet filter parameters in target * @dev: Pointer to netdev * @info: Pointer to iw request info @@ -11558,8 +11563,7 @@ static int __iw_set_packet_filter_params(struct net_device *dev, return -EINVAL; } - if ((NULL == priv_data.pointer) || (0 == priv_data.length) || - priv_data.length < sizeof(struct pkt_filter_cfg)) { + if ((NULL == priv_data.pointer) || (0 == priv_data.length)) { hdd_err("invalid priv data %pK or invalid priv data length %d", priv_data.pointer, priv_data.length); return -EINVAL; @@ -11579,11 +11583,18 @@ static int __iw_set_packet_filter_params(struct net_device *dev, /* copy data using copy_from_user */ request = mem_alloc_copy_from_user_helper(priv_data.pointer, priv_data.length); + if (NULL == request) { hdd_err("mem_alloc_copy_from_user_helper fail"); return -ENOMEM; } + if (!validate_packet_filter_params_size(request, priv_data.length)) { + hdd_err("Invalid priv data length %d", priv_data.length); + qdf_mem_free(request); + return -EINVAL; + } + if (request->filter_action == HDD_RCV_FILTER_SET) hdd_ctx->user_configured_pkt_filter_rules |= 1 << request->filter_id; diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 3c191f71af..b4b97af4f1 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -41,9 +41,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 3 #define QWLAN_VERSION_PATCH 1 -#define QWLAN_VERSION_EXTRA "O" +#define QWLAN_VERSION_EXTRA "Q" #define QWLAN_VERSION_BUILD 1 -#define QWLAN_VERSIONSTR "5.3.1.1O" +#define QWLAN_VERSIONSTR "5.3.1.1Q" #endif /* QWLAN_VERSION_H */ diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 2795e8b11c..ddc7bc201e 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -217,6 +217,11 @@ #define SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID 4 #define SIR_MAC_ACTION_MEASUREMENT_PILOT 7 +/* Public Action frames for GAS */ +#define SIR_MAC_ACTION_GAS_INITIAL_REQUEST 0x0A +#define SIR_MAC_ACTION_GAS_INITIAL_RESPONSE 0x0B +#define SIR_MAC_ACTION_GAS_COMEBACK_REQUEST 0x0C +#define SIR_MAC_ACTION_GAS_COMEBACK_RESPONSE 0x0D #ifdef WLAN_FEATURE_11W /* 11w SA query request/response action frame category code */ diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 67f9a877ef..bdaa51564e 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1656,7 +1656,7 @@ static void lim_process_action_vendor_specific(tpAniSirGlobal mac_ctx, mac_hdr = WMA_GET_RX_MAC_HEADER(pkt_info); frame_len = WMA_GET_RX_PAYLOAD_LEN(pkt_info); - if (frame_len < sizeof(action_hdr)) { + if (frame_len < sizeof(*action_hdr)) { pe_debug("Received action frame of invalid len %d", frame_len); return; } @@ -1705,11 +1705,17 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, #endif tpSirMacMgmtHdr mac_hdr = NULL; int8_t rssi; - uint32_t frame_len; + uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); tpSirMacVendorSpecificFrameHdr vendor_specific; uint8_t oui[] = { 0x00, 0x00, 0xf0 }; tpSirMacVendorSpecificPublicActionFrameHdr pub_action; + if (frame_len < sizeof(*action_hdr)) { + pe_debug("frame_len %d less than Action Frame Hdr size", + frame_len); + return; + } + #ifdef WLAN_FEATURE_11W if (lim_is_robust_mgmt_action_frame(action_hdr->category) && lim_drop_unprotected_action_frame(mac_ctx, session, @@ -1717,8 +1723,6 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, return; #endif - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); - switch (action_hdr->category) { case SIR_MAC_ACTION_QOS_MGMT: if ((session->limQosEnabled) || @@ -1911,10 +1915,14 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY: vendor_specific = (tpSirMacVendorSpecificFrameHdr) action_hdr; mac_hdr = NULL; - frame_len = 0; mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + if (frame_len < sizeof(*vendor_specific)) { + pe_debug("frame len %d less than Vendor Specific Hdr len", + frame_len); + return; + } /* Check if it is a vendor specific action frame. */ if (LIM_IS_STA_ROLE(session) && @@ -1950,7 +1958,12 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, } break; case SIR_MAC_ACTION_PUBLIC_USAGE: + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); switch (action_hdr->actionID) { + case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID: + lim_process_ext_channel_switch_action_frame(mac_ctx, + rx_pkt_info, session); + break; case SIR_MAC_ACTION_VENDOR_SPECIFIC: pub_action = (tpSirMacVendorSpecificPublicActionFrameHdr) @@ -1959,58 +1972,30 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, lim_process_action_vendor_specific(mac_ctx, rx_pkt_info, pub_action, session); break; - /* Handle vendor specific action */ case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY: - { - tpSirMacMgmtHdr header; - uint32_t frame_len; - - header = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); - lim_send_sme_mgmt_frame_ind(mac_ctx, header->fc.subType, - (uint8_t *)header, frame_len + sizeof(tSirMacMgmtHdr), 0, - WMA_GET_RX_CH(rx_pkt_info), NULL, - WMA_GET_RX_RSSI_RAW(rx_pkt_info)); - break; - } - case SIR_MAC_ACTION_2040_BSS_COEXISTENCE: - mac_hdr = NULL; - frame_len = 0; - - mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); - - lim_send_sme_mgmt_frame_ind(mac_ctx, - mac_hdr->fc.subType, - (uint8_t *) mac_hdr, - frame_len + sizeof(tSirMacMgmtHdr), - session->smeSessionId, - WMA_GET_RX_CH(rx_pkt_info), session, - WMA_GET_RX_RSSI_NORMALIZED( - rx_pkt_info)); - break; + case SIR_MAC_ACTION_GAS_INITIAL_REQUEST: + case SIR_MAC_ACTION_GAS_INITIAL_RESPONSE: + case SIR_MAC_ACTION_GAS_COMEBACK_REQUEST: + case SIR_MAC_ACTION_GAS_COMEBACK_RESPONSE: #ifdef FEATURE_WLAN_TDLS case SIR_MAC_TDLS_DIS_RSP: - mac_hdr = NULL; - frame_len = 0; - - mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); - rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); - pe_debug("Public Action TDLS Discovery RSP"); +#endif + /* + * Frame forwarded to SME to HDD to supplicant + * type is action + */ + pe_debug("Public Action Frame %d received", + action_hdr->actionID); lim_send_sme_mgmt_frame_ind(mac_ctx, - mac_hdr->fc.subType, (uint8_t *) mac_hdr, + mac_hdr->fc.subType, + (uint8_t *) mac_hdr, frame_len + sizeof(tSirMacMgmtHdr), session->smeSessionId, WMA_GET_RX_CH(rx_pkt_info), session, WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)); break; -#endif - case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID: - lim_process_ext_channel_switch_action_frame(mac_ctx, - rx_pkt_info, session); - break; + default: pe_warn("Unhandled public action frame: %x", action_hdr->actionID); @@ -2062,10 +2047,8 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, break; case SIR_MAC_ACTION_FST: { tpSirMacMgmtHdr hdr; - uint32_t frame_len; hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); pe_debug("Received FST MGMT action frame"); /* Forward to the SME to HDD */ @@ -2088,7 +2071,6 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, case SIR_MAC_PDPA_GAS_COMEBACK_REQ: case SIR_MAC_PDPA_GAS_COMEBACK_RSP: mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType, (uint8_t *) mac_hdr, @@ -2130,31 +2112,58 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) { + tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(pBd); + uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(pBd); uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd); - tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr = - (tpSirMacVendorSpecificPublicActionFrameHdr) pBody; + tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) pBody; + tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific; pe_debug("Received a Action frame -- no session"); - switch (pActionHdr->category) { + if (frame_len < sizeof(*action_hdr)) { + pe_debug("frame_len %d less than action frame header len", + frame_len); + return; + } + + switch (action_hdr->category) { case SIR_MAC_ACTION_PUBLIC_USAGE: - switch (pActionHdr->actionID) { + switch (action_hdr->actionID) { case SIR_MAC_ACTION_VENDOR_SPECIFIC: - { + vendor_specific = + (tpSirMacVendorSpecificPublicActionFrameHdr) + action_hdr; lim_process_action_vendor_specific(pMac, pBd, - pActionHdr, NULL); - } + vendor_specific, + NULL); + break; + case SIR_MAC_ACTION_GAS_INITIAL_REQUEST: + case SIR_MAC_ACTION_GAS_INITIAL_RESPONSE: + case SIR_MAC_ACTION_GAS_COMEBACK_REQUEST: + case SIR_MAC_ACTION_GAS_COMEBACK_RESPONSE: + /* + * Frame forwarded to SME to HDD to supplicant + * type is action + */ + pe_debug("Public Action Frame %d received", + action_hdr->actionID); + lim_send_sme_mgmt_frame_ind(pMac, + mac_hdr->fc.subType, + (uint8_t *) mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), 0, + WMA_GET_RX_CH(pBd), NULL, + WMA_GET_RX_RSSI_NORMALIZED(pBd)); + break; default: pe_warn("Unhandled public action frame: %x", - pActionHdr->actionID); + action_hdr->actionID); break; } break; default: pe_warn("Unhandled action frame without session: %x", - pActionHdr->category); + action_hdr->category); break; - } } diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c index 829b217585..eea7cc96a0 100644 --- a/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -106,12 +106,12 @@ static void lim_process_auth_shared_system_algo(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr mac_hdr, tSirMacAuthFrameBody *rx_auth_frm_body, tSirMacAuthFrameBody *auth_frame, - uint8_t *challenge_txt_arr, tpPESession pe_session) { uint32_t val; - uint8_t cfg_privacy_opt_imp, *challenge; + uint8_t cfg_privacy_opt_imp; struct tLimPreAuthNode *auth_node; + uint8_t challenge_txt_arr[SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH] = {0}; pe_debug("=======> eSIR_SHARED_KEY"); if (LIM_IS_AP_ROLE(pe_session)) @@ -192,19 +192,39 @@ static void lim_process_auth_shared_system_algo(tpAniSirGlobal mac_ctx, lim_delete_pre_auth_node(mac_ctx, mac_hdr->sa); return; } - lim_activate_auth_rsp_timer(mac_ctx, auth_node); - auth_node->fTimerStarted = 1; + /* * get random bytes and use as challenge text. - * If it fails we already have random stack bytes. */ - if (!QDF_IS_STATUS_SUCCESS(cds_rand_get_bytes(0, - (uint8_t *) challenge_txt_arr, - SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH))) + get_random_bytes(challenge_txt_arr, + SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH); + qdf_mem_zero(auth_node->challengeText, + SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH); + if (!qdf_mem_cmp(challenge_txt_arr, + auth_node->challengeText, + SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH)) { pe_err("Challenge text preparation failed"); - challenge = auth_node->challengeText; - qdf_mem_copy(challenge, (uint8_t *)challenge_txt_arr, - sizeof(challenge_txt_arr)); + lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOGW); + auth_frame->authAlgoNumber = + rx_auth_frm_body->authAlgoNumber; + auth_frame->authTransactionSeqNumber = + rx_auth_frm_body->authTransactionSeqNumber + 1; + auth_frame->authStatusCode = eSIR_MAC_TRY_AGAIN_LATER; + lim_send_auth_mgmt_frame(mac_ctx, + auth_frame, + mac_hdr->sa, + LIM_NO_WEP_IN_FC, + pe_session); + lim_delete_pre_auth_node(mac_ctx, mac_hdr->sa); + return; + } + + lim_activate_auth_rsp_timer(mac_ctx, auth_node); + auth_node->fTimerStarted = 1; + + qdf_mem_copy(auth_node->challengeText, + challenge_txt_arr, + sizeof(challenge_txt_arr)); /* * Sending Authenticaton frame with challenge. */ @@ -273,7 +293,6 @@ static void lim_process_auth_frame_type1(tpAniSirGlobal mac_ctx, { tpDphHashNode sta_ds_ptr = NULL; struct tLimPreAuthNode *auth_node; - uint8_t challenge_txt_arr[SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH]; uint32_t maxnum_preauth; uint16_t associd = 0; @@ -455,8 +474,7 @@ static void lim_process_auth_frame_type1(tpAniSirGlobal mac_ctx, case eSIR_SHARED_KEY: lim_process_auth_shared_system_algo(mac_ctx, mac_hdr, - rx_auth_frm_body, auth_frame, - challenge_txt_arr, pe_session); + rx_auth_frm_body, auth_frame, pe_session); break; default: pe_err("rx Auth frm for unsupported auth algo %d " diff --git a/core/mac/src/pe/lim/lim_process_deauth_frame.c b/core/mac/src/pe/lim/lim_process_deauth_frame.c index 02837a61cf..7f654b5d0d 100644 --- a/core/mac/src/pe/lim/lim_process_deauth_frame.c +++ b/core/mac/src/pe/lim/lim_process_deauth_frame.c @@ -84,6 +84,11 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); frame_rssi = (int32_t)WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + if (frameLen < sizeof(reasonCode)) { + pe_err("Deauth Frame length invalid %d", frameLen); + return ; + } if (LIM_IS_STA_ROLE(psessionEntry) && ((eLIM_SME_WT_DISASSOC_STATE == psessionEntry->limSmeState) || @@ -135,7 +140,6 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, /* If the frame received is unprotected, forward it to the supplicant to initiate */ /* an SA query */ - frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); /* send the unprotected frame indication to SME */ lim_send_sme_unprotected_mgmt_frame_ind(pMac, pHdr->fc.subType, diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 2aa5a3abd6..c0aa521e23 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2214,6 +2214,12 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) return; } + csa_offload_ind = qdf_mem_malloc(sizeof(tSmeCsaOffloadInd)); + if (NULL == csa_offload_ind) { + pe_err("memalloc fail eWNI_SME_CSA_OFFLOAD_EVENT"); + goto err; + } + session_entry = pe_find_session_by_bssid(mac_ctx, csa_params->bssId, &session_id); @@ -2409,12 +2415,15 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) goto err; } + if (CDS_IS_CHANNEL_24GHZ(csa_params->channel) && + (session_entry->dot11mode == WNI_CFG_DOT11_MODE_11A)) + session_entry->dot11mode = WNI_CFG_DOT11_MODE_11G; + else if (CDS_IS_CHANNEL_5GHZ(csa_params->channel) && + ((session_entry->dot11mode == WNI_CFG_DOT11_MODE_11G) || + (session_entry->dot11mode == WNI_CFG_DOT11_MODE_11G_ONLY))) + session_entry->dot11mode = WNI_CFG_DOT11_MODE_11A; + lim_prepare_for11h_channel_switch(mac_ctx, session_entry); - csa_offload_ind = qdf_mem_malloc(sizeof(tSmeCsaOffloadInd)); - if (NULL == csa_offload_ind) { - pe_err("memalloc fail eWNI_SME_CSA_OFFLOAD_EVENT"); - goto err; - } csa_offload_ind->mesgType = eWNI_SME_CSA_OFFLOAD_EVENT; csa_offload_ind->mesgLen = sizeof(tSmeCsaOffloadInd); diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index de235ce52a..fe44364e91 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -3195,8 +3195,7 @@ sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, for (cnt = 0; cnt < ar->num_WMMTSPEC; cnt++) { qdf_mem_copy(&pAssocRsp->TSPECInfo[cnt], &ar->WMMTSPEC[cnt], - (sizeof(tDot11fIEWMMTSPEC) * - ar->num_WMMTSPEC)); + sizeof(tDot11fIEWMMTSPEC)); } pAssocRsp->tspecPresent = true; } diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index f636f7199d..f8352dc541 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -1738,9 +1738,12 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, */ rssi = (int8_t) pSpectCh->rssiAgr; - if (ch_in_pcl(sap_ctx, chn_num)) + if (ch_in_pcl(sap_ctx, pSpectCh->chNum)) rssi -= PCL_RSSI_DISCOUNT; + if (rssi < SOFTAP_MIN_RSSI) + rssi = SOFTAP_MIN_RSSI; + if (pSpectCh->weight == SAP_ACS_WEIGHT_MAX) goto debug_info; @@ -1757,9 +1760,9 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, debug_info: /* ------ Debug Info ------ */ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH, - "In %s, Chan=%d Weight= %d rssiAgr=%d bssCount=%d", + "In %s, Chan=%d Weight= %d rssiAgr=%d, rssi_pcl_discount: %d, bssCount=%d", __func__, pSpectCh->chNum, pSpectCh->weight, - pSpectCh->rssiAgr, pSpectCh->bssCount); + pSpectCh->rssiAgr, rssi, pSpectCh->bssCount); /* ------ Debug Info ------ */ pSpectCh++; } diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 9e5c0aadb2..c759ed7a73 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -233,6 +233,11 @@ void wlansap_context_put(ptSapContext ctx) for (i = 0; i < SAP_MAX_NUM_SESSION; i++) { if (gp_sap_ctx[i] == ctx) { if (qdf_atomic_dec_and_test(&sap_ctx_ref_count[i])) { + if (ctx->channelList) { + qdf_mem_free(ctx->channelList); + ctx->channelList = NULL; + ctx->num_of_channel = 0; + } qdf_mem_free(ctx); gp_sap_ctx[i] = NULL; QDF_TRACE(QDF_MODULE_ID_SAP, diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 32c79179fc..6fa8ea84e1 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3664,6 +3664,9 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, qdf_nbuf_put_tail(wbuf, hdr->buf_len); qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL); wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf); + qdf_mem_zero(((uint8_t *)wh + hdr->buf_len), roundup(hdr->buf_len + + RESERVE_BYTES, 4) - + hdr->buf_len); rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf); rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr + diff --git a/core/wma/src/wma_nan_datapath.c b/core/wma/src/wma_nan_datapath.c index 720b627008..56b3e1fe95 100644 --- a/core/wma/src/wma_nan_datapath.c +++ b/core/wma/src/wma_nan_datapath.c @@ -464,6 +464,7 @@ static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, wmi_ndp_indication_event_fixed_param *fixed_params; struct ndp_indication_event ind_event = {0}; tp_wma_handle wma_handle = handle; + size_t total_array_len; event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)event_info; fixed_params = @@ -482,6 +483,38 @@ static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, return -EINVAL; } + if (fixed_params->nan_scid_len > event->num_ndp_scid) { + WMA_LOGE(FL("Invalid nan_scid_len: %d"), + fixed_params->nan_scid_len); + return -EINVAL; + } + + if (fixed_params->ndp_cfg_len > + (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) { + WMA_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", + __func__, fixed_params->ndp_cfg_len); + return -EINVAL; + } + + total_array_len = fixed_params->ndp_cfg_len + + sizeof(*fixed_params); + + if (fixed_params->ndp_app_info_len > + (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { + WMA_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", + __func__, fixed_params->ndp_app_info_len); + return -EINVAL; + } + + total_array_len += fixed_params->ndp_app_info_len; + + if (fixed_params->nan_scid_len > + (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { + WMA_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", + __func__, fixed_params->nan_scid_len); + return -EINVAL; + } + ind_event.vdev_id = fixed_params->vdev_id; ind_event.service_instance_id = fixed_params->service_instance_id; ind_event.ndp_instance_id = fixed_params->ndp_instance_id; @@ -517,15 +550,6 @@ static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, ind_event.ncs_sk_type = fixed_params->nan_csid; ind_event.scid.scid_len = fixed_params->nan_scid_len; - if (fixed_params->ndp_cfg_len > event->num_ndp_cfg || - fixed_params->ndp_app_info_len > event->num_ndp_app_info || - fixed_params->nan_scid_len > event->num_ndp_scid) { - WMA_LOGD(FL("Invalid ndp_cfg_len: %d, ndp_app_info_len: %d, nan_scid_len: %d"), - fixed_params->ndp_cfg_len, - fixed_params->ndp_app_info_len, - fixed_params->nan_scid_len); - return -EINVAL; - } if (ind_event.ndp_config.ndp_cfg_len) { ind_event.ndp_config.ndp_cfg = qdf_mem_malloc(fixed_params->ndp_cfg_len); diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 7bfa295e4a..c201226a70 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -1349,7 +1349,7 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, } while (0); if (excess_data || - (sizeof(*fixed_param) > WMI_SVC_MSG_MAX_SIZE - buf_len)) { + (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_param))) { WMA_LOGE("excess wmi buffer: rates:%d, peers:%d", peer_stats->num_rates, fixed_param->num_peers); return -EINVAL; @@ -3186,7 +3186,7 @@ int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info, } while (0); if (excess_data || - (sizeof(*event) > WMI_SVC_MSG_MAX_SIZE - buf_len)) { + (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*event))) { WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d", event->num_pdev_stats, event->num_vdev_stats, event->num_peer_stats); |