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
This commit is contained in:
Sourav Mohapatra
2019-08-18 11:39:23 +05:30
committed by nshrivas
parent c65a60b93b
commit 43e6dea453
18 changed files with 996 additions and 909 deletions

1
Kbuild
View File

@@ -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_regulatory.o \
$(HDD_SRC_DIR)/wlan_hdd_scan.o \ $(HDD_SRC_DIR)/wlan_hdd_scan.o \
$(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.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_stats.o \
$(HDD_SRC_DIR)/wlan_hdd_trace.o \ $(HDD_SRC_DIR)/wlan_hdd_trace.o \
$(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \ $(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \

View File

@@ -555,7 +555,7 @@ QDF_STATUS wlan_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc,
bool value); 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 * for broadcast deauth in sap
* @psoc: pointer to psoc object * @psoc: pointer to psoc object
* @value: Value that needs to get from the caller * @value: Value that needs to get from the caller
@@ -563,7 +563,7 @@ QDF_STATUS wlan_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc,
* Return: QDF Status * Return: QDF Status
*/ */
QDF_STATUS QDF_STATUS
wlan_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, wlan_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
bool *value); bool *value);
/** /**

View File

@@ -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 * enabled value
* @psoc: pointer to psoc object * @psoc: pointer to psoc object
* @value: Value that needs to be get from the caller * @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 * Return: QDF Status
*/ */
static inline QDF_STATUS static inline QDF_STATUS
ucfg_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, ucfg_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
bool *value) bool *value)
{ {
return wlan_mlme_is_sap_bcast_deauth_enabled(psoc, value); return wlan_mlme_get_sap_bcast_deauth_enabled(psoc, value);
} }
/** /**

View File

@@ -1716,7 +1716,7 @@ QDF_STATUS wlan_mlme_set_sap_get_peer_info(struct wlan_objmgr_psoc *psoc,
} }
QDF_STATUS QDF_STATUS
wlan_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc, wlan_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
bool *value) bool *value)
{ {
struct wlan_mlme_psoc_obj *mlme_obj; struct wlan_mlme_psoc_obj *mlme_obj;

View File

@@ -226,7 +226,7 @@ enum {
QCSAP_PARAM_CHAN_WIDTH, QCSAP_PARAM_CHAN_WIDTH,
QCSAP_PARAM_SET_TXRX_STATS, QCSAP_PARAM_SET_TXRX_STATS,
QCASAP_SET_11AX_RATE, QCASAP_SET_11AX_RATE,
QCASAP_SET_PEER_RATE, QCASAP_SET_PEER_RATE, /* Not Supported */
QCASAP_PARAM_DCM, QCASAP_PARAM_DCM,
QCASAP_PARAM_RANGE_EXT, QCASAP_PARAM_RANGE_EXT,
QCSAP_SET_DEFAULT_AMPDU, QCSAP_SET_DEFAULT_AMPDU,

View File

@@ -388,8 +388,17 @@ hdd_indicate_ese_bcn_report_no_results(const struct hdd_adapter *adapter,
const uint8_t numBss); const uint8_t numBss);
#endif /* FEATURE_WLAN_ESE */ #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, 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, enum ol_txrx_peer_state sta_state,
bool roam_synch_in_progress); bool roam_synch_in_progress);
#ifdef WLAN_FEATURE_ROAM_OFFLOAD #ifdef WLAN_FEATURE_ROAM_OFFLOAD

View File

