From 43e6dea453eedb331f63491a4a3d3ebad2ee110a Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Sun, 18 Aug 2019 11:39:23 +0530 Subject: [PATCH] qcacld-3.0: Move sta_info from array based to hash based Currently in hdd_adapter, the variable sta_info is an array of hdd_station_info structured indexed by the sta_id. As sta_id is no longer used this array based implementation becomes unnecessary. Move the sta_info implementation to a hash table implementation. Change-Id: I7d6fe04b7e0ab22615d431de9a10a4ad38ed65ba CRs-Fixed: 2514280 --- Kbuild | 1 + .../mlme/dispatcher/inc/wlan_mlme_api.h | 6 +- .../mlme/dispatcher/inc/wlan_mlme_ucfg_api.h | 8 +- .../mlme/dispatcher/src/wlan_mlme_api.c | 4 +- core/hdd/inc/qc_sap_ioctl.h | 2 +- core/hdd/inc/wlan_hdd_assoc.h | 11 +- core/hdd/inc/wlan_hdd_main.h | 137 +---- core/hdd/inc/wlan_hdd_softap_tx_rx.h | 65 +-- core/hdd/src/wlan_hdd_assoc.c | 136 ++--- core/hdd/src/wlan_hdd_cfg80211.c | 282 +++++----- core/hdd/src/wlan_hdd_hostapd.c | 153 +++--- core/hdd/src/wlan_hdd_hostapd_wext.c | 149 ++---- core/hdd/src/wlan_hdd_main.c | 61 ++- core/hdd/src/wlan_hdd_softap_tx_rx.c | 484 ++++++++---------- core/hdd/src/wlan_hdd_sta_info.c | 118 +++++ core/hdd/src/wlan_hdd_sta_info.h | 270 ++++++++++ core/hdd/src/wlan_hdd_station_info.c | 6 +- core/hdd/src/wlan_hdd_stats.c | 12 +- 18 files changed, 996 insertions(+), 909 deletions(-) create mode 100644 core/hdd/src/wlan_hdd_sta_info.c create mode 100644 core/hdd/src/wlan_hdd_sta_info.h diff --git a/Kbuild b/Kbuild index 8fa2d1e0f1..cbff722ce8 100644 --- a/Kbuild +++ b/Kbuild @@ -77,6 +77,7 @@ HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ $(HDD_SRC_DIR)/wlan_hdd_regulatory.o \ $(HDD_SRC_DIR)/wlan_hdd_scan.o \ $(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.o \ + $(HDD_SRC_DIR)/wlan_hdd_sta_info.o \ $(HDD_SRC_DIR)/wlan_hdd_stats.o \ $(HDD_SRC_DIR)/wlan_hdd_trace.o \ $(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index b5e0a10a07..6baab17d9f 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -555,7 +555,7 @@ QDF_STATUS wlan_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc, bool value); /** - * wlan_mlme_is_sap_bcast_deauth_enabled() - get the enable/disable value + * wlan_mlme_get_sap_bcast_deauth_enabled() - get the enable/disable value * for broadcast deauth in sap * @psoc: pointer to psoc object * @value: Value that needs to get from the caller @@ -563,8 +563,8 @@ QDF_STATUS wlan_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc, * Return: QDF Status */ QDF_STATUS -wlan_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, - bool *value); +wlan_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, + bool *value); /** * wlan_mlme_get_sap_allow_all_channels() - get the value of sap allow all diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 7a070b6152..0ed24805f3 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -1421,7 +1421,7 @@ QDF_STATUS ucfg_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc, } /** - * ucfg_mlme_is_sap_bcast_deauth_enabled() - get the sap bcast deauth + * ucfg_mlme_get_sap_bcast_deauth_enabled() - get the sap bcast deauth * enabled value * @psoc: pointer to psoc object * @value: Value that needs to be get from the caller @@ -1431,10 +1431,10 @@ QDF_STATUS ucfg_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc, * Return: QDF Status */ static inline QDF_STATUS -ucfg_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, - bool *value) +ucfg_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, + bool *value) { - return wlan_mlme_is_sap_bcast_deauth_enabled(psoc, value); + return wlan_mlme_get_sap_bcast_deauth_enabled(psoc, value); } /** diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index b9431ee72f..334074c8ad 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -1716,8 +1716,8 @@ QDF_STATUS wlan_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc, } QDF_STATUS -wlan_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, - bool *value) +wlan_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, + bool *value) { struct wlan_mlme_psoc_obj *mlme_obj; diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h index f5d04b7556..7226536b5a 100644 --- a/core/hdd/inc/qc_sap_ioctl.h +++ b/core/hdd/inc/qc_sap_ioctl.h @@ -226,7 +226,7 @@ enum { QCSAP_PARAM_CHAN_WIDTH, QCSAP_PARAM_SET_TXRX_STATS, QCASAP_SET_11AX_RATE, - QCASAP_SET_PEER_RATE, + QCASAP_SET_PEER_RATE, /* Not Supported */ QCASAP_PARAM_DCM, QCASAP_PARAM_RANGE_EXT, QCSAP_SET_DEFAULT_AMPDU, diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index 2aa5bc7de9..e62524027c 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -388,8 +388,17 @@ hdd_indicate_ese_bcn_report_no_results(const struct hdd_adapter *adapter, const uint8_t numBss); #endif /* FEATURE_WLAN_ESE */ +/** + * hdd_change_peer_state() - change peer state + * @adapter: HDD adapter + * @peer_mac_addr: Peer MAC address + * @sta_state: peer state + * @roam_synch_in_progress: roam synch in progress + * + * Return: QDF status + */ QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter, - uint8_t sta_id, + uint8_t *peer_mac_addr, enum ol_txrx_peer_state sta_state, bool roam_synch_in_progress); #ifdef WLAN_FEATURE_ROAM_OFFLOAD diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index da5af95087..8895830ea5 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -112,6 +112,8 @@ #include "qdf_periodic_work.h" #endif +#include "wlan_hdd_sta_info.h" + /* * Preprocessor definitions and constants */ @@ -880,135 +882,6 @@ struct hdd_fw_txrx_stats { struct hdd_rate_info rx_rate; }; -/** - * struct dhcp_phase - Per Peer DHCP Phases - * @DHCP_PHASE_ACK: upon receiving DHCP_ACK/NAK message in REQUEST phase or - * DHCP_DELINE message in OFFER phase - * @DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase - * @DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase - * @DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase or - * ACK phase (Renewal process) - */ -enum dhcp_phase { - DHCP_PHASE_ACK, - DHCP_PHASE_DISCOVER, - DHCP_PHASE_OFFER, - DHCP_PHASE_REQUEST -}; - -/** - * struct dhcp_nego_status - Per Peer DHCP Negotiation Status - * @DHCP_NEGO_STOP: when the peer is in ACK phase or client disassociated - * @DHCP_NEGO_IN_PROGRESS: when the peer is in DISCOVER or REQUEST - * (Renewal process) phase - */ -enum dhcp_nego_status { - DHCP_NEGO_STOP, - DHCP_NEGO_IN_PROGRESS -}; - -/** - * struct hdd_station_info - Per station structure kept in HDD for - * multiple station support for SoftAP - * @in_use: Is the station entry in use? - * @sta_id: Station ID reported back from HAL (through SAP). - * Broadcast uses station ID zero by default. - * @sta_type: Type of station i.e. p2p client or infrastructure station - * @sta_mac: MAC address of the station - * @peer_state: Current Station state so HDD knows how to deal with packet - * queue. Most recent states used to change TLSHIM STA state. - * @is_qos_enabled: Track QoS status of station - * @is_deauth_in_progress: The station entry for which Deauth is in progress - * @nss: Number of spatial streams supported - * @rate_flags: Rate Flags for this connection - * @ecsa_capable: Extended CSA capabilities - * @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc. - * @tx_packets: Packets send to current station - * @tx_bytes: Bytes send to current station - * @rx_packets: Packets received from current station - * @rx_bytes: Bytes received from current station - * @last_tx_rx_ts: Last tx/rx timestamp with current station - * @assoc_ts: Current station association timestamp - * @tx_rate: Tx rate with current station reported from F/W - * @rx_rate: Rx rate with current station reported from F/W - * @ampdu: Ampdu enable or not of the station - * @sgi_enable: Short GI enable or not of the station - * @tx_stbc: Tx Space-time block coding enable/disable - * @rx_stbc: Rx Space-time block coding enable/disable - * @ch_width: Channel Width of the connection - * @mode: Mode of the connection - * @max_supp_idx: Max supported rate index of the station - * @max_ext_idx: Max extended supported rate index of the station - * @max_mcs_idx: Max supported mcs index of the station - * @rx_mcs_map: VHT Rx mcs map - * @tx_mcs_map: VHT Tx mcs map - * @freq : Frequency of the current station - * @dot11_mode: 802.11 Mode of the connection - * @ht_present: HT caps present or not in the current station - * @vht_present: VHT caps present or not in the current station - * @ht_caps: HT capabilities of current station - * @vht_caps: VHT capabilities of current station - * @reason_code: Disconnection reason code for current station - * @rssi: RSSI of the current station reported from F/W - * @capability: Capability information of current station - * @support_mode: Max supported mode of a station currently - * connected to sap - * @rx_retry_cnt: Number of rx retries received from current station - * Currently this feature is not supported from FW - * @rx_mc_bc_cnt: Multicast broadcast packet count received from - * current station - * MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt - * feature or not, if first bit is 1 it indicates that FW supports this - * feature, if it is 0 it indicates FW doesn't support this feature - */ -struct hdd_station_info { - bool in_use; - uint8_t sta_id; - eStationType sta_type; - struct qdf_mac_addr sta_mac; - enum ol_txrx_peer_state peer_state; - bool is_qos_enabled; - bool is_deauth_in_progress; - uint8_t nss; - uint32_t rate_flags; - uint8_t ecsa_capable; - uint32_t max_phy_rate; - uint32_t tx_packets; - uint64_t tx_bytes; - uint32_t rx_packets; - uint64_t rx_bytes; - qdf_time_t last_tx_rx_ts; - qdf_time_t assoc_ts; - qdf_time_t disassoc_ts; - uint32_t tx_rate; - uint32_t rx_rate; - bool ampdu; - bool sgi_enable; - bool tx_stbc; - bool rx_stbc; - tSirMacHTChannelWidth ch_width; - uint8_t mode; - uint8_t max_supp_idx; - uint8_t max_ext_idx; - uint8_t max_mcs_idx; - uint8_t rx_mcs_map; - uint8_t tx_mcs_map; - uint32_t freq; - uint8_t dot11_mode; - bool ht_present; - bool vht_present; - struct ieee80211_ht_cap ht_caps; - struct ieee80211_vht_cap vht_caps; - uint32_t reason_code; - int8_t rssi; - enum dhcp_phase dhcp_phase; - enum dhcp_nego_status dhcp_nego_status; - uint16_t capability; - uint8_t support_mode; - uint32_t rx_retry_cnt; - uint32_t rx_mc_bc_cnt; -}; - /** * struct hdd_ap_ctx - SAP/P2PGO specific information * @hostapd_state: state control information @@ -1264,10 +1137,14 @@ struct hdd_adapter { /** Multiple station supports */ /** Per-station structure */ - spinlock_t sta_info_lock; /* To protect access to station Info */ + + /* TODO: Will be removed as a part of next phase of clean up */ struct hdd_station_info sta_info[WLAN_MAX_STA_COUNT]; struct hdd_station_info cache_sta_info[WLAN_MAX_STA_COUNT]; + /* TODO: _list from name will be removed after clean up */ + struct hdd_sta_info_obj sta_info_list; + struct hdd_sta_info_obj cache_sta_info_list; #ifdef FEATURE_WLAN_WAPI struct hdd_wapi_info wapi_info; diff --git a/core/hdd/inc/wlan_hdd_softap_tx_rx.h b/core/hdd/inc/wlan_hdd_softap_tx_rx.h index c110a7a4cf..39b05c6d36 100644 --- a/core/hdd/inc/wlan_hdd_softap_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_softap_tx_rx.h @@ -70,10 +70,9 @@ void hdd_softap_tx_timeout(struct net_device *dev); * hdd_softap_init_tx_rx() - Initialize Tx/Rx module * @adapter: pointer to adapter context * - * Return: QDF_STATUS_E_FAILURE if any errors encountered, - * QDF_STATUS_SUCCESS otherwise + * Return: None */ -QDF_STATUS hdd_softap_init_tx_rx(struct hdd_adapter *adapter); +void hdd_softap_init_tx_rx(struct hdd_adapter *adapter); /** * hdd_softap_deinit_tx_rx() - Deinitialize Tx/Rx module @@ -87,27 +86,14 @@ QDF_STATUS hdd_softap_deinit_tx_rx(struct hdd_adapter *adapter); /** * hdd_softap_init_tx_rx_sta() - Initialize Tx/Rx for a softap station * @adapter: pointer to adapter context - * @sta_id: Station ID to initialize * @sta_mac: pointer to the MAC address of the station * * Return: QDF_STATUS_E_FAILURE if any errors encountered, * QDF_STATUS_SUCCESS otherwise */ QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter, - uint8_t sta_id, struct qdf_mac_addr *sta_mac); -/** - * hdd_softap_deinit_tx_rx_sta() - Deinitialize Tx/Rx for a softap station - * @adapter: pointer to adapter context - * @sta_id: Station ID to deinitialize - * - * Return: QDF_STATUS_E_FAILURE if any errors encountered, - * QDF_STATUS_SUCCESS otherwise - */ -QDF_STATUS hdd_softap_deinit_tx_rx_sta(struct hdd_adapter *adapter, - uint8_t sta_id); - /** * hdd_softap_rx_packet_cbk() - Receive packet handler * @adapter_context: pointer to HDD adapter @@ -125,14 +111,12 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf); /** * hdd_softap_deregister_sta() - Deregister a STA with the Data Path * @adapter: pointer to adapter context - * @sta_id: Station ID to deregister - * @mac_addr: Peer mac address + * @sta_info: pointer to HDD station info structure * * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error */ QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter, - uint8_t sta_id, - struct qdf_mac_addr mac_addr); + struct hdd_station_info *sta_info); /** * hdd_softap_register_sta() - Register a SoftAP STA @@ -182,20 +166,6 @@ QDF_STATUS hdd_softap_change_sta_state(struct hdd_adapter *adapter, struct qdf_mac_addr *sta_mac, enum ol_txrx_peer_state state); -/** - * hdd_softap_get_sta_id() - Find station ID from MAC address - * @adapter: pointer to adapter context - * @sta_mac: MAC address of the destination - * @sta_id: Station ID associated with the MAC address - * - * Return: QDF_STATUS_SUCCESS if a match was found, in which case - * @sta_id is populated, QDF_STATUS_E_FAILURE if a match is - * not found - */ -QDF_STATUS hdd_softap_get_sta_id(struct hdd_adapter *adapter, - struct qdf_mac_addr *sta_mac, - uint8_t *sta_id); - #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL /** * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler @@ -235,20 +205,39 @@ void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume) /** * hdd_post_dhcp_ind() - Send DHCP START/STOP indication to FW * @adapter: pointer to hdd adapter - * @sta_id: peer station ID + * @mac_addr: mac address * @type: WMA message type * * Return: error number */ int hdd_post_dhcp_ind(struct hdd_adapter *adapter, - uint8_t sta_id, uint16_t type); + uint8_t *mac_addr, uint16_t type); /** - * hdd_softap_inspect_dhcp_packet() - Inspect DHCP packet + * hdd_softap_inspect_dhcp_packet() - Inspect DHCP packet * @adapter: pointer to hdd adapter * @skb: pointer to OS packet (sk_buff) * @dir: direction * + * Inspect the Tx/Rx frame, and send DHCP START/STOP notification to the FW + * through WMI message, during DHCP based IP address acquisition phase. + * + * - Send DHCP_START notification to FW when SAP gets DHCP Discovery + * - Send DHCP_STOP notification to FW when SAP sends DHCP ACK/NAK + * + * DHCP subtypes are determined by a status octet in the DHCP Message type + * option (option code 53 (0x35)). + * + * Each peer will be in one of 4 DHCP phases, starts from QDF_DHCP_PHASE_ACK, + * and transitioned per DHCP message type as it arrives. + * + * - QDF_DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase + * - QDF_DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase + * - QDF_DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase + * or ACK phase (Renewal process) + * - QDF_DHCP_PHASE_ACK : upon receiving DHCP_ACK/NAK message in REQUEST phase + * or DHCP_DELINE message in OFFER phase + * * Return: error number */ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, @@ -257,7 +246,7 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, #else static inline int hdd_post_dhcp_ind(struct hdd_adapter *adapter, - uint8_t sta_id, uint16_t type) + uint8_t *mac_addr, uint16_t type) { return 0; } diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 744fcadc9c..fd810be7fa 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -69,6 +69,7 @@ #include #include #include "wlan_blm_ucfg_api.h" +#include "wlan_hdd_sta_info.h" /* These are needed to recognize WPA and RSN suite types */ #define HDD_WPA_OUI_SIZE 4 @@ -1935,47 +1936,29 @@ static void hdd_set_peer_authorized_event(uint32_t vdev_id) complete(&adapter->sta_authorized_event); } -/** - * hdd_change_peer_state() - change peer state - * @adapter: HDD adapter - * @sta_state: peer state - * @roam_synch_in_progress: roam synch in progress - * - * Return: QDF status - */ QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter, - uint8_t sta_id, + uint8_t *peer_mac, enum ol_txrx_peer_state sta_state, bool roam_synch_in_progress) { QDF_STATUS err; - uint8_t *peer_mac_addr; void *pdev = cds_get_context(QDF_MODULE_ID_TXRX); void *soc = cds_get_context(QDF_MODULE_ID_SOC); void *peer; + /* Will be removed as a part of clean up */ + uint8_t sta_id; if (!pdev) { hdd_err("Failed to get txrx context"); return QDF_STATUS_E_FAULT; } - if (sta_id >= WLAN_MAX_STA_COUNT) { - hdd_err("Invalid sta id: %d", sta_id); - return QDF_STATUS_E_INVAL; - } - - peer = cdp_peer_find_by_local_id(soc, - (struct cdp_pdev *)pdev, sta_id); + peer = cdp_peer_find_by_addr(soc, (struct cdp_pdev *)pdev, + peer_mac, &sta_id); if (!peer) return QDF_STATUS_E_FAULT; - peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer); - if (!peer_mac_addr) { - hdd_err("peer mac addr is NULL"); - return QDF_STATUS_E_FAULT; - } - - err = cdp_peer_state_update(soc, pdev, peer_mac_addr, sta_state); + err = cdp_peer_state_update(soc, pdev, peer_mac, sta_state); if (err != QDF_STATUS_SUCCESS) { hdd_err("peer state update failed"); return QDF_STATUS_E_FAULT; @@ -1994,7 +1977,8 @@ QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter, INIT_COMPLETION(adapter->sta_authorized_event); #endif - err = sme_set_peer_authorized(peer_mac_addr, + err = sme_set_peer_authorized( + peer_mac, hdd_set_peer_authorized_event, adapter->vdev_id); if (err != QDF_STATUS_SUCCESS) { @@ -2061,6 +2045,32 @@ QDF_STATUS hdd_update_dp_vdev_flags(void *cbk_data, return status; } +/** + * hdd_conn_change_peer_state() - Change the state of the peer + * @adapter: pointer to adapter + * @roam_info: pointer to roam info + * @mac_addr: peer mac address + * + * Return: QDF_STATUS enumeration + */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static QDF_STATUS hdd_conn_change_peer_state(struct hdd_adapter *adapter, + struct csr_roam_info *roam_info, + uint8_t *mac_addr) +{ + return hdd_change_peer_state(adapter, mac_addr, OL_TXRX_PEER_STATE_AUTH, + roam_info->roamSynchInProgress); +} +#else +static QDF_STATUS hdd_conn_change_peer_state(struct hdd_adapter *adapter, + struct csr_roam_info *roam_info, + uint8_t *mac_addr) +{ + return hdd_change_peer_state(adapter, mac_addr, OL_TXRX_PEER_STATE_AUTH, + false); +} +#endif + /** * hdd_roam_register_sta() - register station * @adapter: pointer to adapter @@ -2153,30 +2163,20 @@ QDF_STATUS hdd_roam_register_sta(struct hdd_adapter *adapter, * Connections that do not need Upper layer auth, transition * TLSHIM directly to 'Authenticated' state */ - qdf_status = - hdd_change_peer_state(adapter, txrx_desc.sta_id, - OL_TXRX_PEER_STATE_AUTH, -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - roam_info->roamSynchInProgress -#else - false -#endif - ); + qdf_status = hdd_conn_change_peer_state( + adapter, roam_info, + txrx_desc.peer_addr.bytes); hdd_conn_set_authenticated(adapter, true); hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, true); } else { hdd_debug("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", sta_ctx->conn_info.sta_id[0]); - qdf_status = - hdd_change_peer_state(adapter, txrx_desc.sta_id, - OL_TXRX_PEER_STATE_CONN, -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - roam_info->roamSynchInProgress -#else - false -#endif - ); + + qdf_status = hdd_conn_change_peer_state( + adapter, roam_info, + txrx_desc.peer_addr.bytes); + hdd_conn_set_authenticated(adapter, false); hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, false); } @@ -2447,38 +2447,6 @@ bool hdd_is_roam_sync_in_progress(struct csr_roam_info *roaminfo) #endif #ifdef QCA_IBSS_SUPPORT -/** - * hdd_get_ibss_peer_sta_id() - get sta id for IBSS peer - * @hddstactx: pointer to HDD sta context - * @roaminfo: pointer to roaminfo structure - * - * This function returns sta_id for IBSS peer. If peer is broadcast - * MAC address return self sta_id(0) else find the peer sta id of - * the peer. - * - * Return: sta_id (HDD_WLAN_INVALID_STA_ID if peer not found). - */ -static uint8_t hdd_get_ibss_peer_sta_id(struct hdd_station_ctx *hddstactx, - struct csr_roam_info *roaminfo) -{ - uint8_t sta_id = HDD_WLAN_INVALID_STA_ID; - QDF_STATUS status; - - if (qdf_is_macaddr_broadcast(&roaminfo->peerMac)) { - sta_id = 0; - } else { - status = hdd_get_peer_sta_id(hddstactx, - &roaminfo->peerMac, &sta_id); - if (status != QDF_STATUS_SUCCESS) { - hdd_err("Unable to find station ID for " - QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(roaminfo->peerMac.bytes)); - } - } - - return sta_id; -} - /** * hdd_roam_ibss_indication_handler() - update the status of the IBSS * @adapter: pointer to adapter @@ -2694,8 +2662,8 @@ static int hdd_change_sta_state_authenticated(struct hdd_adapter *adapter, struct csr_roam_info *roaminfo) { QDF_STATUS status; + uint8_t *mac_addr; uint32_t timeout, auto_bmps_timer_val; - uint8_t sta_id = HDD_WLAN_INVALID_STA_ID; struct hdd_station_ctx *hddstactx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -2707,17 +2675,19 @@ static int hdd_change_sta_state_authenticated(struct hdd_adapter *adapter, (auto_bmps_timer_val * 1000); if (QDF_IBSS_MODE == adapter->device_mode) - sta_id = hdd_get_ibss_peer_sta_id(hddstactx, roaminfo); + mac_addr = roaminfo->peerMac.bytes; else - sta_id = hddstactx->conn_info.sta_id[0]; + mac_addr = hddstactx->conn_info.bssid.bytes; - hdd_debug("Changing Peer state to AUTHENTICATED for StaId = %d", - sta_id); + hdd_debug("Changing Peer state to AUTHENTICATED for Sta = " + QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(mac_addr)); /* Connections that do not need Upper layer authentication, * transition TL to 'Authenticated' state after the keys are set */ - status = hdd_change_peer_state(adapter, sta_id, OL_TXRX_PEER_STATE_AUTH, + + status = hdd_change_peer_state(adapter, mac_addr, + OL_TXRX_PEER_STATE_AUTH, hdd_is_roam_sync_in_progress(roaminfo)); hdd_conn_set_authenticated(adapter, true); hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, true); @@ -3443,7 +3413,7 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, if (roam_info->fAuthRequired) { qdf_status = hdd_change_peer_state(adapter, - sta_ctx->conn_info.sta_id[0], + roam_info->bssid.bytes, OL_TXRX_PEER_STATE_CONN, #ifdef WLAN_FEATURE_ROAM_OFFLOAD roam_info->roamSynchInProgress @@ -3460,7 +3430,7 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, sta_ctx->conn_info.sta_id[0]); qdf_status = hdd_change_peer_state(adapter, - sta_ctx->conn_info.sta_id[0], + roam_info->bssid.bytes, OL_TXRX_PEER_STATE_AUTH, #ifdef WLAN_FEATURE_ROAM_OFFLOAD roam_info->roamSynchInProgress diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 46e382d7f4..85638c2655 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -142,6 +142,7 @@ #include "wlan_hdd_hw_capability.h" #include "wlan_hdd_oemdata.h" #include "os_if_fwol.h" +#include "wlan_hdd_sta_info.h" #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -9865,9 +9866,9 @@ static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, struct net_device *dev = wdev->netdev; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct hdd_station_ctx *hdd_sta_ctx; + struct hdd_station_info *sta_info; struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1]; uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; - uint32_t sta_id; struct sk_buff *reply_skb; uint32_t rate_flags = 0; uint8_t nss; @@ -9925,26 +9926,24 @@ static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, } else if (adapter->device_mode == QDF_P2P_GO_MODE || adapter->device_mode == QDF_SAP_MODE) { - for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { - if (adapter->sta_info[sta_id].in_use && - !qdf_is_macaddr_broadcast( - &adapter->sta_info[sta_id].sta_mac) && - !qdf_mem_cmp( - &adapter->sta_info[sta_id].sta_mac.bytes, - peer_mac, QDF_MAC_ADDR_SIZE)) - break; - } - - if (WLAN_MAX_STA_COUNT == sta_id) { - hdd_err("No active peer with mac="QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(peer_mac)); + if (QDF_IS_ADDR_BROADCAST(peer_mac)) { + hdd_err("Ignore bcast/self sta"); return -EINVAL; } - nss = adapter->sta_info[sta_id].nss; + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + peer_mac); + + if (!sta_info) { + hdd_err("No active peer with mac = " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(peer_mac)); + return -EINVAL; + } + + nss = sta_info->nss; freq = cds_chan_to_freq( (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel); - rate_flags = adapter->sta_info[sta_id].rate_flags; + rate_flags = sta_info->rate_flags; } else { hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(peer_mac)); @@ -20960,6 +20959,110 @@ static int wlan_hdd_set_txq_params(struct wiphy *wiphy, return errno; } +/** + * hdd_softap_deauth_current_sta() - Deauth current sta + * @sta_info: pointer to the current station info structure + * @adapter: pointer to adapter structure + * @hdd_ctx: pointer to hdd context + * @hapd_state: pointer to hostapd state structure + * @param: pointer to del sta params + * + * Return: QDF_STATUS on success, corresponding QDF failure status on failure + */ +static +QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter, + struct hdd_station_info *sta_info, + struct hdd_hostapd_state *hapd_state, + struct csr_del_sta_params *param) +{ + qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event; + struct hdd_context *hdd_ctx; + QDF_STATUS qdf_status; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) { + hdd_err("hdd_ctx is NULL"); + return QDF_STATUS_E_INVAL; + } + + if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) + return QDF_STATUS_E_INVAL; + + qdf_event_reset(&hapd_state->qdf_sta_disassoc_event); + + if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) + sme_send_disassoc_req_frame(hdd_ctx->mac_handle, + adapter->vdev_id, + (uint8_t *)¶m->peerMacAddr, + param->reason_code, 0); + + qdf_status = hdd_softap_sta_deauth(adapter, param); + + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + sta_info->is_deauth_in_progress = true; + qdf_status = qdf_wait_for_event_completion( + disassoc_event, + SME_PEER_DISCONNECT_TIMEOUT); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) + hdd_warn("Deauth time expired"); + } else { + sta_info->is_deauth_in_progress = false; + hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); + return QDF_STATUS_E_NOENT; + } + return QDF_STATUS_SUCCESS; +} + +/** + * hdd_softap_deauth_all_sta() - Deauth all sta in the sta list + * @hdd_ctx: pointer to hdd context + * @adapter: pointer to adapter structure + * @hapd_state: pointer to hostapd state structure + * @param: pointer to del sta params + * + * Return: QDF_STATUS on success, corresponding QDF failure status on failure + */ +static +QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter, + struct hdd_hostapd_state *hapd_state, + struct csr_del_sta_params *param) +{ + uint8_t index = 0; + QDF_STATUS status; + bool is_sap_bcast_deauth_enabled = false; + struct hdd_context *hdd_ctx; + struct hdd_station_info *sta_info; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) { + hdd_err("hdd_ctx is NULL"); + return QDF_STATUS_E_INVAL; + } + + ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc, + &is_sap_bcast_deauth_enabled); + + hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled); + + if (is_sap_bcast_deauth_enabled) + return QDF_STATUS_E_INVAL; + + hdd_for_each_station(adapter->sta_info_list, sta_info, index) { + if (!sta_info->is_deauth_in_progress) { + hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); + status = + hdd_softap_deauth_current_sta(adapter, sta_info, + hapd_state, param); + if (QDF_IS_STATUS_ERROR(status)) + return status; + } + } + + return QDF_STATUS_SUCCESS; +} + /** * __wlan_hdd_cfg80211_del_station() - delete station v2 * @wiphy: Pointer to wiphy @@ -20975,11 +21078,10 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, { struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct hdd_context *hdd_ctx; - QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; struct hdd_hostapd_state *hapd_state; - uint8_t sta_id; uint8_t *mac; mac_handle_t mac_handle; + struct hdd_station_info *sta_info; hdd_enter(); @@ -21004,123 +21106,43 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, mac = (uint8_t *) param->peerMacAddr.bytes; mac_handle = hdd_ctx->mac_handle; - if ((QDF_SAP_MODE == adapter->device_mode) || - (QDF_P2P_GO_MODE == adapter->device_mode)) { + if (QDF_SAP_MODE != adapter->device_mode && + QDF_P2P_GO_MODE != adapter->device_mode) + goto fn_end; - hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); - if (!hapd_state) { - hdd_err("Hostapd State is Null"); - return 0; - } + hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); + if (!hapd_state) { + hdd_err("Hostapd State is Null"); + return 0; + } - if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) { - uint16_t i; + if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) { + if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter, + hapd_state, + param))) + goto fn_end; + } else { + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + mac); - bool is_sap_bcast_deauth_enabled = false; - - ucfg_mlme_is_sap_bcast_deauth_enabled( - hdd_ctx->psoc, - &is_sap_bcast_deauth_enabled); - hdd_debug("is_sap_bcast_deauth_enabled %d", - is_sap_bcast_deauth_enabled); - - if (is_sap_bcast_deauth_enabled) - goto fn_end; - - for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - if ((adapter->sta_info[i].in_use) && - (!adapter->sta_info[i]. - is_deauth_in_progress)) { - qdf_mem_copy( - mac, - adapter->sta_info[i]. - sta_mac.bytes, - QDF_MAC_ADDR_SIZE); - - hdd_debug("Delete STA with MAC::" - QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(mac)); - - if (hdd_ctx->dev_dfs_cac_status == - DFS_CAC_IN_PROGRESS) - goto fn_end; - - qdf_event_reset(&hapd_state->qdf_sta_disassoc_event); - qdf_status = - hdd_softap_sta_deauth(adapter, - param); - if (QDF_IS_STATUS_SUCCESS(qdf_status)) { - adapter->sta_info[i]. - is_deauth_in_progress = true; - qdf_status = - qdf_wait_for_event_completion( - &hapd_state-> - qdf_sta_disassoc_event, - SME_PEER_DISCONNECT_TIMEOUT); - if (!QDF_IS_STATUS_SUCCESS( - qdf_status)) - hdd_warn("Deauth wait time expired"); - } - } - } - } else { - qdf_status = - hdd_softap_get_sta_id(adapter, - (struct qdf_mac_addr *) mac, - &sta_id); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_debug("Skip DEL STA as this is not used::" - QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(mac)); - return -ENOENT; - } - - if (adapter->sta_info[sta_id].is_deauth_in_progress == - true) { - hdd_debug("Skip DEL STA as deauth is in progress::" - QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(mac)); - return -ENOENT; - } - - adapter->sta_info[sta_id].is_deauth_in_progress = true; - - hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR, + if (!sta_info) { + hdd_debug("Skip DEL STA as this is not used::" + QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(mac)); - - /* Case: SAP in ACS selected DFS ch and client connected - * Now Radar detected. Then if random channel is another - * DFS ch then new CAC is initiated and no TX allowed. - * So do not send any mgmt frames as it will timeout - * during CAC. - */ - - if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) - goto fn_end; - - qdf_event_reset(&hapd_state->qdf_sta_disassoc_event); - sme_send_disassoc_req_frame(mac_handle, - adapter->vdev_id, - (uint8_t *)¶m->peerMacAddr, - param->reason_code, 0); - qdf_status = hdd_softap_sta_deauth(adapter, - param); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - adapter->sta_info[sta_id].is_deauth_in_progress = - false; - hdd_debug("STA removal failed for ::" - QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(mac)); - return -ENOENT; - } - qdf_status = qdf_wait_for_event_completion( - &hapd_state-> - qdf_sta_disassoc_event, - SME_PEER_DISCONNECT_TIMEOUT); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) - hdd_warn("Deauth wait time expired"); - + return -ENOENT; } + + if (sta_info->is_deauth_in_progress) { + hdd_debug("Skip DEL STA as deauth is in progress::" + QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(mac)); + return -ENOENT; + } + + hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(mac)); + hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state, + param); } fn_end: diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index f8e9f93505..b39d622337 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -91,6 +91,7 @@ #include "wlan_fwol_ucfg_api.h" #include "nan_ucfg_api.h" #include +#include "wlan_hdd_sta_info.h" #define ACS_SCAN_EXPIRY_TIMEOUT_S 4 @@ -740,19 +741,15 @@ static int hdd_hostapd_set_mac_address(struct net_device *net_dev, void *addr) return errno; } -static void hdd_clear_sta(struct hdd_adapter *adapter, uint8_t sta_id) +static void hdd_clear_sta(struct hdd_adapter *adapter, + struct hdd_station_info *sta_info) { struct hdd_ap_ctx *ap_ctx; - struct hdd_station_info *sta_info; struct csr_del_sta_params del_sta_params; ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); - if (sta_id == ap_ctx->broadcast_sta_id) - return; - - sta_info = &adapter->sta_info[sta_id]; - if (!sta_info->in_use) + if (qdf_is_macaddr_broadcast(&sta_info->sta_mac)) return; wlansap_populate_del_sta_params(sta_info->sta_mac.bytes, @@ -765,11 +762,14 @@ static void hdd_clear_sta(struct hdd_adapter *adapter, uint8_t sta_id) static void hdd_clear_all_sta(struct hdd_adapter *adapter) { - uint8_t sta_id; + uint8_t index = 0; + struct hdd_station_info *sta_info; hdd_enter_dev(adapter->dev); - for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) - hdd_clear_sta(adapter, sta_id); + + hdd_for_each_station(adapter->sta_info_list, sta_info, index) { + hdd_clear_sta(adapter, sta_info); + } } static int hdd_stop_bss_link(struct hdd_adapter *adapter) @@ -1452,7 +1452,8 @@ static void hdd_fill_station_info(struct hdd_adapter *adapter, return; } - stainfo = &adapter->sta_info[event->staId]; + stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + event->staMac.bytes); if (!stainfo) { hdd_err("invalid stainfo"); @@ -1748,6 +1749,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event, bool legacy_phymode; tSap_StationDisassocCompleteEvent *disassoc_comp; struct hdd_station_info *stainfo, *cache_stainfo; + uint8_t index = 0; mac_handle_t mac_handle; struct sap_config *sap_config; @@ -2228,7 +2230,14 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event, if (QDF_IS_STATUS_SUCCESS(qdf_status)) hdd_fill_station_info(adapter, event); - adapter->sta_info[sta_id].ecsa_capable = event->ecsa_capable; + stainfo = hdd_get_sta_info_by_mac( + &adapter->sta_info_list, + (uint8_t *)&wrqu.addr.sa_data); + + if (stainfo) + stainfo->ecsa_capable = event->ecsa_capable; + else + hdd_err("Station not found"); if (ucfg_ipa_is_enabled()) { status = ucfg_ipa_wlan_evt(hdd_ctx->pdev, @@ -2339,48 +2348,40 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event, else hdd_debug(" MAC initiated disassociation"); we_event = IWEVEXPIRED; - qdf_status = - hdd_softap_get_sta_id(adapter, - &sap_event->sapevt. - sapStationDisassocCompleteEvent.staMac, - &sta_id); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_err("Failed to find sta id status: %d", qdf_status); - return QDF_STATUS_E_FAILURE; - } DPTRACE(qdf_dp_trace_mgmt_pkt(QDF_DP_TRACE_MGMT_PACKET_RECORD, adapter->vdev_id, QDF_TRACE_DEFAULT_PDEV_ID, QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC)); - stainfo = hdd_get_stainfo(adapter->sta_info, - disassoc_comp->staMac); - if (stainfo) { - /* Send DHCP STOP indication to FW */ - stainfo->dhcp_phase = DHCP_PHASE_ACK; - if (stainfo->dhcp_nego_status == - DHCP_NEGO_IN_PROGRESS) - hdd_post_dhcp_ind(adapter, sta_id, - WMA_DHCP_STOP_IND); - stainfo->dhcp_nego_status = DHCP_NEGO_STOP; + stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + disassoc_comp->staMac.bytes); + if (!stainfo) { + hdd_err("Failed to find the right station"); + return QDF_STATUS_E_INVAL; } - /* STA id will be removed as a part of Phase 2 cleanup */ - hdd_softap_deregister_sta(adapter, sta_id, - disassoc_comp->staMac); + + /* Send DHCP STOP indication to FW */ + stainfo->dhcp_phase = DHCP_PHASE_ACK; + if (stainfo->dhcp_nego_status == + DHCP_NEGO_IN_PROGRESS) + hdd_post_dhcp_ind(adapter, + disassoc_comp->staMac.bytes, + WMA_DHCP_STOP_IND); + stainfo->dhcp_nego_status = DHCP_NEGO_STOP; + + hdd_softap_deregister_sta(adapter, stainfo); ap_ctx->ap_active = false; - spin_lock_bh(&adapter->sta_info_lock); - for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - if (adapter->sta_info[i].in_use - && i != - (WLAN_HDD_GET_AP_CTX_PTR(adapter))-> - broadcast_sta_id) { + + hdd_for_each_station(adapter->sta_info_list, stainfo, + index) { + if (!qdf_is_macaddr_broadcast( + &stainfo->sta_mac)) { ap_ctx->ap_active = true; break; } } - spin_unlock_bh(&adapter->sta_info_lock); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN wlan_hdd_auto_shutdown_enable(hdd_ctx, true); @@ -3353,10 +3354,12 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit) hdd_register_hostapd_wext(adapter->dev); /* Initialize the data path module */ - status = hdd_softap_init_tx_rx(adapter); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("hdd_softap_init_tx_rx failed"); - goto error_release_sap_session; + hdd_softap_init_tx_rx(adapter); + + status = hdd_sta_info_init(&adapter->sta_info_list); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("sta info init failed"); + goto error_release_softap_tx_rx; } status = hdd_wmm_adapter_init(adapter); @@ -3394,12 +3397,13 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit) /* rcpi info initialization */ qdf_mem_zero(&adapter->rcpi, sizeof(adapter->rcpi)); - hdd_exit(); return status; error_release_wmm: + hdd_sta_info_deinit(&adapter->sta_info_list); +error_release_softap_tx_rx: hdd_softap_deinit_tx_rx(adapter); error_release_sap_session: hdd_unregister_wext(adapter->dev); @@ -6590,8 +6594,9 @@ int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter) { struct sap_event sap_event; - int sta_id; + uint8_t index = 0; struct sap_context *sap_ctx; + struct hdd_station_info *sta_info; hdd_enter(); @@ -6601,31 +6606,24 @@ void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter) return; } - for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { - if (adapter->sta_info[sta_id].in_use) { - hdd_debug("sta_id: %d in_use: %d %pK", - sta_id, adapter->sta_info[sta_id].in_use, - adapter); + hdd_for_each_station(adapter->sta_info_list, sta_info, index) { + hdd_debug("sta_mac: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); - if (qdf_is_macaddr_broadcast( - &adapter->sta_info[sta_id].sta_mac)) - continue; + if (qdf_is_macaddr_broadcast(&sta_info->sta_mac)) + continue; - sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT; - qdf_mem_copy( - &sap_event.sapevt. - sapStationDisassocCompleteEvent.staMac, - &adapter->sta_info[sta_id].sta_mac, - sizeof(struct qdf_mac_addr)); - sap_event.sapevt.sapStationDisassocCompleteEvent. - reason = + sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT; + + qdf_mem_copy( + &sap_event.sapevt.sapStationDisassocCompleteEvent.staMac, + &sta_info->sta_mac, sizeof(struct qdf_mac_addr)); + + sap_event.sapevt.sapStationDisassocCompleteEvent.reason = eSAP_MAC_INITATED_DISASSOC; - sap_event.sapevt.sapStationDisassocCompleteEvent. - status_code = + sap_event.sapevt.sapStationDisassocCompleteEvent.status_code = QDF_STATUS_E_RESOURCES; - hdd_hostapd_sap_event_cb(&sap_event, - sap_ctx->user_context); - } + hdd_hostapd_sap_event_cb(&sap_event, sap_ctx->user_context); } hdd_exit(); @@ -6634,7 +6632,8 @@ void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter) bool hdd_is_peer_associated(struct hdd_adapter *adapter, struct qdf_mac_addr *mac_addr) { - uint32_t cnt; + uint8_t index = 0; + bool is_associated = false; struct hdd_station_info *sta_info; if (!adapter || !mac_addr) { @@ -6642,17 +6641,13 @@ bool hdd_is_peer_associated(struct hdd_adapter *adapter, return false; } - sta_info = adapter->sta_info; - spin_lock_bh(&adapter->sta_info_lock); - for (cnt = 0; cnt < WLAN_MAX_STA_COUNT; cnt++) { - if ((sta_info[cnt].in_use) && - !qdf_mem_cmp(&(sta_info[cnt].sta_mac), mac_addr, - QDF_MAC_ADDR_SIZE)) + hdd_for_each_station(adapter->sta_info_list, sta_info, index) { + if (!qdf_mem_cmp(&sta_info->sta_mac, mac_addr, + QDF_MAC_ADDR_SIZE)) { + is_associated = true; break; + } } - spin_unlock_bh(&adapter->sta_info_lock); - if (cnt != WLAN_MAX_STA_COUNT) - return true; - return false; + return is_associated; } diff --git a/core/hdd/src/wlan_hdd_hostapd_wext.c b/core/hdd/src/wlan_hdd_hostapd_wext.c index 42aab67ad4..0f0ead68aa 100644 --- a/core/hdd/src/wlan_hdd_hostapd_wext.c +++ b/core/hdd/src/wlan_hdd_hostapd_wext.c @@ -43,6 +43,7 @@ #include #include "wlan_mlme_ucfg_api.h" #include "wlan_reg_ucfg_api.h" +#include "wlan_hdd_sta_info.h" #define WE_WLAN_VERSION 1 /* WEXT limitation: MAX allowed buf len for any * @@ -144,7 +145,7 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, struct cdp_pdev *pdev = NULL; void *soc = NULL; struct cdp_txrx_stats_req req = {0}; - uint8_t count = 0; + uint8_t index = 0; struct hdd_station_info *sta_info; hdd_enter_dev(dev); @@ -171,23 +172,21 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, req.mac_id = value[2]; hdd_info("QCSAP_PARAM_SET_TXRX_STATS stats_id: %d mac_id: %d", req.stats, req.mac_id); - sta_info = adapter->sta_info; + if (value[1] == CDP_TXRX_STATS_28) { req.peer_addr = (char *)&adapter->mac_addr; ret = cdp_txrx_stats_request(soc, vdev, &req); - for (count = 0; count < WLAN_MAX_STA_COUNT; count++) { - if (sta_info->in_use) { - hdd_debug("sta: %d: bss_id: %pM", - sta_info->sta_id, - (void *)&sta_info->sta_mac); - req.peer_addr = - (char *)&sta_info->sta_mac; - ret = cdp_txrx_stats_request(soc, vdev, - &req); - } + hdd_for_each_station(adapter->sta_info_list, sta_info, + index) { + hdd_debug("bss_id: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY( + sta_info->sta_mac.bytes)); - sta_info++; + req.peer_addr = (char *) + &sta_info->sta_mac; + ret = cdp_txrx_stats_request( + soc, vdev, &req); } } else { ret = cdp_txrx_stats_request(soc, vdev, &req); @@ -339,72 +338,6 @@ static QDF_STATUS hdd_print_acl(struct hdd_adapter *adapter) return QDF_STATUS_SUCCESS; } -/** - * hdd_get_aid_rc() - Get AID and rate code passed from user - * @aid: pointer to AID - * @rc: pointer to rate code - * @set_value: value passed from user - * - * If target is 11ax capable, set_value will have AID left shifted 16 bits - * and 16 bits for rate code. If the target is not 11ax capable, rate code - * will only be 8 bits. - * - * Return: None - */ -static void hdd_get_aid_rc(uint8_t *aid, uint16_t *rc, int set_value) -{ - uint8_t rc_bits; - - if (sme_is_feature_supported_by_fw(DOT11AX)) - rc_bits = 16; - else - rc_bits = 8; - - *aid = set_value >> rc_bits; - *rc = set_value & ((1 << (rc_bits + 1)) - 1); -} - -/** - * hdd_set_peer_rate() - set peer rate - * @adapter: adapter being modified - * @set_value: rate code with AID - * - * Return: 0 on success, negative errno on failure - */ -static int hdd_set_peer_rate(struct hdd_adapter *adapter, int set_value) -{ - uint8_t aid, *peer_mac; - uint16_t rc; - QDF_STATUS status; - - if (adapter->device_mode != QDF_SAP_MODE) { - hdd_err("Invalid devicde mode - %d", adapter->device_mode); - return -EINVAL; - } - - hdd_get_aid_rc(&aid, &rc, set_value); - - if ((adapter->sta_info[aid].in_use) && - (OL_TXRX_PEER_STATE_CONN == adapter->sta_info[aid].peer_state)) { - peer_mac = - (uint8_t *)&(adapter->sta_info[aid].sta_mac.bytes[0]); - hdd_info("Peer AID: %d MAC_ADDR: "QDF_MAC_ADDR_STR, - aid, QDF_MAC_ADDR_ARRAY(peer_mac)); - } else { - hdd_err("No matching peer found for AID: %d", aid); - return -EINVAL; - } - - status = sme_set_peer_param(peer_mac, WMI_PEER_PARAM_FIXED_RATE, - rc, adapter->vdev_id); - if (status != QDF_STATUS_SUCCESS) { - hdd_err("Failed to set peer fixed rate - status: %d", status); - return -EIO; - } - - return 0; -} - int static __iw_softap_setparam(struct net_device *dev, struct iw_request_info *info, @@ -1053,9 +986,6 @@ static __iw_softap_setparam(struct net_device *dev, &adapter->session.ap. sap_config); break; - case QCASAP_SET_PEER_RATE: - ret = hdd_set_peer_rate(adapter, set_value); - break; case QCASAP_PARAM_DCM: hdd_debug("Set WMI_VDEV_PARAM_HE_DCM: %d", set_value); ret = wma_cli_set_command(adapter->vdev_id, @@ -1749,10 +1679,10 @@ static __iw_softap_getassoc_stamacaddr(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct hdd_adapter *adapter = (netdev_priv(dev)); - struct hdd_station_info *sta_info = adapter->sta_info; + struct hdd_station_info *sta_info; struct hdd_context *hdd_ctx; char *buf; - int cnt = 0; + int index = 0; int left; int ret; /* maclist_index must be u32 to match userspace */ @@ -1799,18 +1729,14 @@ static __iw_softap_getassoc_stamacaddr(struct net_device *dev, maclist_index = sizeof(maclist_index); left = wrqu->data.length - maclist_index; - spin_lock_bh(&adapter->sta_info_lock); - while ((cnt < WLAN_MAX_STA_COUNT) && (left >= QDF_MAC_ADDR_SIZE)) { - if ((sta_info[cnt].in_use) && - (!qdf_is_macaddr_broadcast(&sta_info[cnt].sta_mac))) { - memcpy(&buf[maclist_index], &(sta_info[cnt].sta_mac), + hdd_for_each_station(adapter->sta_info_list, sta_info, index) { + if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) { + memcpy(&buf[maclist_index], &sta_info->sta_mac, QDF_MAC_ADDR_SIZE); maclist_index += QDF_MAC_ADDR_SIZE; left -= QDF_MAC_ADDR_SIZE; } - cnt++; } - spin_unlock_bh(&adapter->sta_info_lock); *((u32 *) buf) = maclist_index; wrqu->data.length = maclist_index; @@ -2295,30 +2221,24 @@ static int hdd_softap_get_sta_info(struct hdd_adapter *adapter, uint8_t *buf, int size) { - int i; + uint8_t index = 0; int written; - uint8_t bc_sta_id; + struct hdd_station_info *sta; hdd_enter(); - bc_sta_id = WLAN_HDD_GET_AP_CTX_PTR(adapter)->broadcast_sta_id; - written = scnprintf(buf, size, "\nstaId staAddress\n"); - for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - struct hdd_station_info *sta = &adapter->sta_info[i]; + hdd_for_each_station(adapter->sta_info_list, sta, index) { if (written >= size - 1) break; - if (!sta->in_use) - continue; - - if (i == bc_sta_id) + if (QDF_IS_ADDR_BROADCAST(sta->sta_mac.bytes)) continue; written += scnprintf(buf + written, size - written, - "%5d "QDF_MAC_ADDR_STR" ecsa=%d\n", - sta->sta_id, + QDF_MAC_ADDR_STR + " ecsa=%d\n", sta->sta_mac.bytes[0], sta->sta_mac.bytes[1], sta->sta_mac.bytes[2], @@ -2527,7 +2447,8 @@ int __iw_get_softap_linkspeed(struct net_device *dev, struct qdf_mac_addr mac_address; char macaddr_string[MAC_ADDRESS_STR_LEN + 1]; QDF_STATUS status = QDF_STATUS_E_FAILURE; - int rc, ret, i; + int rc, ret; + uint8_t index = 0; hdd_enter_dev(dev); @@ -2567,14 +2488,12 @@ int __iw_get_softap_linkspeed(struct net_device *dev, * link speed for first connected client will be returned. */ if (wrqu->data.length < 17 || !QDF_IS_STATUS_SUCCESS(status)) { - for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - if (adapter->sta_info[i].in_use && - (!qdf_is_macaddr_broadcast - (&adapter->sta_info[i].sta_mac))) { - qdf_copy_macaddr( - &mac_address, - &adapter->sta_info[i]. - sta_mac); + struct hdd_station_info *sta_info; + + hdd_for_each_station(adapter->sta_info_list, sta_info, index) { + if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) { + qdf_copy_macaddr(&mac_address, + &sta_info->sta_mac); status = QDF_STATUS_SUCCESS; break; } @@ -3247,12 +3166,6 @@ static const struct iw_priv_args hostapd_private_args[] = { 0, "set_11ax_rate" } , - { - QCASAP_SET_PEER_RATE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_peer_rate" - } - , { QCASAP_PARAM_DCM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index fba90be178..e01d0ab429 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -173,6 +173,7 @@ #include "wlan_blm_ucfg_api.h" #include "ol_txrx.h" #include "nan_ucfg_api.h" +#include "wlan_hdd_sta_info.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -4854,6 +4855,10 @@ static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx, hdd_apf_context_destroy(adapter); qdf_spinlock_destroy(&adapter->vdev_lock); + if (adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) + hdd_sta_info_deinit(&adapter->sta_info_list); + wlan_hdd_debugfs_csr_deinit(adapter); if (adapter->device_mode == QDF_STA_MODE) hdd_sysfs_destroy_adapter_root_obj(adapter); @@ -6182,9 +6187,10 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx) struct hdd_adapter *adapter; struct hdd_station_ctx *sta_ctx; struct qdf_mac_addr peer_macaddr; - int sta_id; bool value; struct wlan_objmgr_vdev *vdev; + uint8_t index = 0; + struct hdd_station_info *sta_info; hdd_enter(); @@ -6287,19 +6293,17 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx) } else if (adapter->device_mode == QDF_P2P_GO_MODE) { clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags); - for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; - sta_id++) { - struct hdd_station_info sta = - adapter->sta_info[sta_id]; - if (sta.in_use) { - hdd_debug("[SSR] deregister STA with ID %d", - sta_id); - /* STA id will be removed */ - hdd_softap_deregister_sta(adapter, - sta_id, - sta.sta_mac); - sta.in_use = 0; - } + + hdd_for_each_station(adapter->sta_info_list, sta_info, + index) { + hdd_debug( + "[SSR] deregister STA MAC:" + QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY( + sta_info->sta_mac.bytes)); + hdd_softap_deregister_sta( + adapter, + sta_info); } } @@ -6316,6 +6320,10 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx) hdd_stop_tsf_sync(adapter); hdd_softap_deinit_tx_rx(adapter); + if (adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) + hdd_sta_info_deinit(&adapter->sta_info_list); + hdd_deregister_hl_netdev_fc_timer(adapter); hdd_deregister_tx_flow_control(adapter); @@ -15433,10 +15441,11 @@ bool hdd_is_connection_in_progress(uint8_t *out_vdev_id, { struct hdd_station_ctx *hdd_sta_ctx = NULL; struct hdd_adapter *adapter = NULL; - uint8_t sta_id = 0; + uint8_t index = 0; uint8_t *sta_mac = NULL; struct hdd_context *hdd_ctx; mac_handle_t mac_handle; + struct hdd_station_info *sta_info = NULL; hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -15483,6 +15492,7 @@ bool hdd_is_connection_in_progress(uint8_t *out_vdev_id, } return true; } + if ((QDF_STA_MODE == adapter->device_mode) || (QDF_P2P_CLIENT_MODE == adapter->device_mode) || (QDF_P2P_DEVICE_MODE == adapter->device_mode)) { @@ -15505,23 +15515,22 @@ bool hdd_is_connection_in_progress(uint8_t *out_vdev_id, } } else if ((QDF_SAP_MODE == adapter->device_mode) || (QDF_P2P_GO_MODE == adapter->device_mode)) { - for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; - sta_id++) { - if (!((adapter->sta_info[sta_id].in_use) - && (OL_TXRX_PEER_STATE_CONN == - adapter->sta_info[sta_id].peer_state))) + hdd_for_each_station(adapter->sta_info_list, sta_info, + index) { + if (sta_info->peer_state != + OL_TXRX_PEER_STATE_CONN) continue; - sta_mac = (uint8_t *) - &(adapter->sta_info[sta_id]. - sta_mac.bytes[0]); + sta_mac = sta_info->sta_mac.bytes; hdd_debug("client " QDF_MAC_ADDR_STR - " of SAP/GO is in middle of WPS/EAPOL exchange", - QDF_MAC_ADDR_ARRAY(sta_mac)); + " of SAP/GO is in middle of WPS/EAPOL exchange", + QDF_MAC_ADDR_ARRAY(sta_mac)); if (out_vdev_id && out_reason) { *out_vdev_id = adapter->vdev_id; - *out_reason = SAP_EAPOL_IN_PROGRESS; + *out_reason = + SAP_EAPOL_IN_PROGRESS; } + return true; } if (hdd_ctx->connection_in_progress) { diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index f4d018d4e6..fa4130994d 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -44,7 +44,7 @@ #include "wlan_ipa_ucfg_api.h" #include "wlan_policy_mgr_ucfg.h" #include -#include +#include "wlan_hdd_sta_info.h" /* Preprocessor definitions and constants */ #undef QCA_HDD_SAP_DUMP_SK_BUFF @@ -246,13 +246,14 @@ static inline struct sk_buff *hdd_skb_orphan(struct hdd_adapter *adapter, * * Return: error number */ -int hdd_post_dhcp_ind(struct hdd_adapter *adapter, - uint8_t sta_id, uint16_t type) +int hdd_post_dhcp_ind(struct hdd_adapter *adapter, uint8_t *mac_addr, + uint16_t type) { tAniDHCPInd pmsg; QDF_STATUS status = QDF_STATUS_SUCCESS; - hdd_debug("Post DHCP indication,sta_id=%d, type=%d", sta_id, type); + hdd_debug("Post DHCP indication,sta_mac=" QDF_MAC_ADDR_STR + " , type=%d", QDF_MAC_ADDR_ARRAY(mac_addr), type); if (!adapter) { hdd_err("NULL adapter"); @@ -266,7 +267,7 @@ int hdd_post_dhcp_ind(struct hdd_adapter *adapter, adapter->mac_addr.bytes, QDF_MAC_ADDR_SIZE); qdf_mem_copy(pmsg.peerMacAddr.bytes, - adapter->sta_info[sta_id].sta_mac.bytes, + mac_addr, QDF_MAC_ADDR_SIZE); status = wma_process_dhcp_ind(cds_get_context(QDF_MODULE_ID_WMA), @@ -292,8 +293,7 @@ int hdd_post_dhcp_ind(struct hdd_adapter *adapter, static void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf) { struct hdd_ap_ctx *hdd_ap_ctx; - struct qdf_mac_addr *dest_mac_addr; - uint8_t sta_id; + uint8_t *dest_mac_addr; struct hdd_adapter *adapter = context; if (hdd_validate_adapter(adapter)) @@ -305,59 +305,20 @@ static void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf) return; } - dest_mac_addr = (struct qdf_mac_addr *)(netbuf->data + - DHCP_CLIENT_MAC_ADDR_OFFSET); + dest_mac_addr = netbuf->data + DHCP_CLIENT_MAC_ADDR_OFFSET; - if (QDF_STATUS_SUCCESS != - hdd_softap_get_sta_id(adapter, - dest_mac_addr, &sta_id)) { - QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, - QDF_TRACE_LEVEL_INFO_HIGH, - "%s: Failed to find right station", __func__); - return; - } - - hdd_post_dhcp_ind(adapter, sta_id, WMA_DHCP_STOP_IND); + hdd_post_dhcp_ind(adapter, dest_mac_addr, WMA_DHCP_STOP_IND); } -/** - * hdd_softap_inspect_dhcp_packet() - Inspect DHCP packet - * @adapter: pointer to hdd adapter - * @skb: pointer to OS packet (sk_buff) - * @dir: direction - * - * Inspect the Tx/Rx frame, and send DHCP START/STOP notification to the FW - * through WMI message, during DHCP based IP address acquisition phase. - * - * - Send DHCP_START notification to FW when SAP gets DHCP Discovery - * - Send DHCP_STOP notification to FW when SAP sends DHCP ACK/NAK - * - * DHCP subtypes are determined by a status octet in the DHCP Message type - * option (option code 53 (0x35)). - * - * Each peer will be in one of 4 DHCP phases, starts from QDF_DHCP_PHASE_ACK, - * and transitioned per DHCP message type as it arrives. - * - * - QDF_DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase - * - QDF_DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase - * - QDF_DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase - * or ACK phase (Renewal process) - * - QDF_DHCP_PHASE_ACK : upon receiving DHCP_ACK/NAK message in REQUEST phase - * or DHCP_DELINE message in OFFER phase - * - * Return: error number - */ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, struct sk_buff *skb, enum qdf_proto_dir dir) { enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; struct hdd_station_info *hdd_sta_info; - uint8_t sta_id; int errno = 0; - struct qdf_mac_addr *src_mac; - QDF_STATUS status; - + struct qdf_mac_addr *src_mac, *macaddr = + (struct qdf_mac_addr *)(skb->data + QDF_NBUF_SRC_MAC_OFFSET); if (((adapter->device_mode == QDF_SAP_MODE) || (adapter->device_mode == QDF_P2P_GO_MODE)) && @@ -367,14 +328,15 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, src_mac = (struct qdf_mac_addr *)(skb->data + DHCP_CLIENT_MAC_ADDR_OFFSET); - status = hdd_softap_get_sta_id(adapter, src_mac, &sta_id); - if (status != QDF_STATUS_SUCCESS) { - hdd_err("invalid station id"); - return -EINVAL; - } subtype = qdf_nbuf_get_dhcp_subtype(skb); - hdd_sta_info = &adapter->sta_info[sta_id]; + hdd_sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + macaddr->bytes); + + if (!hdd_sta_info) { + hdd_err("Station not found"); + return -EINVAL; + } hdd_debug("ENTER: type=%d, phase=%d, nego_status=%d", subtype, @@ -386,8 +348,10 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, if (dir != QDF_RX) break; if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP) - errno = hdd_post_dhcp_ind(adapter, sta_id, - WMA_DHCP_START_IND); + errno = hdd_post_dhcp_ind( + adapter, + hdd_sta_info->sta_mac.bytes, + WMA_DHCP_START_IND); hdd_sta_info->dhcp_phase = DHCP_PHASE_DISCOVER; hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS; break; @@ -398,8 +362,10 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, if (dir != QDF_RX) break; if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP) - errno = hdd_post_dhcp_ind(adapter, sta_id, - WMA_DHCP_START_IND); + errno = hdd_post_dhcp_ind( + adapter, + hdd_sta_info->sta_mac.bytes, + WMA_DHCP_START_IND); hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS; case QDF_PROTO_DHCP_DECLINE: if (dir == QDF_RX) @@ -453,9 +419,11 @@ static void __hdd_softap_hard_start_xmit(struct sk_buff *skb, struct hdd_adapter *adapter = (struct hdd_adapter *) netdev_priv(dev); struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); struct hdd_context *hdd_ctx = adapter->hdd_ctx; - struct qdf_mac_addr *dest_mac_addr; - uint8_t sta_id; + struct qdf_mac_addr *dest_mac_addr, *mac_addr; + static struct qdf_mac_addr bcast_mac_addr = QDF_MAC_ADDR_BCAST_INIT; + uint32_t num_seg; + struct hdd_station_info *sta_info; ++adapter->hdd_stats.tx_rx_stats.tx_called; adapter->hdd_stats.tx_rx_stats.cont_txtimeout_cnt = 0; @@ -505,53 +473,41 @@ static void __hdd_softap_hard_start_xmit(struct sk_buff *skb, dest_mac_addr = (struct qdf_mac_addr *)skb->data; - if (QDF_NBUF_CB_GET_IS_BCAST(skb) || - QDF_NBUF_CB_GET_IS_MCAST(skb)) { - /* The BC/MC station ID is assigned during BSS - * starting phase. SAP will return the station ID - * used for BC/MC traffic. - */ - sta_id = ap_ctx->broadcast_sta_id; - } else { - if (QDF_STATUS_SUCCESS != - hdd_softap_get_sta_id(adapter, - dest_mac_addr, &sta_id)) { + /* In case of mcast, fetch the bcast sta_info. Else use the pkt addr */ + if (QDF_NBUF_CB_GET_IS_MCAST(skb)) + mac_addr = &bcast_mac_addr; + else + mac_addr = dest_mac_addr; + + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + mac_addr->bytes); + + if (!QDF_NBUF_CB_GET_IS_BCAST(skb) && !QDF_NBUF_CB_GET_IS_MCAST(skb)) { + if (!sta_info) { QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, "%s: Failed to find right station", __func__); goto drop_pkt; } - if (sta_id >= WLAN_MAX_STA_COUNT) { + if (sta_info->is_deauth_in_progress) { QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, - "%s: Failed to find right station", __func__); - goto drop_pkt; - } else if (!adapter->sta_info[sta_id].in_use) { - QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, - QDF_TRACE_LEVEL_INFO_HIGH, - "%s: STA %d is unregistered", __func__, - sta_id); - goto drop_pkt; - } else if (adapter->sta_info[sta_id]. - is_deauth_in_progress) { - QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, - QDF_TRACE_LEVEL_INFO_HIGH, - "%s: STA %d deauth in progress", __func__, - sta_id); + "%s: STA " QDF_MAC_ADDR_STR + "deauth in progress", __func__, + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); goto drop_pkt; } - if ((OL_TXRX_PEER_STATE_CONN != - adapter->sta_info[sta_id].peer_state) - && (OL_TXRX_PEER_STATE_AUTH != - adapter->sta_info[sta_id].peer_state)) { + if (sta_info->peer_state != OL_TXRX_PEER_STATE_CONN && + sta_info->peer_state != OL_TXRX_PEER_STATE_AUTH) { QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, "%s: Station not connected yet", __func__); goto drop_pkt; - } else if (OL_TXRX_PEER_STATE_CONN == - adapter->sta_info[sta_id].peer_state) { + } + + if (sta_info->peer_state == OL_TXRX_PEER_STATE_CONN) { if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) { QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, @@ -600,18 +556,21 @@ static void __hdd_softap_hard_start_xmit(struct sk_buff *skb, qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__); adapter->stats.tx_bytes += skb->len; - adapter->sta_info[sta_id].tx_bytes += skb->len; - if (qdf_nbuf_is_tso(skb)) { - num_seg = qdf_nbuf_get_tso_num_seg(skb); - adapter->stats.tx_packets += num_seg; - adapter->sta_info[sta_id].tx_packets += num_seg; - } else { - ++adapter->stats.tx_packets; - adapter->sta_info[sta_id].tx_packets++; - hdd_ctx->no_tx_offload_pkt_cnt++; + if (sta_info) { + sta_info->tx_bytes += skb->len; + + if (qdf_nbuf_is_tso(skb)) { + num_seg = qdf_nbuf_get_tso_num_seg(skb); + adapter->stats.tx_packets += num_seg; + sta_info->tx_packets += num_seg; + } else { + ++adapter->stats.tx_packets; + sta_info->tx_packets++; + hdd_ctx->no_tx_offload_pkt_cnt++; + } + sta_info->last_tx_rx_ts = qdf_system_ticks(); } - adapter->sta_info[sta_id].last_tx_rx_ts = qdf_system_ticks(); QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(skb) = 0; @@ -639,8 +598,9 @@ static void __hdd_softap_hard_start_xmit(struct sk_buff *skb, if (adapter->tx_fn(adapter->txrx_vdev, (qdf_nbuf_t)skb) != NULL) { QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, - "%s: Failed to send packet to txrx for sta_id:%d", - __func__, sta_id); + "%s: Failed to send packet to txrx for sta: " + QDF_MAC_ADDR_STR, __func__, + QDF_MAC_ADDR_ARRAY(dest_mac_addr->bytes)); ++adapter->hdd_stats.tx_rx_stats.tx_dropped_ac[ac]; goto drop_pkt_and_release_skb; } @@ -756,22 +716,9 @@ void hdd_softap_tx_timeout(struct net_device *net_dev) osif_vdev_sync_op_stop(vdev_sync); } -QDF_STATUS hdd_softap_init_tx_rx(struct hdd_adapter *adapter) +void hdd_softap_init_tx_rx(struct hdd_adapter *adapter) { - QDF_STATUS status = QDF_STATUS_SUCCESS; - - uint8_t STAId = 0; - qdf_mem_zero(&adapter->stats, sizeof(struct net_device_stats)); - - spin_lock_init(&adapter->sta_info_lock); - - for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) { - qdf_mem_zero(&adapter->sta_info[STAId], - sizeof(struct hdd_station_info)); - } - - return status; } QDF_STATUS hdd_softap_deinit_tx_rx(struct hdd_adapter *adapter) @@ -787,47 +734,34 @@ QDF_STATUS hdd_softap_deinit_tx_rx(struct hdd_adapter *adapter) } QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter, - uint8_t sta_id, struct qdf_mac_addr *sta_mac) { - spin_lock_bh(&adapter->sta_info_lock); - if (adapter->sta_info[sta_id].in_use) { - spin_unlock_bh(&adapter->sta_info_lock); - hdd_err("Reinit of in use station %d", sta_id); + struct hdd_station_info *sta_info; + QDF_STATUS status; + + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + sta_mac->bytes); + + if (sta_info) { + hdd_err("Reinit of in use station " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_mac->bytes)); return QDF_STATUS_E_FAILURE; } - qdf_mem_zero(&adapter->sta_info[sta_id], - sizeof(struct hdd_station_info)); + sta_info = qdf_mem_malloc(sizeof(struct hdd_station_info)); + if (!sta_info) + return QDF_STATUS_E_NOMEM; - adapter->sta_info[sta_id].in_use = true; - adapter->sta_info[sta_id].is_deauth_in_progress = false; - qdf_copy_macaddr(&adapter->sta_info[sta_id].sta_mac, sta_mac); + sta_info->is_deauth_in_progress = false; + qdf_mem_copy(&sta_info->sta_mac, sta_mac, sizeof(struct qdf_mac_addr)); - spin_unlock_bh(&adapter->sta_info_lock); - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS hdd_softap_deinit_tx_rx_sta(struct hdd_adapter *adapter, - uint8_t sta_id) -{ - QDF_STATUS status = QDF_STATUS_SUCCESS; - struct hdd_hostapd_state *hostapd_state; - - hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); - - spin_lock_bh(&adapter->sta_info_lock); - - if (false == adapter->sta_info[sta_id].in_use) { - spin_unlock_bh(&adapter->sta_info_lock); - hdd_err("Deinit station not inited %d", sta_id); - return QDF_STATUS_E_FAILURE; + status = hdd_sta_info_attach(&adapter->sta_info_list, sta_info); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to attach station: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_mac->bytes)); + qdf_mem_free(sta_info); } - adapter->sta_info[sta_id].in_use = false; - adapter->sta_info[sta_id].is_deauth_in_progress = false; - - spin_unlock_bh(&adapter->sta_info_lock); return status; } @@ -889,7 +823,7 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf) struct sk_buff *next = NULL; struct hdd_context *hdd_ctx = NULL; struct qdf_mac_addr *src_mac; - uint8_t sta_id; + struct hdd_station_info *sta_info; /* Sanity check on inputs */ if (unlikely((!adapter_context) || (!rx_buf))) { @@ -945,16 +879,14 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf) /* Send DHCP Indication to FW */ src_mac = (struct qdf_mac_addr *)(skb->data + QDF_NBUF_SRC_MAC_OFFSET); - if (QDF_STATUS_SUCCESS == - hdd_softap_get_sta_id(adapter, src_mac, &sta_id)) { - if (sta_id < WLAN_MAX_STA_COUNT) { - adapter->sta_info[sta_id].rx_packets++; - adapter->sta_info[sta_id].rx_bytes += skb->len; - adapter->sta_info[sta_id].last_tx_rx_ts = - qdf_system_ticks(); - hdd_softap_inspect_dhcp_packet(adapter, skb, - QDF_RX); - } + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + (uint8_t *)src_mac); + + if (sta_info) { + sta_info->rx_packets++; + sta_info->rx_bytes += skb->len; + sta_info->last_tx_rx_ts = qdf_system_ticks(); + hdd_softap_inspect_dhcp_packet(adapter, skb, QDF_RX); } hdd_event_eapol_log(skb, QDF_RX); @@ -1002,11 +934,11 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf) } QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter, - uint8_t sta_id, - struct qdf_mac_addr mac_addr) + struct hdd_station_info *sta_info) { QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; struct hdd_context *hdd_ctx; + struct qdf_mac_addr *mac_addr; if (!adapter) { hdd_err("NULL adapter"); @@ -1018,40 +950,55 @@ QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter, return QDF_STATUS_E_INVAL; } - hdd_ctx = WLAN_HDD_GET_CTX(adapter); - - if (sta_id >= WLAN_MAX_STA_COUNT) { - hdd_err("Error: Invalid sta_id: %u", sta_id); + if (!sta_info) { + hdd_err("Invalid station"); return QDF_STATUS_E_INVAL; } + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (!hdd_ctx) { + hdd_err("HDD context is null"); + return QDF_STATUS_E_INVAL; + } + + /* + * If the address is a broadcast address then the CDP layers expects + * the self mac address of the adapter. + */ + if (QDF_IS_ADDR_BROADCAST(sta_info->sta_mac.bytes)) + mac_addr = &adapter->mac_addr; + else + mac_addr = &sta_info->sta_mac; + /* Clear station in TL and then update HDD data * structures. This helps to block RX frames from other * station to this station. */ - qdf_status = cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC), + + hdd_debug("Deregistering sta: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); + + qdf_status = cdp_clear_peer( + cds_get_context(QDF_MODULE_ID_SOC), (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX), - mac_addr); + *mac_addr); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - hdd_err("cdp_clear_peer failed for staID %d, Status=%d [0x%08X]", - sta_id, qdf_status, qdf_status); + hdd_err("cdp_clear_peer failed for sta: " QDF_MAC_ADDR_STR + ", Status=%d [0x%08X]", + QDF_MAC_ADDR_ARRAY(mac_addr->bytes), qdf_status, + qdf_status); } - if (adapter->sta_info[sta_id].in_use) { - if (ucfg_ipa_is_enabled()) { - if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev, - adapter->device_mode, - adapter->vdev_id, - WLAN_IPA_CLIENT_DISCONNECT, - adapter->sta_info[sta_id].sta_mac. - bytes) != QDF_STATUS_SUCCESS) - hdd_err("WLAN_CLIENT_DISCONNECT event failed"); - } - spin_lock_bh(&adapter->sta_info_lock); - qdf_mem_zero(&adapter->sta_info[sta_id], - sizeof(struct hdd_station_info)); - spin_unlock_bh(&adapter->sta_info_lock); + if (ucfg_ipa_is_enabled()) { + if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev, + adapter->device_mode, + adapter->vdev_id, + WLAN_IPA_CLIENT_DISCONNECT, + mac_addr->bytes) != QDF_STATUS_SUCCESS) + hdd_err("WLAN_CLIENT_DISCONNECT event failed"); } + hdd_sta_info_detach(&adapter->sta_info_list, sta_info); ucfg_mlme_update_oce_flags(hdd_ctx->pdev); @@ -1073,42 +1020,43 @@ QDF_STATUS hdd_softap_register_sta(struct hdd_adapter *adapter, void *pdev = cds_get_context(QDF_MODULE_ID_TXRX); struct cdp_vdev *txrx_vdev = NULL; struct hdd_ap_ctx *ap_ctx; - - hdd_info("STA:%u, Auth:%u, Priv:%u, WMM:%u", - sta_id, auth_required, privacy_required, wmm_enabled); + struct hdd_station_info *sta_info; ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); - if (!ap_ctx) - hdd_err("Invalid AP context"); - - if (sta_id >= WLAN_MAX_STA_COUNT) { - hdd_err("Error: Invalid sta_id: %u", sta_id); - return qdf_status; - } /* * Clean up old entry if it is not cleaned up properly */ - if (adapter->sta_info[sta_id].in_use) { - hdd_info("clean up old entry for STA %d", sta_id); - hdd_softap_deregister_sta(adapter, sta_id, - adapter->sta_info[sta_id].sta_mac); + + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + sta_mac->bytes); + if (sta_info) { + hdd_info("clean up old entry for STA MAC " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_mac->bytes)); + hdd_softap_deregister_sta(adapter, sta_info); } /* Get the Station ID from the one saved during the association. */ txrx_desc.sta_id = sta_id; - /* * If the address is a broadcast address, then provide the self mac addr * to the data path. Else provide the mac address of the connected peer. */ if (qdf_is_macaddr_broadcast(sta_mac) && ap_ctx) - qdf_copy_macaddr(&txrx_desc.peer_addr, - &ap_ctx->sap_context->bssid); + qdf_mem_copy(&txrx_desc.peer_addr, &adapter->mac_addr, + QDF_MAC_ADDR_SIZE); else - qdf_copy_macaddr(&txrx_desc.peer_addr, sta_mac); + qdf_mem_copy(&txrx_desc.peer_addr, sta_mac, + QDF_MAC_ADDR_SIZE); - qdf_status = hdd_softap_init_tx_rx_sta(adapter, sta_id, sta_mac); + qdf_status = hdd_softap_init_tx_rx_sta(adapter, sta_mac); + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + sta_mac->bytes); + + if (!sta_info) { + hdd_err("STA not found"); + return QDF_STATUS_E_INVAL; + } txrx_desc.is_qos_enabled = wmm_enabled; @@ -1156,32 +1104,38 @@ QDF_STATUS hdd_softap_register_sta(struct hdd_adapter *adapter, * put TL directly into 'authenticated' state */ - adapter->sta_info[sta_id].sta_id = sta_id; - adapter->sta_info[sta_id].is_qos_enabled = wmm_enabled; + sta_info->is_qos_enabled = wmm_enabled; if (!auth_required) { - hdd_info("open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", - adapter->sta_info[sta_id].sta_id); + hdd_info("open/shared auth STA MAC= " QDF_MAC_ADDR_STR + ". Changing TL state to AUTHENTICATED at Join time", + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); /* Connections that do not need Upper layer auth, * transition TL directly to 'Authenticated' state. */ - qdf_status = hdd_change_peer_state(adapter, txrx_desc.sta_id, - OL_TXRX_PEER_STATE_AUTH, false); + qdf_status = hdd_change_peer_state(adapter, + txrx_desc.peer_addr.bytes, + OL_TXRX_PEER_STATE_AUTH, + false); - adapter->sta_info[sta_id].peer_state = OL_TXRX_PEER_STATE_AUTH; + sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH; if (!qdf_is_macaddr_broadcast(sta_mac)) qdf_status = wlan_hdd_send_sta_authorized_event( adapter, hdd_ctx, sta_mac); } else { - hdd_info("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", - adapter->sta_info[sta_id].sta_id); + hdd_info("ULA auth STA MAC = " QDF_MAC_ADDR_STR + ". Changing TL state to CONNECTED at Join time", + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); - qdf_status = hdd_change_peer_state(adapter, txrx_desc.sta_id, - OL_TXRX_PEER_STATE_CONN, false); - adapter->sta_info[sta_id].peer_state = OL_TXRX_PEER_STATE_CONN; + qdf_status = hdd_change_peer_state(adapter, + txrx_desc.peer_addr.bytes, + OL_TXRX_PEER_STATE_CONN, + false); + + sta_info->peer_state = OL_TXRX_PEER_STATE_CONN; } hdd_debug("Enabling queues"); @@ -1221,28 +1175,15 @@ QDF_STATUS hdd_softap_register_bc_sta(struct hdd_adapter *adapter, return qdf_status; } -/** - * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA - * @adapter: pointer to adapter context - * - * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error - */ -static QDF_STATUS hdd_softap_deregister_bc_sta(struct hdd_adapter *adapter) -{ - struct hdd_ap_ctx *ap_ctx; - - ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); - - return hdd_softap_deregister_sta(adapter, ap_ctx->broadcast_sta_id, - adapter->mac_addr); -} - QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - uint8_t sta_id = 0, indoor_chnl_marking = 0; + uint8_t indoor_chnl_marking = 0; struct hdd_context *hdd_ctx; struct hdd_ap_ctx *ap_ctx; + uint16_t index; + struct hdd_station_info *sta_info; + struct hdd_sta_info_entry *tmp; hdd_ctx = WLAN_HDD_GET_CTX(adapter); ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); @@ -1255,24 +1196,17 @@ QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter) * driver unload in progress check otherwise it can lead to peer * object leak */ - status = hdd_softap_deregister_bc_sta(adapter); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("Failed to deregister BC sta Id %d", - ap_ctx->broadcast_sta_id); + hdd_for_each_station_safe(adapter->sta_info_list, sta_info, + index, tmp) { + status = hdd_softap_deregister_sta(adapter, + sta_info); - for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { - /* This excludes BC sta as it is already deregistered */ - if (adapter->sta_info[sta_id].in_use) { - status = hdd_softap_deregister_sta( - adapter, sta_id, - adapter->sta_info[sta_id].sta_mac); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("Failed to deregister sta Id %d", - sta_id); - } - } + if (QDF_IS_STATUS_ERROR(status) && sta_info) + hdd_err("Deregistering STA " QDF_MAC_ADDR_STR " failed", + QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes)); } + if (adapter->device_mode == QDF_SAP_MODE && !hdd_ctx->config->disable_channel) wlan_hdd_restore_channels(hdd_ctx, true); @@ -1301,31 +1235,34 @@ QDF_STATUS hdd_softap_change_sta_state(struct hdd_adapter *adapter, struct qdf_mac_addr *sta_mac, enum ol_txrx_peer_state state) { - uint8_t sta_id = WLAN_MAX_STA_COUNT; QDF_STATUS qdf_status; + struct hdd_station_info *sta_info; + struct qdf_mac_addr mac_addr; hdd_enter_dev(adapter->dev); - qdf_status = hdd_softap_get_sta_id(adapter, sta_mac, &sta_id); - if (QDF_STATUS_SUCCESS != qdf_status) { - hdd_err("Failed to find right station"); - return qdf_status; + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + sta_mac->bytes); + + if (!sta_info) { + hdd_err("Failed to find right station MAC: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(sta_mac->bytes)); + return QDF_STATUS_E_INVAL; } - if (false == - qdf_is_macaddr_equal(&adapter->sta_info[sta_id].sta_mac, - sta_mac)) { - hdd_err("Station %u MAC address not matching", sta_id); - return QDF_STATUS_E_FAILURE; - } + if (qdf_is_macaddr_broadcast(&sta_info->sta_mac)) + qdf_mem_copy(&mac_addr, &adapter->mac_addr, QDF_MAC_ADDR_SIZE); + else + qdf_mem_copy(&mac_addr, sta_mac, QDF_MAC_ADDR_SIZE); qdf_status = - hdd_change_peer_state(adapter, sta_id, state, false); - hdd_info("Station %u changed to state %d", sta_id, state); + hdd_change_peer_state(adapter, mac_addr.bytes, + state, false); + hdd_info("Station " QDF_MAC_ADDR_STR " changed to state %d", + QDF_MAC_ADDR_ARRAY(mac_addr.bytes), state); if (QDF_STATUS_SUCCESS == qdf_status) { - adapter->sta_info[sta_id].peer_state = - OL_TXRX_PEER_STATE_AUTH; + sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH; p2p_peer_authorized(adapter->vdev, sta_mac->bytes); } @@ -1333,20 +1270,3 @@ QDF_STATUS hdd_softap_change_sta_state(struct hdd_adapter *adapter, return qdf_status; } -QDF_STATUS hdd_softap_get_sta_id(struct hdd_adapter *adapter, - struct qdf_mac_addr *sta_mac, - uint8_t *sta_id) -{ - uint8_t i; - - for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - if (!qdf_mem_cmp - (&adapter->sta_info[i].sta_mac, sta_mac, - QDF_MAC_ADDR_SIZE) && adapter->sta_info[i].in_use) { - *sta_id = i; - return QDF_STATUS_SUCCESS; - } - } - - return QDF_STATUS_E_FAILURE; -} diff --git a/core/hdd/src/wlan_hdd_sta_info.c b/core/hdd/src/wlan_hdd_sta_info.c new file mode 100644 index 0000000000..961b05f10d --- /dev/null +++ b/core/hdd/src/wlan_hdd_sta_info.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * 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. + */ + +/** + * DOC: wlan_hdd_sta_info.c + * + * Store and manage station info structure. + * + */ + +#include "wlan_hdd_sta_info.h" +#include + +/* Generate a numeric constant to form the key to be provided for hashing */ +#define WLAN_HDD_STA_INFO_HASH(addr) \ + (((const uint8_t *)addr)[QDF_MAC_ADDR_SIZE - 1]) + +QDF_STATUS hdd_sta_info_init(struct hdd_sta_info_obj *sta_info_container) +{ + if (!sta_info_container) { + hdd_err("Parameter null"); + return QDF_STATUS_E_INVAL; + } + + qdf_spinlock_create(&sta_info_container->sta_obj_lock); + qdf_ht_init(sta_info_container->sta_obj); + + return QDF_STATUS_SUCCESS; +} + +void hdd_sta_info_deinit(struct hdd_sta_info_obj *sta_info_container) +{ + if (!sta_info_container) { + hdd_err("Parameter null"); + return; + } + + qdf_ht_deinit(sta_info_container->sta_obj); + qdf_spinlock_destroy(&sta_info_container->sta_obj_lock); +} + +QDF_STATUS hdd_sta_info_attach(struct hdd_sta_info_obj *sta_info_container, + struct hdd_station_info *sta_info) +{ + if (!sta_info_container || !sta_info) { + hdd_err("Parameter(s) null"); + return QDF_STATUS_E_INVAL; + } + + qdf_spin_lock_bh(&sta_info_container->sta_obj_lock); + + qdf_ht_add(sta_info_container->sta_obj, &sta_info->sta_node, + WLAN_HDD_STA_INFO_HASH(sta_info->sta_mac.bytes)); + + qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock); + + return QDF_STATUS_SUCCESS; +} + +void hdd_sta_info_detach(struct hdd_sta_info_obj *sta_info_container, + struct hdd_station_info *sta_info) +{ + if (!sta_info_container || !sta_info) { + hdd_err("Parameter(s) null"); + return; + } + + qdf_spin_lock_bh(&sta_info_container->sta_obj_lock); + + qdf_ht_remove(&sta_info->sta_node); + + qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock); + + qdf_mem_free(sta_info); + sta_info = NULL; +} + +struct hdd_station_info *hdd_get_sta_info_by_mac( + struct hdd_sta_info_obj *sta_info_container, + const uint8_t *mac_addr) +{ + struct hdd_station_info *sta_info = NULL; + + if (!mac_addr || !sta_info_container) { + hdd_err("Parameter(s) null"); + return NULL; + } + + qdf_spin_lock_bh(&sta_info_container->sta_obj_lock); + + qdf_ht_for_each_in_bucket(sta_info_container->sta_obj, sta_info, + sta_node, WLAN_HDD_STA_INFO_HASH(mac_addr)) { + if (qdf_is_macaddr_equal(&sta_info->sta_mac, + (struct qdf_mac_addr *)mac_addr)) { + qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock); + return sta_info; + } + } + + qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock); + + return NULL; +} diff --git a/core/hdd/src/wlan_hdd_sta_info.h b/core/hdd/src/wlan_hdd_sta_info.h new file mode 100644 index 0000000000..9e98adc54d --- /dev/null +++ b/core/hdd/src/wlan_hdd_sta_info.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * 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. + */ + +/** + * DOC: wlan_hdd_sta_info.h + * + * Store and manage station info structure. + * + */ +#if !defined(__WLAN_HDD_STA_INFO_H) +#define __WLAN_HDD_STA_INFO_H + +#include "qdf_lock.h" +#include "qdf_types.h" +#include "qdf_hashtable.h" +#include "sap_api.h" +#include "cdp_txrx_cmn_struct.h" +#include "sir_mac_prot_def.h" +#include + +/* A bucket size of 2^4 = 16 */ +#define WLAN_HDD_STA_INFO_SIZE 4 + +/* Opaque handle for abstraction */ +#define hdd_sta_info_entry qdf_ht_entry + +/** + * struct dhcp_phase - Per Peer DHCP Phases + * @DHCP_PHASE_ACK: upon receiving DHCP_ACK/NAK message in REQUEST phase or + * DHCP_DELINE message in OFFER phase + * @DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase + * @DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase + * @DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase or + * ACK phase (Renewal process) + */ +enum dhcp_phase { + DHCP_PHASE_ACK, + DHCP_PHASE_DISCOVER, + DHCP_PHASE_OFFER, + DHCP_PHASE_REQUEST +}; + +/** + * struct dhcp_nego_status - Per Peer DHCP Negotiation Status + * @DHCP_NEGO_STOP: when the peer is in ACK phase or client disassociated + * @DHCP_NEGO_IN_PROGRESS: when the peer is in DISCOVER or REQUEST + * (Renewal process) phase + */ +enum dhcp_nego_status { + DHCP_NEGO_STOP, + DHCP_NEGO_IN_PROGRESS +}; + +/** + * struct hdd_station_info - Per station structure kept in HDD for + * multiple station support for SoftAP + * @in_use: Is the station entry in use? + * @sta_id: Station ID reported back from HAL (through SAP). + * Broadcast uses station ID zero by default. + * @sta_type: Type of station i.e. p2p client or infrastructure station + * @sta_mac: MAC address of the station + * @peer_state: Current Station state so HDD knows how to deal with packet + * queue. Most recent states used to change TLSHIM STA state. + * @is_qos_enabled: Track QoS status of station + * @is_deauth_in_progress: The station entry for which Deauth is in progress + * @nss: Number of spatial streams supported + * @rate_flags: Rate Flags for this connection + * @ecsa_capable: Extended CSA capabilities + * @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc. + * @tx_packets: Packets send to current station + * @tx_bytes: Bytes send to current station + * @rx_packets: Packets received from current station + * @rx_bytes: Bytes received from current station + * @last_tx_rx_ts: Last tx/rx timestamp with current station + * @assoc_ts: Current station association timestamp + * @tx_rate: Tx rate with current station reported from F/W + * @rx_rate: Rx rate with current station reported from F/W + * @ampdu: Ampdu enable or not of the station + * @sgi_enable: Short GI enable or not of the station + * @tx_stbc: Tx Space-time block coding enable/disable + * @rx_stbc: Rx Space-time block coding enable/disable + * @ch_width: Channel Width of the connection + * @mode: Mode of the connection + * @max_supp_idx: Max supported rate index of the station + * @max_ext_idx: Max extended supported rate index of the station + * @max_mcs_idx: Max supported mcs index of the station + * @rx_mcs_map: VHT Rx mcs map + * @tx_mcs_map: VHT Tx mcs map + * @freq : Frequency of the current station + * @dot11_mode: 802.11 Mode of the connection + * @ht_present: HT caps present or not in the current station + * @vht_present: VHT caps present or not in the current station + * @ht_caps: HT capabilities of current station + * @vht_caps: VHT capabilities of current station + * @reason_code: Disconnection reason code for current station + * @rssi: RSSI of the current station reported from F/W + * @capability: Capability information of current station + * @support_mode: Max supported mode of a station currently + * connected to sap + * @rx_retry_cnt: Number of rx retries received from current station + * Currently this feature is not supported from FW + * @rx_mc_bc_cnt: Multicast broadcast packet count received from + * current station + * MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt + * feature or not, if first bit is 1 it indicates that FW supports this + * feature, if it is 0 it indicates FW doesn't support this feature + * @sta_info: The sta_info node for the station info list maintained in adapter + */ +struct hdd_station_info { + bool in_use; + uint8_t sta_id; + eStationType sta_type; + struct qdf_mac_addr sta_mac; + enum ol_txrx_peer_state peer_state; + bool is_qos_enabled; + bool is_deauth_in_progress; + uint8_t nss; + uint32_t rate_flags; + uint8_t ecsa_capable; + uint32_t max_phy_rate; + uint32_t tx_packets; + uint64_t tx_bytes; + uint32_t rx_packets; + uint64_t rx_bytes; + qdf_time_t last_tx_rx_ts; + qdf_time_t assoc_ts; + qdf_time_t disassoc_ts; + uint32_t tx_rate; + uint32_t rx_rate; + bool ampdu; + bool sgi_enable; + bool tx_stbc; + bool rx_stbc; + tSirMacHTChannelWidth ch_width; + uint8_t mode; + uint8_t max_supp_idx; + uint8_t max_ext_idx; + uint8_t max_mcs_idx; + uint8_t rx_mcs_map; + uint8_t tx_mcs_map; + uint32_t freq; + uint8_t dot11_mode; + bool ht_present; + bool vht_present; + struct ieee80211_ht_cap ht_caps; + struct ieee80211_vht_cap vht_caps; + uint32_t reason_code; + int8_t rssi; + enum dhcp_phase dhcp_phase; + enum dhcp_nego_status dhcp_nego_status; + uint16_t capability; + uint8_t support_mode; + uint32_t rx_retry_cnt; + uint32_t rx_mc_bc_cnt; + struct qdf_ht_entry sta_node; +}; + +/** + * struct hdd_sta_info_obj - Station info container structure + * @sta_obj: The sta info object that stores the sta_info + * @sta_obj_lock: Lock to protect the sta_obj read/write access + */ +struct hdd_sta_info_obj { + qdf_ht_declare(sta_obj, WLAN_HDD_STA_INFO_SIZE); + qdf_spinlock_t sta_obj_lock; +}; + +/** + * hdd_for_each_station - Iterate over each station stored in the sta info + * container + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * @sta_info: The station info structure that acts as the iterator object. + * @index: The current index in which the current station is present. + * + * The sta_info will contain the structure that is fetched for that particular + * iteration. The index of the current iterator object in the container + * represents the bucket at which the given station info is stored. + */ +#define hdd_for_each_station(sta_info_container, sta_info, index) \ + qdf_ht_for_each(sta_info_container.sta_obj, index, sta_info, sta_node) + +/** + * hdd_for_each_station_safe - Iterate over each station stored in the sta info + * container being safe for removal of the sta info + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * @sta_info: The station info structure that acts as the iterator object. + * @index: The current index in which the current station is present. + * @tmp: A &struct for temporary storage + * + * The sta_info will contain the structure that is fetched for that particular + * iteration. The index of the current iterator object in the container + * represents the bucket at which the given station info is stored. + */ +#define hdd_for_each_station_safe(sta_info_container, sta_info, index, tmp) \ + qdf_ht_for_each_safe(sta_info_container.sta_obj, index, tmp, \ + sta_info, sta_node) + +/** + * wlan_sta_info_init() - Initialise the wlan hdd station info container obj + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * + * Return: QDF_STATUS_SUCCESS on success, failure code otherwise + */ +QDF_STATUS hdd_sta_info_init(struct hdd_sta_info_obj *sta_info_container); + +/** + * wlan_sta_info_deinit() - Deinit the wlan hdd station info container obj + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * + * Return: None + */ +void hdd_sta_info_deinit(struct hdd_sta_info_obj *sta_info_container); + +/** + * hdd_sta_info_detach() - Detach the station info structure from the list + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * @sta_info: The station info structure that has to be detached from the + * container object. + * + * Return: None + */ +void hdd_sta_info_detach(struct hdd_sta_info_obj *sta_info_container, + struct hdd_station_info *sta_info); + +/** + * hdd_sta_info_attach() - Attach the station info structure into the list + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * @sta_info: The station info structure that is to be attached to the + * container object. + * + * Return: QDF STATUS SUCCESS on successful attach, error code otherwise + */ +QDF_STATUS hdd_sta_info_attach(struct hdd_sta_info_obj *sta_info_container, + struct hdd_station_info *sta_info); + +/** + * hdd_get_sta_info_by_mac() - Find the sta_info structure by mac addr + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * @mac_addr: The mac addr by which the sta_info has to be fetched. + * + * Return: Pointer to the hdd_station_info structure which contains the mac + * address passed + */ +struct hdd_station_info *hdd_get_sta_info_by_mac( + struct hdd_sta_info_obj *sta_info_container, + const uint8_t *mac_addr); + +#endif /* __WLAN_HDD_STA_INFO_H */ diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c index 601fcd1e9c..48da5ca869 100644 --- a/core/hdd/src/wlan_hdd_station_info.c +++ b/core/hdd/src/wlan_hdd_station_info.c @@ -34,6 +34,7 @@ #include #include #include "wlan_mlme_ucfg_api.h" +#include "wlan_hdd_sta_info.h" /* * define short names for the global vendor params @@ -1225,10 +1226,11 @@ static int hdd_get_station_remote(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, struct qdf_mac_addr mac_addr) { - struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info, - mac_addr); int status = 0; bool is_associated = false; + struct hdd_station_info *stainfo = + hdd_get_sta_info_by_mac(&adapter->sta_info_list, + mac_addr.bytes); if (!stainfo) { status = hdd_get_cached_station_remote(hdd_ctx, adapter, diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index cf4faa8d14..66d0c9c8a3 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -40,6 +40,7 @@ #include "wlan_cp_stats_mc_ucfg_api.h" #include "wlan_mlme_ucfg_api.h" #include "wlan_mlme_ucfg_api.h" +#include "wlan_hdd_sta_info.h" #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS) #define HDD_INFO_SIGNAL STATION_INFO_SIGNAL @@ -3908,7 +3909,6 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy, struct sir_peer_info_ext peer_info; struct hdd_fw_txrx_stats txrx_stats; int status; - int i; status = wlan_hdd_validate_context(hddctx); if (status != 0) @@ -3916,15 +3916,7 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy, hdd_debug("get peer %pM info", mac); - for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { - if (!qdf_mem_cmp(adapter->sta_info[i].sta_mac.bytes, - mac, - QDF_MAC_ADDR_SIZE)) { - stainfo = &adapter->sta_info[i]; - break; - } - } - + stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list, mac); if (!stainfo) { hdd_err("peer %pM not found", mac); return -EINVAL;