@@ -112,6 +112,8 @@
#include "qdf_periodic_work.h" #include "qdf_periodic_work.h"
#endif #endif
#include "wlan_hdd_sta_info.h"
/* /*
* Preprocessor definitions and constants * Preprocessor definitions and constants
*/ */
@@ -880,135 +882,6 @@ struct hdd_fw_txrx_stats {
struct hdd_rate_info rx_rate; 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 * struct hdd_ap_ctx - SAP/P2PGO specific information
* @hostapd_state: state control information * @hostapd_state: state control information
@@ -1264,10 +1137,14 @@ struct hdd_adapter {
/** Multiple station supports */ /** Multiple station supports */
/** Per-station structure */ /** 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 sta_info[WLAN_MAX_STA_COUNT];
struct hdd_station_info cache_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 #ifdef FEATURE_WLAN_WAPI
struct hdd_wapi_info wapi_info; struct hdd_wapi_info wapi_info;

View File

@@ -70,10 +70,9 @@ void hdd_softap_tx_timeout(struct net_device *dev);
* hdd_softap_init_tx_rx() - Initialize Tx/Rx module * hdd_softap_init_tx_rx() - Initialize Tx/Rx module
* @adapter: pointer to adapter context * @adapter: pointer to adapter context
* *
* Return: QDF_STATUS_E_FAILURE if any errors encountered, * Return: None
* QDF_STATUS_SUCCESS otherwise
*/ */
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 * 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 * hdd_softap_init_tx_rx_sta() - Initialize Tx/Rx for a softap station
* @adapter: pointer to adapter context * @adapter: pointer to adapter context
* @sta_id: Station ID to initialize
* @sta_mac: pointer to the MAC address of the station * @sta_mac: pointer to the MAC address of the station
* *
* Return: QDF_STATUS_E_FAILURE if any errors encountered, * Return: QDF_STATUS_E_FAILURE if any errors encountered,
* QDF_STATUS_SUCCESS otherwise * QDF_STATUS_SUCCESS otherwise
*/ */
QDF_STATUS hdd_softap_init_tx_rx_sta(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); 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 * hdd_softap_rx_packet_cbk() - Receive packet handler
* @adapter_context: pointer to HDD adapter * @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 * hdd_softap_deregister_sta() - Deregister a STA with the Data Path
* @adapter: pointer to adapter context * @adapter: pointer to adapter context
* @sta_id: Station ID to deregister * @sta_info: pointer to HDD station info structure
* @mac_addr: Peer mac address
* *
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/ */
QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter, QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter,
uint8_t sta_id, struct hdd_station_info *sta_info);
struct qdf_mac_addr mac_addr);
/** /**
* hdd_softap_register_sta() - Register a SoftAP STA * 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, struct qdf_mac_addr *sta_mac,
enum ol_txrx_peer_state state); 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 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
/** /**
* hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler
@@ -235,13 +205,13 @@ void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume)
/** /**
* hdd_post_dhcp_ind() - Send DHCP START/STOP indication to FW * hdd_post_dhcp_ind() - Send DHCP START/STOP indication to FW
* @adapter: pointer to hdd adapter * @adapter: pointer to hdd adapter
* @sta_id: peer station ID * @mac_addr: mac address
* @type: WMA message type * @type: WMA message type
* *
* Return: error number * Return: error number
*/ */
int hdd_post_dhcp_ind(struct hdd_adapter *adapter, 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
@@ -249,6 +219,25 @@ int hdd_post_dhcp_ind(struct hdd_adapter *adapter,
* @skb: pointer to OS packet (sk_buff) * @skb: pointer to OS packet (sk_buff)
* @dir: direction * @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 * Return: error number
*/ */
int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter, 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 #else
static inline static inline
int hdd_post_dhcp_ind(struct hdd_adapter *adapter, 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; return 0;
} }

View File

@@ -69,6 +69,7 @@
#include <wlan_cfg80211_crypto.h> #include <wlan_cfg80211_crypto.h>
#include <wlan_crypto_global_api.h> #include <wlan_crypto_global_api.h>
#include "wlan_blm_ucfg_api.h" #include "wlan_blm_ucfg_api.h"
#include "wlan_hdd_sta_info.h"
/* These are needed to recognize WPA and RSN suite types */ /* These are needed to recognize WPA and RSN suite types */
#define HDD_WPA_OUI_SIZE 4 #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); 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, 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, enum ol_txrx_peer_state sta_state,
bool roam_synch_in_progress) bool roam_synch_in_progress)
{ {
QDF_STATUS err; QDF_STATUS err;
uint8_t *peer_mac_addr;
void *pdev = cds_get_context(QDF_MODULE_ID_TXRX); void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
void *soc = cds_get_context(QDF_MODULE_ID_SOC); void *soc = cds_get_context(QDF_MODULE_ID_SOC);
void *peer; void *peer;
/* Will be removed as a part of clean up */
uint8_t sta_id;
if (!pdev) { if (!pdev) {
hdd_err("Failed to get txrx context"); hdd_err("Failed to get txrx context");
return QDF_STATUS_E_FAULT; return QDF_STATUS_E_FAULT;
} }
if (sta_id >= WLAN_MAX_STA_COUNT) { peer = cdp_peer_find_by_addr(soc, (struct cdp_pdev *)pdev,
hdd_err("Invalid sta id: %d", sta_id); peer_mac, &sta_id);
return QDF_STATUS_E_INVAL;
}
peer = cdp_peer_find_by_local_id(soc,
(struct cdp_pdev *)pdev, sta_id);
if (!peer) if (!peer)
return QDF_STATUS_E_FAULT; return QDF_STATUS_E_FAULT;
peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer); err = cdp_peer_state_update(soc, pdev, peer_mac, sta_state);
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);
if (err != QDF_STATUS_SUCCESS) { if (err != QDF_STATUS_SUCCESS) {
hdd_err("peer state update failed"); hdd_err("peer state update failed");
return QDF_STATUS_E_FAULT; 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); INIT_COMPLETION(adapter->sta_authorized_event);
#endif #endif
err = sme_set_peer_authorized(peer_mac_addr, err = sme_set_peer_authorized(
peer_mac,
hdd_set_peer_authorized_event, hdd_set_peer_authorized_event,
adapter->vdev_id); adapter->vdev_id);
if (err != QDF_STATUS_SUCCESS) { if (err != QDF_STATUS_SUCCESS) {
@@ -2061,6 +2045,32 @@ QDF_STATUS hdd_update_dp_vdev_flags(void *cbk_data,
return status; 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 * hdd_roam_register_sta() - register station
* @adapter: pointer to adapter * @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 * Connections that do not need Upper layer auth, transition
* TLSHIM directly to 'Authenticated' state * TLSHIM directly to 'Authenticated' state
*/ */
qdf_status = qdf_status = hdd_conn_change_peer_state(
hdd_change_peer_state(adapter, txrx_desc.sta_id, adapter, roam_info,
OL_TXRX_PEER_STATE_AUTH, txrx_desc.peer_addr.bytes);
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
roam_info->roamSynchInProgress
#else
false
#endif
);
hdd_conn_set_authenticated(adapter, true); hdd_conn_set_authenticated(adapter, true);
hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, true); hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, true);
} else { } else {
hdd_debug("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", hdd_debug("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
sta_ctx->conn_info.sta_id[0]); sta_ctx->conn_info.sta_id[0]);
qdf_status =
hdd_change_peer_state(adapter, txrx_desc.sta_id, qdf_status = hdd_conn_change_peer_state(
OL_TXRX_PEER_STATE_CONN, adapter, roam_info,
#ifdef WLAN_FEATURE_ROAM_OFFLOAD txrx_desc.peer_addr.bytes);
roam_info->roamSynchInProgress
#else
false
#endif
);
hdd_conn_set_authenticated(adapter, false); hdd_conn_set_authenticated(adapter, false);
hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, 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 #endif
#ifdef QCA_IBSS_SUPPORT #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 * hdd_roam_ibss_indication_handler() - update the status of the IBSS
* @adapter: pointer to adapter * @adapter: pointer to adapter
@@ -2694,8 +2662,8 @@ static int hdd_change_sta_state_authenticated(struct hdd_adapter *adapter,
struct csr_roam_info *roaminfo) struct csr_roam_info *roaminfo)
{ {
QDF_STATUS status; QDF_STATUS status;
uint8_t *mac_addr;
uint32_t timeout, auto_bmps_timer_val; uint32_t timeout, auto_bmps_timer_val;
uint8_t sta_id = HDD_WLAN_INVALID_STA_ID;
struct hdd_station_ctx *hddstactx = struct hdd_station_ctx *hddstactx =
WLAN_HDD_GET_STATION_CTX_PTR(adapter); WLAN_HDD_GET_STATION_CTX_PTR(adapter);
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(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); (auto_bmps_timer_val * 1000);
if (QDF_IBSS_MODE == adapter->device_mode) if (QDF_IBSS_MODE == adapter->device_mode)
sta_id = hdd_get_ibss_peer_sta_id(hddstactx, roaminfo); mac_addr = roaminfo->peerMac.bytes;
else 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", hdd_debug("Changing Peer state to AUTHENTICATED for Sta = "
sta_id); QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(mac_addr));
/* Connections that do not need Upper layer authentication, /* Connections that do not need Upper layer authentication,
* transition TL to 'Authenticated' state after the keys are set * 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_is_roam_sync_in_progress(roaminfo));
hdd_conn_set_authenticated(adapter, true); hdd_conn_set_authenticated(adapter, true);
hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, 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) { if (roam_info->fAuthRequired) {
qdf_status = qdf_status =
hdd_change_peer_state(adapter, hdd_change_peer_state(adapter,
sta_ctx->conn_info.sta_id[0], roam_info->bssid.bytes,
OL_TXRX_PEER_STATE_CONN, OL_TXRX_PEER_STATE_CONN,
#ifdef WLAN_FEATURE_ROAM_OFFLOAD #ifdef WLAN_FEATURE_ROAM_OFFLOAD
roam_info->roamSynchInProgress roam_info->roamSynchInProgress
@@ -3460,7 +3430,7 @@ hdd_association_completion_handler(struct hdd_adapter *adapter,
sta_ctx->conn_info.sta_id[0]); sta_ctx->conn_info.sta_id[0]);
qdf_status = qdf_status =
hdd_change_peer_state(adapter, hdd_change_peer_state(adapter,
sta_ctx->conn_info.sta_id[0], roam_info->bssid.bytes,
OL_TXRX_PEER_STATE_AUTH, OL_TXRX_PEER_STATE_AUTH,
#ifdef WLAN_FEATURE_ROAM_OFFLOAD #ifdef WLAN_FEATURE_ROAM_OFFLOAD
roam_info->roamSynchInProgress roam_info->roamSynchInProgress

View File

@@ -142,6 +142,7 @@
#include "wlan_hdd_hw_capability.h" #include "wlan_hdd_hw_capability.h"
#include "wlan_hdd_oemdata.h" #include "wlan_hdd_oemdata.h"
#include "os_if_fwol.h" #include "os_if_fwol.h"
#include "wlan_hdd_sta_info.h"
#define g_mode_rates_size (12) #define g_mode_rates_size (12)
#define a_mode_rates_size (8) #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 net_device *dev = wdev->netdev;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
struct hdd_station_ctx *hdd_sta_ctx; struct hdd_station_ctx *hdd_sta_ctx;
struct hdd_station_info *sta_info;
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1]; struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
uint32_t sta_id;
struct sk_buff *reply_skb; struct sk_buff *reply_skb;
uint32_t rate_flags = 0; uint32_t rate_flags = 0;
uint8_t nss; 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 || } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
adapter->device_mode == QDF_SAP_MODE) { adapter->device_mode == QDF_SAP_MODE) {
for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
if (adapter->sta_info[sta_id].in_use && hdd_err("Ignore bcast/self sta");
!qdf_is_macaddr_broadcast( return -EINVAL;
&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) { sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
hdd_err("No active peer with mac="QDF_MAC_ADDR_STR, peer_mac);
if (!sta_info) {
hdd_err("No active peer with mac = " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(peer_mac)); QDF_MAC_ADDR_ARRAY(peer_mac));
return -EINVAL; return -EINVAL;
} }
nss = adapter->sta_info[sta_id].nss; nss = sta_info->nss;
freq = cds_chan_to_freq( freq = cds_chan_to_freq(
(WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel); (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 { } else {
hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR, hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(peer_mac)); QDF_MAC_ADDR_ARRAY(peer_mac));
@@ -20960,6 +20959,110 @@ static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
return errno; 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 *)&param->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 * __wlan_hdd_cfg80211_del_station() - delete station v2
* @wiphy: Pointer to wiphy * @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_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
struct hdd_context *hdd_ctx; struct hdd_context *hdd_ctx;
QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
struct hdd_hostapd_state *hapd_state; struct hdd_hostapd_state *hapd_state;
uint8_t sta_id;
uint8_t *mac; uint8_t *mac;
mac_handle_t mac_handle; mac_handle_t mac_handle;
struct hdd_station_info *sta_info;
hdd_enter(); hdd_enter();
@@ -21004,8 +21106,9 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
mac = (uint8_t *) param->peerMacAddr.bytes; mac = (uint8_t *) param->peerMacAddr.bytes;
mac_handle = hdd_ctx->mac_handle; mac_handle = hdd_ctx->mac_handle;
if ((QDF_SAP_MODE == adapter->device_mode) || if (QDF_SAP_MODE != adapter->device_mode &&
(QDF_P2P_GO_MODE == adapter->device_mode)) { QDF_P2P_GO_MODE != adapter->device_mode)
goto fn_end;
hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
if (!hapd_state) { if (!hapd_state) {
@@ -21013,114 +21116,33 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
return 0; return 0;
} }
if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) { if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
uint16_t i; if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
hapd_state,
bool is_sap_bcast_deauth_enabled = false; param)))
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; 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 { } else {
qdf_status = sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
hdd_softap_get_sta_id(adapter, mac);
(struct qdf_mac_addr *) mac,
&sta_id); if (!sta_info) {
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
hdd_debug("Skip DEL STA as this is not used::" hdd_debug("Skip DEL STA as this is not used::"
QDF_MAC_ADDR_STR, QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac)); QDF_MAC_ADDR_ARRAY(mac));
return -ENOENT; return -ENOENT;
} }
if (adapter->sta_info[sta_id].is_deauth_in_progress == if (sta_info->is_deauth_in_progress) {
true) {
hdd_debug("Skip DEL STA as deauth is in progress::" hdd_debug("Skip DEL STA as deauth is in progress::"
QDF_MAC_ADDR_STR, QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac)); QDF_MAC_ADDR_ARRAY(mac));
return -ENOENT; return -ENOENT;
} }
adapter->sta_info[sta_id].is_deauth_in_progress = true;
hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR, hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac)); QDF_MAC_ADDR_ARRAY(mac));
hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
/* 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 *)&param->peerMacAddr,
param->reason_code, 0);
qdf_status = hdd_softap_sta_deauth(adapter,
param); 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");
}
} }
fn_end: fn_end:

View File

@@ -91,6 +91,7 @@
#include "wlan_fwol_ucfg_api.h" #include "wlan_fwol_ucfg_api.h"
#include "nan_ucfg_api.h" #include "nan_ucfg_api.h"
#include <wlan_reg_services_api.h> #include <wlan_reg_services_api.h>
#include "wlan_hdd_sta_info.h"
#define ACS_SCAN_EXPIRY_TIMEOUT_S 4 #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; 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_ap_ctx *ap_ctx;
struct hdd_station_info *sta_info;
struct csr_del_sta_params del_sta_params; struct csr_del_sta_params del_sta_params;
ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
if (sta_id == ap_ctx->broadcast_sta_id) if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
return;
sta_info = &adapter->sta_info[sta_id];
if (!sta_info->in_use)
return; return;
wlansap_populate_del_sta_params(sta_info->sta_mac.bytes, 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) 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); 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) 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; return;
} }
stainfo = &adapter->sta_info[event->staId]; stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
event->staMac.bytes);
if (!stainfo) { if (!stainfo) {
hdd_err("invalid stainfo"); hdd_err("invalid stainfo");
@@ -1748,6 +1749,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
bool legacy_phymode; bool legacy_phymode;
tSap_StationDisassocCompleteEvent *disassoc_comp; tSap_StationDisassocCompleteEvent *disassoc_comp;
struct hdd_station_info *stainfo, *cache_stainfo; struct hdd_station_info *stainfo, *cache_stainfo;
uint8_t index = 0;
mac_handle_t mac_handle; mac_handle_t mac_handle;
struct sap_config *sap_config; 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)) if (QDF_IS_STATUS_SUCCESS(qdf_status))
hdd_fill_station_info(adapter, event); 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()) { if (ucfg_ipa_is_enabled()) {
status = ucfg_ipa_wlan_evt(hdd_ctx->pdev, 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 else
hdd_debug(" MAC initiated disassociation"); hdd_debug(" MAC initiated disassociation");
we_event = IWEVEXPIRED; 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, DPTRACE(qdf_dp_trace_mgmt_pkt(QDF_DP_TRACE_MGMT_PACKET_RECORD,
adapter->vdev_id, adapter->vdev_id,
QDF_TRACE_DEFAULT_PDEV_ID, QDF_TRACE_DEFAULT_PDEV_ID,
QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC)); QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC));
stainfo = hdd_get_stainfo(adapter->sta_info, stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
disassoc_comp->staMac); disassoc_comp->staMac.bytes);
if (stainfo) { if (!stainfo) {
hdd_err("Failed to find the right station");
return QDF_STATUS_E_INVAL;
}
/* Send DHCP STOP indication to FW */ /* Send DHCP STOP indication to FW */
stainfo->dhcp_phase = DHCP_PHASE_ACK; stainfo->dhcp_phase = DHCP_PHASE_ACK;
if (stainfo->dhcp_nego_status == if (stainfo->dhcp_nego_status ==
DHCP_NEGO_IN_PROGRESS) DHCP_NEGO_IN_PROGRESS)
hdd_post_dhcp_ind(adapter, sta_id, hdd_post_dhcp_ind(adapter,
disassoc_comp->staMac.bytes,
WMA_DHCP_STOP_IND); WMA_DHCP_STOP_IND);
stainfo->dhcp_nego_status = DHCP_NEGO_STOP; stainfo->dhcp_nego_status = DHCP_NEGO_STOP;
}
/* STA id will be removed as a part of Phase 2 cleanup */ hdd_softap_deregister_sta(adapter, stainfo);
hdd_softap_deregister_sta(adapter, sta_id,
disassoc_comp->staMac);
ap_ctx->ap_active = false; ap_ctx->ap_active = false;
spin_lock_bh(&adapter->sta_info_lock);
for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { hdd_for_each_station(adapter->sta_info_list, stainfo,
if (adapter->sta_info[i].in_use index) {
&& i != if (!qdf_is_macaddr_broadcast(
(WLAN_HDD_GET_AP_CTX_PTR(adapter))-> &stainfo->sta_mac)) {
broadcast_sta_id) {
ap_ctx->ap_active = true; ap_ctx->ap_active = true;
break; break;
} }
} }
spin_unlock_bh(&adapter->sta_info_lock);
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
wlan_hdd_auto_shutdown_enable(hdd_ctx, true); 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); hdd_register_hostapd_wext(adapter->dev);
/* Initialize the data path module */ /* Initialize the data path module */
status = hdd_softap_init_tx_rx(adapter); hdd_softap_init_tx_rx(adapter);
if (!QDF_IS_STATUS_SUCCESS(status)) {
hdd_err("hdd_softap_init_tx_rx failed"); status = hdd_sta_info_init(&adapter->sta_info_list);
goto error_release_sap_session; if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("sta info init failed");
goto error_release_softap_tx_rx;
} }
status = hdd_wmm_adapter_init(adapter); 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 */ /* rcpi info initialization */
qdf_mem_zero(&adapter->rcpi, sizeof(adapter->rcpi)); qdf_mem_zero(&adapter->rcpi, sizeof(adapter->rcpi));
hdd_exit(); hdd_exit();
return status; return status;
error_release_wmm: error_release_wmm:
hdd_sta_info_deinit(&adapter->sta_info_list);
error_release_softap_tx_rx:
hdd_softap_deinit_tx_rx(adapter); hdd_softap_deinit_tx_rx(adapter);
error_release_sap_session: error_release_sap_session:
hdd_unregister_wext(adapter->dev); 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) void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter)
{ {
struct sap_event sap_event; struct sap_event sap_event;
int sta_id; uint8_t index = 0;
struct sap_context *sap_ctx; struct sap_context *sap_ctx;
struct hdd_station_info *sta_info;
hdd_enter(); hdd_enter();
@@ -6601,31 +6606,24 @@ void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter)
return; return;
} }
for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
if (adapter->sta_info[sta_id].in_use) { hdd_debug("sta_mac: " QDF_MAC_ADDR_STR,
hdd_debug("sta_id: %d in_use: %d %pK", QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
sta_id, adapter->sta_info[sta_id].in_use,
adapter);
if (qdf_is_macaddr_broadcast( if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
&adapter->sta_info[sta_id].sta_mac))
continue; continue;
sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT; sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT;
qdf_mem_copy( qdf_mem_copy(
&sap_event.sapevt. &sap_event.sapevt.sapStationDisassocCompleteEvent.staMac,
sapStationDisassocCompleteEvent.staMac, &sta_info->sta_mac, sizeof(struct qdf_mac_addr));
&adapter->sta_info[sta_id].sta_mac,
sizeof(struct qdf_mac_addr)); sap_event.sapevt.sapStationDisassocCompleteEvent.reason =
sap_event.sapevt.sapStationDisassocCompleteEvent.
reason =
eSAP_MAC_INITATED_DISASSOC; eSAP_MAC_INITATED_DISASSOC;
sap_event.sapevt.sapStationDisassocCompleteEvent. sap_event.sapevt.sapStationDisassocCompleteEvent.status_code =
status_code =
QDF_STATUS_E_RESOURCES; QDF_STATUS_E_RESOURCES;
hdd_hostapd_sap_event_cb(&sap_event, hdd_hostapd_sap_event_cb(&sap_event, sap_ctx->user_context);
sap_ctx->user_context);
}
} }
hdd_exit(); 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, bool hdd_is_peer_associated(struct hdd_adapter *adapter,
struct qdf_mac_addr *mac_addr) struct qdf_mac_addr *mac_addr)
{ {
uint32_t cnt; uint8_t index = 0;
bool is_associated = false;
struct hdd_station_info *sta_info; struct hdd_station_info *sta_info;
if (!adapter || !mac_addr) { if (!adapter || !mac_addr) {
@@ -6642,17 +6641,13 @@ bool hdd_is_peer_associated(struct hdd_adapter *adapter,
return false; return false;
} }
sta_info = adapter->sta_info; hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
spin_lock_bh(&adapter->sta_info_lock); if (!qdf_mem_cmp(&sta_info->sta_mac, mac_addr,
for (cnt = 0; cnt < WLAN_MAX_STA_COUNT; cnt++) { QDF_MAC_ADDR_SIZE)) {
if ((sta_info[cnt].in_use) && is_associated = true;
!qdf_mem_cmp(&(sta_info[cnt].sta_mac), mac_addr,
QDF_MAC_ADDR_SIZE))
break; break;
} }
spin_unlock_bh(&adapter->sta_info_lock); }
if (cnt != WLAN_MAX_STA_COUNT)
return true;
return false; return is_associated;
} }

View File

@@ -43,6 +43,7 @@
#include <wlan_cfg80211_mc_cp_stats.h> #include <wlan_cfg80211_mc_cp_stats.h>
#include "wlan_mlme_ucfg_api.h" #include "wlan_mlme_ucfg_api.h"
#include "wlan_reg_ucfg_api.h" #include "wlan_reg_ucfg_api.h"
#include "wlan_hdd_sta_info.h"
#define WE_WLAN_VERSION 1 #define WE_WLAN_VERSION 1
/* WEXT limitation: MAX allowed buf len for any * /* 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; struct cdp_pdev *pdev = NULL;
void *soc = NULL; void *soc = NULL;
struct cdp_txrx_stats_req req = {0}; struct cdp_txrx_stats_req req = {0};
uint8_t count = 0; uint8_t index = 0;
struct hdd_station_info *sta_info; struct hdd_station_info *sta_info;
hdd_enter_dev(dev); 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]; req.mac_id = value[2];
hdd_info("QCSAP_PARAM_SET_TXRX_STATS stats_id: %d mac_id: %d", hdd_info("QCSAP_PARAM_SET_TXRX_STATS stats_id: %d mac_id: %d",
req.stats, req.mac_id); req.stats, req.mac_id);
sta_info = adapter->sta_info;
if (value[1] == CDP_TXRX_STATS_28) { if (value[1] == CDP_TXRX_STATS_28) {
req.peer_addr = (char *)&adapter->mac_addr; req.peer_addr = (char *)&adapter->mac_addr;
ret = cdp_txrx_stats_request(soc, vdev, &req); ret = cdp_txrx_stats_request(soc, vdev, &req);
for (count = 0; count < WLAN_MAX_STA_COUNT; count++) { hdd_for_each_station(adapter->sta_info_list, sta_info,
if (sta_info->in_use) { index) {
hdd_debug("sta: %d: bss_id: %pM", hdd_debug("bss_id: " QDF_MAC_ADDR_STR,
sta_info->sta_id, QDF_MAC_ADDR_ARRAY(
(void *)&sta_info->sta_mac); sta_info->sta_mac.bytes));
req.peer_addr =
(char *)&sta_info->sta_mac;
ret = cdp_txrx_stats_request(soc, vdev,
&req);
}
sta_info++; req.peer_addr = (char *)
&sta_info->sta_mac;
ret = cdp_txrx_stats_request(
soc, vdev, &req);
} }
} else { } else {
ret = cdp_txrx_stats_request(soc, vdev, &req); 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; 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 int
static __iw_softap_setparam(struct net_device *dev, static __iw_softap_setparam(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
@@ -1053,9 +986,6 @@ static __iw_softap_setparam(struct net_device *dev,
&adapter->session.ap. &adapter->session.ap.
sap_config); sap_config);
break; break;
case QCASAP_SET_PEER_RATE:
ret = hdd_set_peer_rate(adapter, set_value);
break;
case QCASAP_PARAM_DCM: case QCASAP_PARAM_DCM:
hdd_debug("Set WMI_VDEV_PARAM_HE_DCM: %d", set_value); hdd_debug("Set WMI_VDEV_PARAM_HE_DCM: %d", set_value);
ret = wma_cli_set_command(adapter->vdev_id, 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) union iwreq_data *wrqu, char *extra)
{ {
struct hdd_adapter *adapter = (netdev_priv(dev)); 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; struct hdd_context *hdd_ctx;
char *buf; char *buf;
int cnt = 0; int index = 0;
int left; int left;
int ret; int ret;
/* maclist_index must be u32 to match userspace */ /* 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); maclist_index = sizeof(maclist_index);
left = wrqu->data.length - maclist_index; left = wrqu->data.length - maclist_index;
spin_lock_bh(&adapter->sta_info_lock); hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
while ((cnt < WLAN_MAX_STA_COUNT) && (left >= QDF_MAC_ADDR_SIZE)) { if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
if ((sta_info[cnt].in_use) && memcpy(&buf[maclist_index], &sta_info->sta_mac,
(!qdf_is_macaddr_broadcast(&sta_info[cnt].sta_mac))) {
memcpy(&buf[maclist_index], &(sta_info[cnt].sta_mac),
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
maclist_index += QDF_MAC_ADDR_SIZE; maclist_index += QDF_MAC_ADDR_SIZE;
left -= QDF_MAC_ADDR_SIZE; left -= QDF_MAC_ADDR_SIZE;
} }
cnt++;
} }
spin_unlock_bh(&adapter->sta_info_lock);
*((u32 *) buf) = maclist_index; *((u32 *) buf) = maclist_index;
wrqu->data.length = 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, uint8_t *buf,
int size) int size)
{ {
int i; uint8_t index = 0;
int written; int written;
uint8_t bc_sta_id; struct hdd_station_info *sta;
hdd_enter(); hdd_enter();
bc_sta_id = WLAN_HDD_GET_AP_CTX_PTR(adapter)->broadcast_sta_id;
written = scnprintf(buf, size, "\nstaId staAddress\n"); 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) if (written >= size - 1)
break; break;
if (!sta->in_use) if (QDF_IS_ADDR_BROADCAST(sta->sta_mac.bytes))
continue;
if (i == bc_sta_id)
continue; continue;
written += scnprintf(buf + written, size - written, written += scnprintf(buf + written, size - written,
"%5d "QDF_MAC_ADDR_STR" ecsa=%d\n", QDF_MAC_ADDR_STR
sta->sta_id, " ecsa=%d\n",
sta->sta_mac.bytes[0], sta->sta_mac.bytes[0],
sta->sta_mac.bytes[1], sta->sta_mac.bytes[1],
sta->sta_mac.bytes[2], sta->sta_mac.bytes[2],
@@ -2527,7 +2447,8 @@ int __iw_get_softap_linkspeed(struct net_device *dev,
struct qdf_mac_addr mac_address; struct qdf_mac_addr mac_address;
char macaddr_string[MAC_ADDRESS_STR_LEN + 1]; char macaddr_string[MAC_ADDRESS_STR_LEN + 1];
QDF_STATUS status = QDF_STATUS_E_FAILURE; QDF_STATUS status = QDF_STATUS_E_FAILURE;
int rc, ret, i; int rc, ret;
uint8_t index = 0;
hdd_enter_dev(dev); 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. * link speed for first connected client will be returned.
*/ */
if (wrqu->data.length < 17 || !QDF_IS_STATUS_SUCCESS(status)) { if (wrqu->data.length < 17 || !QDF_IS_STATUS_SUCCESS(status)) {
for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { struct hdd_station_info *sta_info;
if (adapter->sta_info[i].in_use &&
(!qdf_is_macaddr_broadcast hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
(&adapter->sta_info[i].sta_mac))) { if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
qdf_copy_macaddr( qdf_copy_macaddr(&mac_address,
&mac_address, &sta_info->sta_mac);
&adapter->sta_info[i].
sta_mac);
status = QDF_STATUS_SUCCESS; status = QDF_STATUS_SUCCESS;
break; break;
} }
@@ -3247,12 +3166,6 @@ static const struct iw_priv_args hostapd_private_args[] = {
0, "set_11ax_rate" 0, "set_11ax_rate"
} }
, ,
{
QCASAP_SET_PEER_RATE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "set_peer_rate"
}
,
{ {
QCASAP_PARAM_DCM, QCASAP_PARAM_DCM,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,

View File

@@ -173,6 +173,7 @@
#include "wlan_blm_ucfg_api.h" #include "wlan_blm_ucfg_api.h"
#include "ol_txrx.h" #include "ol_txrx.h"
#include "nan_ucfg_api.h" #include "nan_ucfg_api.h"
#include "wlan_hdd_sta_info.h"
#ifdef MODULE #ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_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); hdd_apf_context_destroy(adapter);
qdf_spinlock_destroy(&adapter->vdev_lock); 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); wlan_hdd_debugfs_csr_deinit(adapter);
if (adapter->device_mode == QDF_STA_MODE) if (adapter->device_mode == QDF_STA_MODE)
hdd_sysfs_destroy_adapter_root_obj(adapter); 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_adapter *adapter;
struct hdd_station_ctx *sta_ctx; struct hdd_station_ctx *sta_ctx;
struct qdf_mac_addr peer_macaddr; struct qdf_mac_addr peer_macaddr;
int sta_id;
bool value; bool value;
struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev;
uint8_t index = 0;
struct hdd_station_info *sta_info;
hdd_enter(); 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) { } else if (adapter->device_mode == QDF_P2P_GO_MODE) {
clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags); clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
sta_id++) { hdd_for_each_station(adapter->sta_info_list, sta_info,
struct hdd_station_info sta = index) {
adapter->sta_info[sta_id]; hdd_debug(
if (sta.in_use) { "[SSR] deregister STA MAC:"
hdd_debug("[SSR] deregister STA with ID %d", QDF_MAC_ADDR_STR,
sta_id); QDF_MAC_ADDR_ARRAY(
/* STA id will be removed */ sta_info->sta_mac.bytes));
hdd_softap_deregister_sta(adapter, hdd_softap_deregister_sta(
sta_id, adapter,
sta.sta_mac); sta_info);
sta.in_use = 0;
}
} }
} }
@@ -6316,6 +6320,10 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx)
hdd_stop_tsf_sync(adapter); hdd_stop_tsf_sync(adapter);
hdd_softap_deinit_tx_rx(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_hl_netdev_fc_timer(adapter);
hdd_deregister_tx_flow_control(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_station_ctx *hdd_sta_ctx = NULL;
struct hdd_adapter *adapter = NULL; struct hdd_adapter *adapter = NULL;
uint8_t sta_id = 0; uint8_t index = 0;
uint8_t *sta_mac = NULL; uint8_t *sta_mac = NULL;
struct hdd_context *hdd_ctx; struct hdd_context *hdd_ctx;
mac_handle_t mac_handle; mac_handle_t mac_handle;
struct hdd_station_info *sta_info = NULL;
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) { if (!hdd_ctx) {
@@ -15483,6 +15492,7 @@ bool hdd_is_connection_in_progress(uint8_t *out_vdev_id,
} }
return true; return true;
} }
if ((QDF_STA_MODE == adapter->device_mode) || if ((QDF_STA_MODE == adapter->device_mode) ||
(QDF_P2P_CLIENT_MODE == adapter->device_mode) || (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
(QDF_P2P_DEVICE_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) || } else if ((QDF_SAP_MODE == adapter->device_mode) ||
(QDF_P2P_GO_MODE == adapter->device_mode)) { (QDF_P2P_GO_MODE == adapter->device_mode)) {
for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; hdd_for_each_station(adapter->sta_info_list, sta_info,
sta_id++) { index) {
if (!((adapter->sta_info[sta_id].in_use) if (sta_info->peer_state !=
&& (OL_TXRX_PEER_STATE_CONN == OL_TXRX_PEER_STATE_CONN)
adapter->sta_info[sta_id].peer_state)))
continue; continue;
sta_mac = (uint8_t *) sta_mac = sta_info->sta_mac.bytes;
&(adapter->sta_info[sta_id].
sta_mac.bytes[0]);
hdd_debug("client " QDF_MAC_ADDR_STR hdd_debug("client " QDF_MAC_ADDR_STR
" of SAP/GO is in middle of WPS/EAPOL exchange", " of SAP/GO is in middle of WPS/EAPOL exchange",
QDF_MAC_ADDR_ARRAY(sta_mac)); QDF_MAC_ADDR_ARRAY(sta_mac));
if (out_vdev_id && out_reason) { if (out_vdev_id && out_reason) {
*out_vdev_id = adapter->vdev_id; *out_vdev_id = adapter->vdev_id;
*out_reason = SAP_EAPOL_IN_PROGRESS; *out_reason =
SAP_EAPOL_IN_PROGRESS;
} }
return true; return true;
} }
if (hdd_ctx->connection_in_progress) { if (hdd_ctx->connection_in_progress) {

View File

@@ -44,7 +44,7 @@
#include "wlan_ipa_ucfg_api.h" #include "wlan_ipa_ucfg_api.h"
#include "wlan_policy_mgr_ucfg.h" #include "wlan_policy_mgr_ucfg.h"
#include <wma_types.h> #include <wma_types.h>
#include <sap_internal.h> #include "wlan_hdd_sta_info.h"
/* Preprocessor definitions and constants */ /* Preprocessor definitions and constants */
#undef QCA_HDD_SAP_DUMP_SK_BUFF #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 * Return: error number
*/ */
int hdd_post_dhcp_ind(struct hdd_adapter *adapter, int hdd_post_dhcp_ind(struct hdd_adapter *adapter, uint8_t *mac_addr,
uint8_t sta_id, uint16_t type) uint16_t type)
{ {
tAniDHCPInd pmsg; tAniDHCPInd pmsg;
QDF_STATUS status = QDF_STATUS_SUCCESS; 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) { if (!adapter) {
hdd_err("NULL adapter"); hdd_err("NULL adapter");
@@ -266,7 +267,7 @@ int hdd_post_dhcp_ind(struct hdd_adapter *adapter,
adapter->mac_addr.bytes, adapter->mac_addr.bytes,
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
qdf_mem_copy(pmsg.peerMacAddr.bytes, qdf_mem_copy(pmsg.peerMacAddr.bytes,
adapter->sta_info[sta_id].sta_mac.bytes, mac_addr,
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
status = wma_process_dhcp_ind(cds_get_context(QDF_MODULE_ID_WMA), 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) static void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf)
{ {
struct hdd_ap_ctx *hdd_ap_ctx; struct hdd_ap_ctx *hdd_ap_ctx;
struct qdf_mac_addr *dest_mac_addr; uint8_t *dest_mac_addr;
uint8_t sta_id;
struct hdd_adapter *adapter = context; struct hdd_adapter *adapter = context;
if (hdd_validate_adapter(adapter)) if (hdd_validate_adapter(adapter))
@@ -305,59 +305,20 @@ static void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf)
return; return;
} }
dest_mac_addr = (struct qdf_mac_addr *)(netbuf->data + dest_mac_addr = netbuf->data + DHCP_CLIENT_MAC_ADDR_OFFSET;
DHCP_CLIENT_MAC_ADDR_OFFSET);
if (QDF_STATUS_SUCCESS != hdd_post_dhcp_ind(adapter, dest_mac_addr, WMA_DHCP_STOP_IND);
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_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, int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
struct sk_buff *skb, struct sk_buff *skb,
enum qdf_proto_dir dir) enum qdf_proto_dir dir)
{ {
enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
struct hdd_station_info *hdd_sta_info; struct hdd_station_info *hdd_sta_info;
uint8_t sta_id;
int errno = 0; int errno = 0;
struct qdf_mac_addr *src_mac; struct qdf_mac_addr *src_mac, *macaddr =
QDF_STATUS status; (struct qdf_mac_addr *)(skb->data + QDF_NBUF_SRC_MAC_OFFSET);
if (((adapter->device_mode == QDF_SAP_MODE) || if (((adapter->device_mode == QDF_SAP_MODE) ||
(adapter->device_mode == QDF_P2P_GO_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 + src_mac = (struct qdf_mac_addr *)(skb->data +
DHCP_CLIENT_MAC_ADDR_OFFSET); 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); 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", hdd_debug("ENTER: type=%d, phase=%d, nego_status=%d",
subtype, subtype,
@@ -386,7 +348,9 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
if (dir != QDF_RX) if (dir != QDF_RX)
break; break;
if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP) if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
errno = hdd_post_dhcp_ind(adapter, sta_id, errno = hdd_post_dhcp_ind(
adapter,
hdd_sta_info->sta_mac.bytes,
WMA_DHCP_START_IND); WMA_DHCP_START_IND);
hdd_sta_info->dhcp_phase = DHCP_PHASE_DISCOVER; hdd_sta_info->dhcp_phase = DHCP_PHASE_DISCOVER;
hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS; hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS;
@@ -398,7 +362,9 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
if (dir != QDF_RX) if (dir != QDF_RX)
break; break;
if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP) if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
errno = hdd_post_dhcp_ind(adapter, sta_id, errno = hdd_post_dhcp_ind(
adapter,
hdd_sta_info->sta_mac.bytes,
WMA_DHCP_START_IND); WMA_DHCP_START_IND);
hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS; hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS;
case QDF_PROTO_DHCP_DECLINE: case QDF_PROTO_DHCP_DECLINE:
@@ -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_adapter *adapter = (struct hdd_adapter *) netdev_priv(dev);
struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
struct hdd_context *hdd_ctx = adapter->hdd_ctx; struct hdd_context *hdd_ctx = adapter->hdd_ctx;
struct qdf_mac_addr *dest_mac_addr; struct qdf_mac_addr *dest_mac_addr, *mac_addr;
uint8_t sta_id; static struct qdf_mac_addr bcast_mac_addr = QDF_MAC_ADDR_BCAST_INIT;
uint32_t num_seg; uint32_t num_seg;
struct hdd_station_info *sta_info;
++adapter->hdd_stats.tx_rx_stats.tx_called; ++adapter->hdd_stats.tx_rx_stats.tx_called;
adapter->hdd_stats.tx_rx_stats.cont_txtimeout_cnt = 0; 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; dest_mac_addr = (struct qdf_mac_addr *)skb->data;
if (QDF_NBUF_CB_GET_IS_BCAST(skb) || /* In case of mcast, fetch the bcast sta_info. Else use the pkt addr */
QDF_NBUF_CB_GET_IS_MCAST(skb)) { if (QDF_NBUF_CB_GET_IS_MCAST(skb))
/* The BC/MC station ID is assigned during BSS mac_addr = &bcast_mac_addr;
* starting phase. SAP will return the station ID else
* used for BC/MC traffic. mac_addr = dest_mac_addr;
*/
sta_id = ap_ctx->broadcast_sta_id; sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
} else { mac_addr->bytes);
if (QDF_STATUS_SUCCESS !=
hdd_softap_get_sta_id(adapter, if (!QDF_NBUF_CB_GET_IS_BCAST(skb) && !QDF_NBUF_CB_GET_IS_MCAST(skb)) {
dest_mac_addr, &sta_id)) { if (!sta_info) {
QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
QDF_TRACE_LEVEL_INFO_HIGH, QDF_TRACE_LEVEL_INFO_HIGH,
"%s: Failed to find right station", __func__); "%s: Failed to find right station", __func__);
goto drop_pkt; 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(QDF_MODULE_ID_HDD_SAP_DATA,
QDF_TRACE_LEVEL_INFO_HIGH, QDF_TRACE_LEVEL_INFO_HIGH,
"%s: Failed to find right station", __func__); "%s: STA " QDF_MAC_ADDR_STR
goto drop_pkt; "deauth in progress", __func__,
} else if (!adapter->sta_info[sta_id].in_use) { QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
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);
goto drop_pkt; goto drop_pkt;
} }
if ((OL_TXRX_PEER_STATE_CONN != if (sta_info->peer_state != OL_TXRX_PEER_STATE_CONN &&
adapter->sta_info[sta_id].peer_state) sta_info->peer_state != OL_TXRX_PEER_STATE_AUTH) {
&& (OL_TXRX_PEER_STATE_AUTH !=
adapter->sta_info[sta_id].peer_state)) {
QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
QDF_TRACE_LEVEL_INFO_HIGH, QDF_TRACE_LEVEL_INFO_HIGH,
"%s: Station not connected yet", __func__); "%s: Station not connected yet", __func__);
goto drop_pkt; 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) { if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
QDF_TRACE_LEVEL_INFO_HIGH, 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__); qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__);
adapter->stats.tx_bytes += skb->len; adapter->stats.tx_bytes += skb->len;
adapter->sta_info[sta_id].tx_bytes += skb->len;
if (sta_info) {
sta_info->tx_bytes += skb->len;
if (qdf_nbuf_is_tso(skb)) { if (qdf_nbuf_is_tso(skb)) {
num_seg = qdf_nbuf_get_tso_num_seg(skb); num_seg = qdf_nbuf_get_tso_num_seg(skb);
adapter->stats.tx_packets += num_seg; adapter->stats.tx_packets += num_seg;
adapter->sta_info[sta_id].tx_packets += num_seg; sta_info->tx_packets += num_seg;
} else { } else {
++adapter->stats.tx_packets; ++adapter->stats.tx_packets;
adapter->sta_info[sta_id].tx_packets++; sta_info->tx_packets++;
hdd_ctx->no_tx_offload_pkt_cnt++; hdd_ctx->no_tx_offload_pkt_cnt++;
} }
adapter->sta_info[sta_id].last_tx_rx_ts = qdf_system_ticks(); sta_info->last_tx_rx_ts = qdf_system_ticks();
}
QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(skb) = 0; 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, if (adapter->tx_fn(adapter->txrx_vdev,
(qdf_nbuf_t)skb) != NULL) { (qdf_nbuf_t)skb) != NULL) {
QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH, QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
"%s: Failed to send packet to txrx for sta_id:%d", "%s: Failed to send packet to txrx for sta: "
__func__, sta_id); QDF_MAC_ADDR_STR, __func__,
QDF_MAC_ADDR_ARRAY(dest_mac_addr->bytes));
++adapter->hdd_stats.tx_rx_stats.tx_dropped_ac[ac]; ++adapter->hdd_stats.tx_rx_stats.tx_dropped_ac[ac];
goto drop_pkt_and_release_skb; 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); 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)); 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) 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, QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter,
uint8_t sta_id,
struct qdf_mac_addr *sta_mac) struct qdf_mac_addr *sta_mac)
{ {
spin_lock_bh(&adapter->sta_info_lock); struct hdd_station_info *sta_info;
if (adapter->sta_info[sta_id].in_use) { QDF_STATUS status;
spin_unlock_bh(&adapter->sta_info_lock);
hdd_err("Reinit of in use station %d", sta_id); 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; return QDF_STATUS_E_FAILURE;
} }
qdf_mem_zero(&adapter->sta_info[sta_id], sta_info = qdf_mem_malloc(sizeof(struct hdd_station_info));
sizeof(struct hdd_station_info)); if (!sta_info)
return QDF_STATUS_E_NOMEM;
adapter->sta_info[sta_id].in_use = true; sta_info->is_deauth_in_progress = false;
adapter->sta_info[sta_id].is_deauth_in_progress = false; qdf_mem_copy(&sta_info->sta_mac, sta_mac, sizeof(struct qdf_mac_addr));
qdf_copy_macaddr(&adapter->sta_info[sta_id].sta_mac, sta_mac);
spin_unlock_bh(&adapter->sta_info_lock); status = hdd_sta_info_attach(&adapter->sta_info_list, sta_info);
return QDF_STATUS_SUCCESS; if (QDF_IS_STATUS_ERROR(status)) {
} hdd_err("Failed to attach station: " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(sta_mac->bytes));
QDF_STATUS hdd_softap_deinit_tx_rx_sta(struct hdd_adapter *adapter, qdf_mem_free(sta_info);
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;
} }
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; 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 sk_buff *next = NULL;
struct hdd_context *hdd_ctx = NULL; struct hdd_context *hdd_ctx = NULL;
struct qdf_mac_addr *src_mac; struct qdf_mac_addr *src_mac;
uint8_t sta_id; struct hdd_station_info *sta_info;
/* Sanity check on inputs */ /* Sanity check on inputs */
if (unlikely((!adapter_context) || (!rx_buf))) { 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 */ /* Send DHCP Indication to FW */
src_mac = (struct qdf_mac_addr *)(skb->data + src_mac = (struct qdf_mac_addr *)(skb->data +
QDF_NBUF_SRC_MAC_OFFSET); QDF_NBUF_SRC_MAC_OFFSET);
if (QDF_STATUS_SUCCESS == sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
hdd_softap_get_sta_id(adapter, src_mac, &sta_id)) { (uint8_t *)src_mac);
if (sta_id < WLAN_MAX_STA_COUNT) {
adapter->sta_info[sta_id].rx_packets++; if (sta_info) {
adapter->sta_info[sta_id].rx_bytes += skb->len; sta_info->rx_packets++;
adapter->sta_info[sta_id].last_tx_rx_ts = sta_info->rx_bytes += skb->len;
qdf_system_ticks(); sta_info->last_tx_rx_ts = qdf_system_ticks();
hdd_softap_inspect_dhcp_packet(adapter, skb, hdd_softap_inspect_dhcp_packet(adapter, skb, QDF_RX);
QDF_RX);
}
} }
hdd_event_eapol_log(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, QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter,
uint8_t sta_id, struct hdd_station_info *sta_info)
struct qdf_mac_addr mac_addr)
{ {
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
struct hdd_context *hdd_ctx; struct hdd_context *hdd_ctx;
struct qdf_mac_addr *mac_addr;
if (!adapter) { if (!adapter) {
hdd_err("NULL adapter"); hdd_err("NULL adapter");
@@ -1018,40 +950,55 @@ QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter,
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
hdd_ctx = WLAN_HDD_GET_CTX(adapter); if (!sta_info) {
hdd_err("Invalid station");
if (sta_id >= WLAN_MAX_STA_COUNT) {
hdd_err("Error: Invalid sta_id: %u", sta_id);
return QDF_STATUS_E_INVAL; 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 /* Clear station in TL and then update HDD data
* structures. This helps to block RX frames from other * structures. This helps to block RX frames from other
* station to this station. * 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), (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
mac_addr); *mac_addr);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
hdd_err("cdp_clear_peer failed for staID %d, Status=%d [0x%08X]", hdd_err("cdp_clear_peer failed for sta: " QDF_MAC_ADDR_STR
sta_id, qdf_status, qdf_status); ", 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_is_enabled()) {
if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev, if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev,
adapter->device_mode, adapter->device_mode,
adapter->vdev_id, adapter->vdev_id,
WLAN_IPA_CLIENT_DISCONNECT, WLAN_IPA_CLIENT_DISCONNECT,
adapter->sta_info[sta_id].sta_mac. mac_addr->bytes) != QDF_STATUS_SUCCESS)
bytes) != QDF_STATUS_SUCCESS)
hdd_err("WLAN_CLIENT_DISCONNECT event failed"); hdd_err("WLAN_CLIENT_DISCONNECT event failed");
} }
spin_lock_bh(&adapter->sta_info_lock); hdd_sta_info_detach(&adapter->sta_info_list, sta_info);
qdf_mem_zero(&adapter->sta_info[sta_id],
sizeof(struct hdd_station_info));
spin_unlock_bh(&adapter->sta_info_lock);
}
ucfg_mlme_update_oce_flags(hdd_ctx->pdev); 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); void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
struct cdp_vdev *txrx_vdev = NULL; struct cdp_vdev *txrx_vdev = NULL;
struct hdd_ap_ctx *ap_ctx; struct hdd_ap_ctx *ap_ctx;
struct hdd_station_info *sta_info;
hdd_info("STA:%u, Auth:%u, Priv:%u, WMM:%u",
sta_id, auth_required, privacy_required, wmm_enabled);
ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); 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 * 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); sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
hdd_softap_deregister_sta(adapter, sta_id, sta_mac->bytes);
adapter->sta_info[sta_id].sta_mac); 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. */ /* Get the Station ID from the one saved during the association. */
txrx_desc.sta_id = sta_id; txrx_desc.sta_id = sta_id;
/* /*
* If the address is a broadcast address, then provide the self mac addr * 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. * to the data path. Else provide the mac address of the connected peer.
*/ */
if (qdf_is_macaddr_broadcast(sta_mac) && ap_ctx) if (qdf_is_macaddr_broadcast(sta_mac) && ap_ctx)
qdf_copy_macaddr(&txrx_desc.peer_addr, qdf_mem_copy(&txrx_desc.peer_addr, &adapter->mac_addr,
&ap_ctx->sap_context->bssid); QDF_MAC_ADDR_SIZE);
else 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; 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 * put TL directly into 'authenticated' state
*/ */
adapter->sta_info[sta_id].sta_id = sta_id; sta_info->is_qos_enabled = wmm_enabled;
adapter->sta_info[sta_id].is_qos_enabled = wmm_enabled;
if (!auth_required) { if (!auth_required) {
hdd_info("open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", hdd_info("open/shared auth STA MAC= " QDF_MAC_ADDR_STR
adapter->sta_info[sta_id].sta_id); ". 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, /* Connections that do not need Upper layer auth,
* transition TL directly to 'Authenticated' state. * transition TL directly to 'Authenticated' state.
*/ */
qdf_status = hdd_change_peer_state(adapter, txrx_desc.sta_id, qdf_status = hdd_change_peer_state(adapter,
OL_TXRX_PEER_STATE_AUTH, false); 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)) if (!qdf_is_macaddr_broadcast(sta_mac))
qdf_status = wlan_hdd_send_sta_authorized_event( qdf_status = wlan_hdd_send_sta_authorized_event(
adapter, hdd_ctx, adapter, hdd_ctx,
sta_mac); sta_mac);
} else { } else {
hdd_info("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", hdd_info("ULA auth STA MAC = " QDF_MAC_ADDR_STR
adapter->sta_info[sta_id].sta_id); ". 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, qdf_status = hdd_change_peer_state(adapter,
OL_TXRX_PEER_STATE_CONN, false); txrx_desc.peer_addr.bytes,
adapter->sta_info[sta_id].peer_state = OL_TXRX_PEER_STATE_CONN; OL_TXRX_PEER_STATE_CONN,
false);
sta_info->peer_state = OL_TXRX_PEER_STATE_CONN;
} }
hdd_debug("Enabling queues"); hdd_debug("Enabling queues");
@@ -1221,28 +1175,15 @@ QDF_STATUS hdd_softap_register_bc_sta(struct hdd_adapter *adapter,
return qdf_status; 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 hdd_softap_stop_bss(struct hdd_adapter *adapter)
{ {
QDF_STATUS status = QDF_STATUS_E_FAILURE; 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_context *hdd_ctx;
struct hdd_ap_ctx *ap_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); hdd_ctx = WLAN_HDD_GET_CTX(adapter);
ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(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 * driver unload in progress check otherwise it can lead to peer
* object leak * object leak
*/ */
status = hdd_softap_deregister_bc_sta(adapter);
if (!QDF_IS_STATUS_SUCCESS(status)) hdd_for_each_station_safe(adapter->sta_info_list, sta_info,
hdd_err("Failed to deregister BC sta Id %d", index, tmp) {
ap_ctx->broadcast_sta_id); status = hdd_softap_deregister_sta(adapter,
sta_info);
for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { if (QDF_IS_STATUS_ERROR(status) && sta_info)
/* This excludes BC sta as it is already deregistered */ hdd_err("Deregistering STA " QDF_MAC_ADDR_STR " failed",
if (adapter->sta_info[sta_id].in_use) { QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
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 (adapter->device_mode == QDF_SAP_MODE && if (adapter->device_mode == QDF_SAP_MODE &&
!hdd_ctx->config->disable_channel) !hdd_ctx->config->disable_channel)
wlan_hdd_restore_channels(hdd_ctx, true); 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, struct qdf_mac_addr *sta_mac,
enum ol_txrx_peer_state state) enum ol_txrx_peer_state state)
{ {
uint8_t sta_id = WLAN_MAX_STA_COUNT;
QDF_STATUS qdf_status; QDF_STATUS qdf_status;
struct hdd_station_info *sta_info;
struct qdf_mac_addr mac_addr;
hdd_enter_dev(adapter->dev); hdd_enter_dev(adapter->dev);
qdf_status = hdd_softap_get_sta_id(adapter, sta_mac, &sta_id); sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
if (QDF_STATUS_SUCCESS != qdf_status) { sta_mac->bytes);
hdd_err("Failed to find right station");
return qdf_status; 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 == if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
qdf_is_macaddr_equal(&adapter->sta_info[sta_id].sta_mac, qdf_mem_copy(&mac_addr, &adapter->mac_addr, QDF_MAC_ADDR_SIZE);
sta_mac)) { else
hdd_err("Station %u MAC address not matching", sta_id); qdf_mem_copy(&mac_addr, sta_mac, QDF_MAC_ADDR_SIZE);
return QDF_STATUS_E_FAILURE;
}
qdf_status = qdf_status =
hdd_change_peer_state(adapter, sta_id, state, false); hdd_change_peer_state(adapter, mac_addr.bytes,
hdd_info("Station %u changed to state %d", sta_id, state); 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) { if (QDF_STATUS_SUCCESS == qdf_status) {
adapter->sta_info[sta_id].peer_state = sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH;
OL_TXRX_PEER_STATE_AUTH;
p2p_peer_authorized(adapter->vdev, sta_mac->bytes); 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; 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;
}

View File

@@ -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 <wlan_hdd_includes.h>
/* 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;
}

View File

@@ -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 <linux/ieee80211.h>
/* 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 */

View File

@@ -34,6 +34,7 @@
#include <wlan_hdd_hostapd.h> #include <wlan_hdd_hostapd.h>
#include <wlan_hdd_station_info.h> #include <wlan_hdd_station_info.h>
#include "wlan_mlme_ucfg_api.h" #include "wlan_mlme_ucfg_api.h"
#include "wlan_hdd_sta_info.h"
/* /*
* define short names for the global vendor params * 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 hdd_adapter *adapter,
struct qdf_mac_addr mac_addr) struct qdf_mac_addr mac_addr)
{ {
struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
mac_addr);
int status = 0; int status = 0;
bool is_associated = false; bool is_associated = false;
struct hdd_station_info *stainfo =
hdd_get_sta_info_by_mac(&adapter->sta_info_list,
mac_addr.bytes);
if (!stainfo) { if (!stainfo) {
status = hdd_get_cached_station_remote(hdd_ctx, adapter, status = hdd_get_cached_station_remote(hdd_ctx, adapter,

View File

@@ -40,6 +40,7 @@
#include "wlan_cp_stats_mc_ucfg_api.h" #include "wlan_cp_stats_mc_ucfg_api.h"
#include "wlan_mlme_ucfg_api.h" #include "wlan_mlme_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) #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
#define HDD_INFO_SIGNAL STATION_INFO_SIGNAL #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 sir_peer_info_ext peer_info;
struct hdd_fw_txrx_stats txrx_stats; struct hdd_fw_txrx_stats txrx_stats;
int status; int status;
int i;
status = wlan_hdd_validate_context(hddctx); status = wlan_hdd_validate_context(hddctx);
if (status != 0) if (status != 0)
@@ -3916,15 +3916,7 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy,
hdd_debug("get peer %pM info", mac); hdd_debug("get peer %pM info", mac);
for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list, mac);
if (!qdf_mem_cmp(adapter->sta_info[i].sta_mac.bytes,
mac,
QDF_MAC_ADDR_SIZE)) {
stainfo = &adapter->sta_info[i];
break;
}
}
if (!stainfo) { if (!stainfo) {
hdd_err("peer %pM not found", mac); hdd_err("peer %pM not found", mac);
return -EINVAL; return -EINVAL;