2022-06-07 16:11:36 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2011-03-21 18:00:50 -07:00
/*
2020-02-12 21:47:10 +05:30
* NXP Wireless LAN device driver : HW / FW Initialization
2011-03-21 18:00:50 -07:00
*
2020-02-12 21:47:10 +05:30
* Copyright 2011 - 2020 NXP
2011-03-21 18:00:50 -07:00
*/
# include "decl.h"
# include "ioctl.h"
# include "util.h"
# include "fw.h"
# include "main.h"
# include "wmm.h"
# include "11n.h"
/*
* This function adds a BSS priority table to the table list .
*
* The function allocates a new BSS priority table node and adds it to
* the end of BSS priority table list , kept in driver memory .
*/
static int mwifiex_add_bss_prio_tbl ( struct mwifiex_private * priv )
{
struct mwifiex_adapter * adapter = priv - > adapter ;
struct mwifiex_bss_prio_node * bss_prio ;
2012-03-13 19:22:36 -07:00
struct mwifiex_bss_prio_tbl * tbl = adapter - > bss_prio_tbl ;
2011-03-21 18:00:50 -07:00
bss_prio = kzalloc ( sizeof ( struct mwifiex_bss_prio_node ) , GFP_KERNEL ) ;
2013-02-03 17:28:14 +00:00
if ( ! bss_prio )
2011-05-08 22:50:09 +02:00
return - ENOMEM ;
2011-03-21 18:00:50 -07:00
bss_prio - > priv = priv ;
INIT_LIST_HEAD ( & bss_prio - > list ) ;
2012-03-13 19:22:36 -07:00
2019-06-25 10:40:45 -07:00
spin_lock_bh ( & tbl [ priv - > bss_priority ] . bss_prio_lock ) ;
2012-03-13 19:22:36 -07:00
list_add_tail ( & bss_prio - > list , & tbl [ priv - > bss_priority ] . bss_prio_head ) ;
2019-06-25 10:40:45 -07:00
spin_unlock_bh ( & tbl [ priv - > bss_priority ] . bss_prio_lock ) ;
2011-03-21 18:00:50 -07:00
2011-04-13 17:27:06 -07:00
return 0 ;
2011-03-21 18:00:50 -07:00
}
2017-10-24 02:29:19 -07:00
static void wakeup_timer_fn ( struct timer_list * t )
2014-12-31 02:36:41 -08:00
{
2017-10-24 02:29:19 -07:00
struct mwifiex_adapter * adapter = from_timer ( adapter , t , wakeup_timer ) ;
2014-12-31 02:36:41 -08:00
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , ERROR , " Firmware wakeup failed \n " ) ;
2014-12-31 02:36:41 -08:00
adapter - > hw_status = MWIFIEX_HW_STATUS_RESET ;
mwifiex_cancel_all_pending_cmd ( adapter ) ;
2019-08-05 10:15:04 -07:00
if ( adapter - > if_ops . card_reset )
2014-12-31 02:36:41 -08:00
adapter - > if_ops . card_reset ( adapter ) ;
}
2022-08-23 19:21:27 +08:00
static void fw_dump_work ( struct work_struct * work )
2017-12-12 15:38:12 +08:00
{
2022-08-23 19:21:27 +08:00
struct mwifiex_adapter * adapter =
container_of ( work , struct mwifiex_adapter , devdump_work . work ) ;
2017-12-12 15:38:12 +08:00
mwifiex_upload_device_dump ( adapter ) ;
}
2011-03-21 18:00:50 -07:00
/*
* This function initializes the private structure and sets default
* values to the members .
*
* Additionally , it also initializes all the locks and sets up all the
* lists .
*/
2012-09-25 20:23:42 -07:00
int mwifiex_init_priv ( struct mwifiex_private * priv )
2011-03-21 18:00:50 -07:00
{
u32 i ;
priv - > media_connected = false ;
2015-03-02 19:54:49 -08:00
eth_broadcast_addr ( priv - > curr_addr ) ;
2015-06-22 19:06:18 +05:30
priv - > port_open = false ;
2015-09-18 06:32:15 -07:00
priv - > usb_port = MWIFIEX_USB_EP_DATA ;
2011-03-21 18:00:50 -07:00
priv - > pkt_tx_ctrl = 0 ;
2011-09-26 20:37:26 -07:00
priv - > bss_mode = NL80211_IFTYPE_UNSPECIFIED ;
2011-03-21 18:00:50 -07:00
priv - > data_rate = 0 ; /* Initially indicate the rate as auto */
priv - > is_data_rate_auto = true ;
priv - > bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR ;
priv - > data_avg_factor = DEFAULT_DATA_AVG_FACTOR ;
2012-02-24 21:36:04 -08:00
priv - > sec_info . wep_enabled = 0 ;
2011-03-28 17:55:42 -07:00
priv - > sec_info . authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM ;
2011-04-01 18:36:47 -07:00
priv - > sec_info . encryption_mode = 0 ;
2011-03-21 18:00:50 -07:00
for ( i = 0 ; i < ARRAY_SIZE ( priv - > wep_key ) ; i + + )
memset ( & priv - > wep_key [ i ] , 0 , sizeof ( struct mwifiex_wep_key ) ) ;
priv - > wep_key_curr_index = 0 ;
2016-12-16 12:55:45 +05:30
priv - > curr_pkt_filter = HostCmd_ACT_MAC_DYNAMIC_BW_ENABLE |
HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
2011-03-21 18:00:50 -07:00
HostCmd_ACT_MAC_ETHERNETII_ENABLE ;
2015-12-06 22:56:21 +01:00
priv - > beacon_period = 100 ; /* beacon interval */
2011-03-21 18:00:50 -07:00
priv - > attempted_bss_desc = NULL ;
memset ( & priv - > curr_bss_params , 0 , sizeof ( priv - > curr_bss_params ) ) ;
priv - > listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL ;
memset ( & priv - > prev_ssid , 0 , sizeof ( priv - > prev_ssid ) ) ;
memset ( & priv - > prev_bssid , 0 , sizeof ( priv - > prev_bssid ) ) ;
memset ( & priv - > assoc_rsp_buf , 0 , sizeof ( priv - > assoc_rsp_buf ) ) ;
priv - > assoc_rsp_size = 0 ;
priv - > adhoc_channel = DEFAULT_AD_HOC_CHANNEL ;
priv - > atim_window = 0 ;
priv - > adhoc_state = ADHOC_IDLE ;
priv - > tx_power_level = 0 ;
priv - > max_tx_power_level = 0 ;
priv - > min_tx_power_level = 0 ;
2016-06-06 13:02:38 -04:00
priv - > tx_ant = 0 ;
priv - > rx_ant = 0 ;
2011-03-21 18:00:50 -07:00
priv - > tx_rate = 0 ;
priv - > rxpd_htinfo = 0 ;
priv - > rxpd_rate = 0 ;
priv - > rate_bitmap = 0 ;
priv - > data_rssi_last = 0 ;
priv - > data_rssi_avg = 0 ;
priv - > data_nf_avg = 0 ;
priv - > data_nf_last = 0 ;
priv - > bcn_rssi_last = 0 ;
priv - > bcn_rssi_avg = 0 ;
priv - > bcn_nf_avg = 0 ;
priv - > bcn_nf_last = 0 ;
memset ( & priv - > wpa_ie , 0 , sizeof ( priv - > wpa_ie ) ) ;
memset ( & priv - > aes_key , 0 , sizeof ( priv - > aes_key ) ) ;
priv - > wpa_ie_len = 0 ;
priv - > wpa_is_gtk_set = false ;
memset ( & priv - > assoc_tlv_buf , 0 , sizeof ( priv - > assoc_tlv_buf ) ) ;
priv - > assoc_tlv_buf_len = 0 ;
memset ( & priv - > wps , 0 , sizeof ( priv - > wps ) ) ;
memset ( & priv - > gen_ie_buf , 0 , sizeof ( priv - > gen_ie_buf ) ) ;
priv - > gen_ie_buf_len = 0 ;
memset ( priv - > vs_ie , 0 , sizeof ( priv - > vs_ie ) ) ;
priv - > wmm_required = true ;
priv - > wmm_enabled = false ;
priv - > wmm_qosinfo = 0 ;
priv - > curr_bcn_buf = NULL ;
priv - > curr_bcn_size = 0 ;
2012-04-09 20:06:56 -07:00
priv - > wps_ie = NULL ;
priv - > wps_ie_len = 0 ;
2012-08-03 18:06:05 -07:00
priv - > ap_11n_enabled = 0 ;
2012-09-25 20:23:36 -07:00
memset ( & priv - > roc_cfg , 0 , sizeof ( priv - > roc_cfg ) ) ;
2011-03-21 18:00:50 -07:00
priv - > scan_block = false ;
2013-06-18 16:36:58 -07:00
priv - > csa_chan = 0 ;
priv - > csa_expire_time = 0 ;
2013-07-22 19:17:41 -07:00
priv - > del_list_idx = 0 ;
2013-08-23 16:48:23 -07:00
priv - > hs2_enabled = false ;
2014-11-13 21:54:16 +05:30
priv - > check_tdls_tx = false ;
2014-02-07 16:27:29 -08:00
memcpy ( priv - > tos_to_tid_inv , tos_to_tid_inv , MAX_NUM_TID ) ;
2013-06-18 16:36:58 -07:00
2015-01-28 15:54:25 +05:30
mwifiex_init_11h_params ( priv ) ;
2011-04-15 20:50:40 -07:00
return mwifiex_add_bss_prio_tbl ( priv ) ;
2011-03-21 18:00:50 -07:00
}
/*
* This function allocates buffers for members of the adapter
* structure .
*
* The memory allocated includes scan table , command buffers , and
* sleep confirm command buffer . In addition , the queues are
* also initialized .
*/
static int mwifiex_allocate_adapter ( struct mwifiex_adapter * adapter )
{
2011-05-03 20:11:46 -07:00
int ret ;
2011-03-21 18:00:50 -07:00
/* Allocate command buffer */
ret = mwifiex_alloc_cmd_buffer ( adapter ) ;
if ( ret ) {
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , ERROR ,
" %s: failed to alloc cmd buffer \n " ,
__func__ ) ;
2011-03-21 18:00:50 -07:00
return - 1 ;
}
adapter - > sleep_cfm =
2011-05-09 19:00:18 -07:00
dev_alloc_skb ( sizeof ( struct mwifiex_opt_sleep_confirm )
2012-03-13 19:22:36 -07:00
+ INTF_HEADER_LEN ) ;
2011-03-21 18:00:50 -07:00
if ( ! adapter - > sleep_cfm ) {
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , ERROR ,
" %s: failed to alloc sleep cfm \t "
" cmd buffer \n " , __func__ ) ;
2011-03-21 18:00:50 -07:00
return - 1 ;
}
skb_reserve ( adapter - > sleep_cfm , INTF_HEADER_LEN ) ;
return 0 ;
}
/*
* This function initializes the adapter structure and sets default
* values to the members of adapter .
*
* This also initializes the WMM related parameters in the driver private
* structures .
*/
static void mwifiex_init_adapter ( struct mwifiex_adapter * adapter )
{
2011-05-09 19:00:18 -07:00
struct mwifiex_opt_sleep_confirm * sleep_cfm_buf = NULL ;
2011-03-21 18:00:50 -07:00
2011-05-09 19:00:18 -07:00
skb_put ( adapter - > sleep_cfm , sizeof ( struct mwifiex_opt_sleep_confirm ) ) ;
2011-03-21 18:00:50 -07:00
adapter - > cmd_sent = false ;
2011-10-11 17:41:21 -07:00
2012-04-18 20:08:28 -07:00
if ( adapter - > iface_type = = MWIFIEX_SDIO )
2011-10-11 17:41:21 -07:00
adapter - > data_sent = true ;
2012-04-18 20:08:28 -07:00
else
adapter - > data_sent = false ;
2011-10-11 17:41:21 -07:00
2017-05-23 07:12:30 +00:00
if ( adapter - > iface_type = = MWIFIEX_USB )
adapter - > intf_hdr_len = 0 ;
else
adapter - > intf_hdr_len = INTF_HEADER_LEN ;
2011-03-21 18:00:50 -07:00
adapter - > cmd_resp_received = false ;
adapter - > event_received = false ;
adapter - > data_received = false ;
2018-07-13 17:56:35 +05:30
clear_bit ( MWIFIEX_SURPRISE_REMOVED , & adapter - > work_flags ) ;
2011-03-21 18:00:50 -07:00
adapter - > hw_status = MWIFIEX_HW_STATUS_INITIALIZING ;
adapter - > ps_mode = MWIFIEX_802_11_POWER_MODE_CAM ;
adapter - > ps_state = PS_STATE_AWAKE ;
adapter - > need_to_wakeup = false ;
adapter - > scan_mode = HostCmd_BSS_MODE_ANY ;
adapter - > specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME ;
adapter - > active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME ;
adapter - > passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME ;
2014-09-12 20:08:54 +05:30
adapter - > scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME ;
2011-03-21 18:00:50 -07:00
adapter - > scan_probes = 1 ;
adapter - > multiple_dtim = 1 ;
adapter - > local_listen_interval = 0 ; /* default value in firmware
will be used */
adapter - > is_deep_sleep = false ;
adapter - > delay_null_pkt = false ;
adapter - > delay_to_ps = 1000 ;
adapter - > enhanced_ps_mode = PS_MODE_AUTO ;
adapter - > gen_null_pkt = false ; /* Disable NULL Pkg generation by
default */
adapter - > pps_uapsd_mode = false ; /* Disable pps/uapsd mode by
default */
adapter - > pm_wakeup_card_req = false ;
adapter - > pm_wakeup_fw_try = false ;
adapter - > curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K ;
2018-07-13 17:56:35 +05:30
clear_bit ( MWIFIEX_IS_HS_CONFIGURED , & adapter - > work_flags ) ;
2013-03-04 16:27:57 -08:00
adapter - > hs_cfg . conditions = cpu_to_le32 ( HS_CFG_COND_DEF ) ;
adapter - > hs_cfg . gpio = HS_CFG_GPIO_DEF ;
adapter - > hs_cfg . gap = HS_CFG_GAP_DEF ;
2011-03-21 18:00:50 -07:00
adapter - > hs_activated = false ;
memset ( adapter - > event_body , 0 , sizeof ( adapter - > event_body ) ) ;
adapter - > hw_dot_11n_dev_cap = 0 ;
adapter - > hw_dev_mcs_support = 0 ;
2011-12-20 23:47:21 -08:00
adapter - > sec_chan_offset = 0 ;
2011-03-21 18:00:50 -07:00
adapter - > adhoc_11n_enabled = false ;
mwifiex_wmm_init ( adapter ) ;
2016-11-18 19:30:24 +05:30
atomic_set ( & adapter - > tx_hw_pending , 0 ) ;
2011-03-21 18:00:50 -07:00
2015-03-23 12:35:51 +03:00
sleep_cfm_buf = ( struct mwifiex_opt_sleep_confirm * )
adapter - > sleep_cfm - > data ;
memset ( sleep_cfm_buf , 0 , adapter - > sleep_cfm - > len ) ;
sleep_cfm_buf - > command = cpu_to_le16 ( HostCmd_CMD_802_11_PS_MODE_ENH ) ;
sleep_cfm_buf - > size = cpu_to_le16 ( adapter - > sleep_cfm - > len ) ;
sleep_cfm_buf - > result = 0 ;
sleep_cfm_buf - > action = cpu_to_le16 ( SLEEP_CONFIRM ) ;
sleep_cfm_buf - > resp_ctrl = cpu_to_le16 ( RESP_NEEDED ) ;
2011-03-21 18:00:50 -07:00
memset ( & adapter - > sleep_params , 0 , sizeof ( adapter - > sleep_params ) ) ;
memset ( & adapter - > sleep_period , 0 , sizeof ( adapter - > sleep_period ) ) ;
adapter - > tx_lock_flag = false ;
adapter - > null_pkt_interval = 0 ;
adapter - > fw_bands = 0 ;
adapter - > config_bands = 0 ;
adapter - > adhoc_start_band = 0 ;
adapter - > scan_channels = NULL ;
adapter - > fw_release_number = 0 ;
adapter - > fw_cap_info = 0 ;
memset ( & adapter - > upld_buf , 0 , sizeof ( adapter - > upld_buf ) ) ;
adapter - > event_cause = 0 ;
adapter - > region_code = 0 ;
adapter - > bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT ;
adapter - > adhoc_awake_period = 0 ;
memset ( & adapter - > arp_filter , 0 , sizeof ( adapter - > arp_filter ) ) ;
adapter - > arp_filter_size = 0 ;
2012-05-08 18:30:28 -07:00
adapter - > max_mgmt_ie_index = MAX_MGMT_IE_INDEX ;
2016-09-02 13:05:06 +05:30
adapter - > mfg_mode = mfg_mode ;
2014-08-19 08:24:25 -04:00
adapter - > key_api_major_ver = 0 ;
adapter - > key_api_minor_ver = 0 ;
2015-03-02 19:54:49 -08:00
eth_broadcast_addr ( adapter - > perm_addr ) ;
2015-01-28 15:42:03 +05:30
adapter - > iface_limit . sta_intf = MWIFIEX_MAX_STA_NUM ;
adapter - > iface_limit . uap_intf = MWIFIEX_MAX_UAP_NUM ;
adapter - > iface_limit . p2p_intf = MWIFIEX_MAX_P2P_NUM ;
2015-08-05 06:09:42 -07:00
adapter - > active_scan_triggered = false ;
2017-10-24 02:29:19 -07:00
timer_setup ( & adapter - > wakeup_timer , wakeup_timer_fn , 0 ) ;
2017-12-12 15:38:11 +08:00
adapter - > devdump_len = 0 ;
2022-08-23 19:21:27 +08:00
INIT_DELAYED_WORK ( & adapter - > devdump_work , fw_dump_work ) ;
2011-03-21 18:00:50 -07:00
}
2011-12-08 20:41:05 -08:00
/*
* This function sets trans_start per tx_queue
*/
void mwifiex_set_trans_start ( struct net_device * dev )
{
int i ;
for ( i = 0 ; i < dev - > num_tx_queues ; i + + )
2021-11-16 19:29:22 -08:00
txq_trans_cond_update ( netdev_get_tx_queue ( dev , i ) ) ;
2011-12-08 20:41:05 -08:00
2016-05-03 16:33:13 +02:00
netif_trans_update ( dev ) ;
2011-12-08 20:41:05 -08:00
}
/*
* This function wakes up all queues in net_device
*/
void mwifiex_wake_up_net_dev_queue ( struct net_device * netdev ,
struct mwifiex_adapter * adapter )
{
2019-06-25 10:40:45 -07:00
spin_lock_bh ( & adapter - > queue_lock ) ;
2017-07-24 18:13:27 -07:00
netif_tx_wake_all_queues ( netdev ) ;
2019-06-25 10:40:45 -07:00
spin_unlock_bh ( & adapter - > queue_lock ) ;
2011-12-08 20:41:05 -08:00
}
/*
* This function stops all queues in net_device
*/
void mwifiex_stop_net_dev_queue ( struct net_device * netdev ,
struct mwifiex_adapter * adapter )
{
2019-06-25 10:40:45 -07:00
spin_lock_bh ( & adapter - > queue_lock ) ;
2017-07-24 18:13:27 -07:00
netif_tx_stop_all_queues ( netdev ) ;
2019-06-25 10:40:45 -07:00
spin_unlock_bh ( & adapter - > queue_lock ) ;
2011-12-08 20:41:05 -08:00
}
2011-10-12 20:29:33 -07:00
/*
2017-07-24 18:13:25 -07:00
* This function invalidates the list heads .
2011-10-12 20:29:33 -07:00
*/
2017-07-24 18:13:25 -07:00
static void mwifiex_invalidate_lists ( struct mwifiex_adapter * adapter )
2011-10-12 20:29:33 -07:00
{
struct mwifiex_private * priv ;
s32 i , j ;
list_del ( & adapter - > cmd_free_q ) ;
list_del ( & adapter - > cmd_pending_q ) ;
list_del ( & adapter - > scan_pending_q ) ;
for ( i = 0 ; i < adapter - > priv_num ; i + + )
list_del ( & adapter - > bss_prio_tbl [ i ] . bss_prio_head ) ;
for ( i = 0 ; i < adapter - > priv_num ; i + + ) {
if ( adapter - > priv [ i ] ) {
priv = adapter - > priv [ i ] ;
for ( j = 0 ; j < MAX_NUM_TID ; + + j )
list_del ( & priv - > wmm . tid_tbl_ptr [ j ] . ra_list ) ;
list_del ( & priv - > tx_ba_stream_tbl_ptr ) ;
list_del ( & priv - > rx_reorder_tbl_ptr ) ;
2012-08-03 18:06:07 -07:00
list_del ( & priv - > sta_list ) ;
2014-11-13 21:54:16 +05:30
list_del ( & priv - > auto_tdls_list ) ;
2011-10-12 20:29:33 -07:00
}
}
}
2011-03-21 18:00:50 -07:00
/*
2013-05-17 17:50:18 -07:00
* This function performs cleanup for adapter structure .
2011-03-21 18:00:50 -07:00
*
2013-05-17 17:50:18 -07:00
* The cleanup is done recursively , by canceling all pending
* commands , freeing the member buffers previously allocated
* ( command buffers , scan table buffer , sleep confirm command
* buffer ) , stopping the timers and calling the cleanup routines
* for every interface .
2011-03-21 18:00:50 -07:00
*/
static void
2013-05-17 17:50:18 -07:00
mwifiex_adapter_cleanup ( struct mwifiex_adapter * adapter )
2011-03-21 18:00:50 -07:00
{
2014-12-31 02:36:41 -08:00
del_timer ( & adapter - > wakeup_timer ) ;
2022-08-23 19:21:27 +08:00
cancel_delayed_work_sync ( & adapter - > devdump_work ) ;
2011-03-21 18:00:50 -07:00
mwifiex_cancel_all_pending_cmd ( adapter ) ;
2014-12-31 02:36:42 -08:00
wake_up_interruptible ( & adapter - > cmd_wait_q . wait ) ;
wake_up_interruptible ( & adapter - > hs_activate_wait_q ) ;
2017-07-24 18:13:21 -07:00
}
2011-03-21 18:00:50 -07:00
2017-07-24 18:13:21 -07:00
void mwifiex_free_cmd_buffers ( struct mwifiex_adapter * adapter )
{
2017-07-24 18:13:25 -07:00
mwifiex_invalidate_lists ( adapter ) ;
2011-03-21 18:00:50 -07:00
/* Free command buffer */
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , INFO , " info: free cmd buffer \n " ) ;
2011-03-21 18:00:50 -07:00
mwifiex_free_cmd_buffer ( adapter ) ;
2012-02-03 20:34:02 -08:00
if ( adapter - > sleep_cfm )
dev_kfree_skb_any ( adapter - > sleep_cfm ) ;
2011-03-21 18:00:50 -07:00
}
/*
* This function intializes the lock variables and
* the list heads .
*/
int mwifiex_init_lock_list ( struct mwifiex_adapter * adapter )
{
2011-05-03 20:11:46 -07:00
struct mwifiex_private * priv ;
s32 i , j ;
2011-03-21 18:00:50 -07:00
spin_lock_init ( & adapter - > int_lock ) ;
spin_lock_init ( & adapter - > main_proc_lock ) ;
spin_lock_init ( & adapter - > mwifiex_cmd_lock ) ;
2011-12-08 20:41:05 -08:00
spin_lock_init ( & adapter - > queue_lock ) ;
2011-03-21 18:00:50 -07:00
for ( i = 0 ; i < adapter - > priv_num ; i + + ) {
if ( adapter - > priv [ i ] ) {
priv = adapter - > priv [ i ] ;
spin_lock_init ( & priv - > wmm . ra_list_spinlock ) ;
spin_lock_init ( & priv - > curr_bcn_buf_lock ) ;
2012-08-03 18:06:07 -07:00
spin_lock_init ( & priv - > sta_list_spinlock ) ;
2014-11-13 21:54:16 +05:30
spin_lock_init ( & priv - > auto_tdls_lock ) ;
2011-03-21 18:00:50 -07:00
}
}
/* Initialize cmd_free_q */
INIT_LIST_HEAD ( & adapter - > cmd_free_q ) ;
/* Initialize cmd_pending_q */
INIT_LIST_HEAD ( & adapter - > cmd_pending_q ) ;
/* Initialize scan_pending_q */
INIT_LIST_HEAD ( & adapter - > scan_pending_q ) ;
spin_lock_init ( & adapter - > cmd_free_q_lock ) ;
spin_lock_init ( & adapter - > cmd_pending_q_lock ) ;
spin_lock_init ( & adapter - > scan_pending_q_lock ) ;
2014-09-12 20:08:59 +05:30
spin_lock_init ( & adapter - > rx_proc_lock ) ;
2011-03-21 18:00:50 -07:00
2014-09-12 20:08:59 +05:30
skb_queue_head_init ( & adapter - > rx_data_q ) ;
2015-03-13 17:37:57 +05:30
skb_queue_head_init ( & adapter - > tx_data_q ) ;
2012-04-18 20:08:28 -07:00
2011-03-21 18:00:50 -07:00
for ( i = 0 ; i < adapter - > priv_num ; + + i ) {
INIT_LIST_HEAD ( & adapter - > bss_prio_tbl [ i ] . bss_prio_head ) ;
spin_lock_init ( & adapter - > bss_prio_tbl [ i ] . bss_prio_lock ) ;
}
for ( i = 0 ; i < adapter - > priv_num ; i + + ) {
if ( ! adapter - > priv [ i ] )
continue ;
priv = adapter - > priv [ i ] ;
2013-04-04 20:03:51 -07:00
for ( j = 0 ; j < MAX_NUM_TID ; + + j )
2011-03-21 18:00:50 -07:00
INIT_LIST_HEAD ( & priv - > wmm . tid_tbl_ptr [ j ] . ra_list ) ;
INIT_LIST_HEAD ( & priv - > tx_ba_stream_tbl_ptr ) ;
INIT_LIST_HEAD ( & priv - > rx_reorder_tbl_ptr ) ;
2012-08-03 18:06:07 -07:00
INIT_LIST_HEAD ( & priv - > sta_list ) ;
2014-11-13 21:54:16 +05:30
INIT_LIST_HEAD ( & priv - > auto_tdls_list ) ;
2014-02-07 16:30:35 -08:00
skb_queue_head_init ( & priv - > tdls_txq ) ;
2015-06-22 19:06:17 +05:30
skb_queue_head_init ( & priv - > bypass_txq ) ;
2011-03-21 18:00:50 -07:00
spin_lock_init ( & priv - > tx_ba_stream_tbl_lock ) ;
spin_lock_init ( & priv - > rx_reorder_tbl_lock ) ;
2014-11-25 06:43:05 -08:00
spin_lock_init ( & priv - > ack_status_lock ) ;
idr_init ( & priv - > ack_status_frames ) ;
2011-03-21 18:00:50 -07:00
}
return 0 ;
}
/*
* This function initializes the firmware .
*
* The following operations are performed sequentially -
* - Allocate adapter structure
* - Initialize the adapter structure
* - Initialize the private structure
* - Add BSS priority tables to the adapter structure
* - For each interface , send the init commands to firmware
* - Send the first command in command pending queue , if available
*/
int mwifiex_init_fw ( struct mwifiex_adapter * adapter )
{
2011-05-03 20:11:46 -07:00
int ret ;
struct mwifiex_private * priv ;
u8 i , first_sta = true ;
2011-03-21 18:00:50 -07:00
int is_cmd_pend_q_empty ;
adapter - > hw_status = MWIFIEX_HW_STATUS_INITIALIZING ;
/* Allocate memory for member of adapter structure */
ret = mwifiex_allocate_adapter ( adapter ) ;
if ( ret )
return - 1 ;
/* Initialize adapter structure */
mwifiex_init_adapter ( adapter ) ;
for ( i = 0 ; i < adapter - > priv_num ; i + + ) {
if ( adapter - > priv [ i ] ) {
priv = adapter - > priv [ i ] ;
/* Initialize private structure */
ret = mwifiex_init_priv ( priv ) ;
if ( ret )
return - 1 ;
}
}
2016-09-02 13:05:06 +05:30
if ( adapter - > mfg_mode ) {
adapter - > hw_status = MWIFIEX_HW_STATUS_READY ;
ret = - EINPROGRESS ;
} else {
for ( i = 0 ; i < adapter - > priv_num ; i + + ) {
if ( adapter - > priv [ i ] ) {
ret = mwifiex_sta_init_cmd ( adapter - > priv [ i ] ,
first_sta , true ) ;
if ( ret = = - 1 )
return - 1 ;
first_sta = false ;
}
2013-01-03 21:21:29 -08:00
2011-03-21 18:00:50 -07:00
}
}
2019-06-25 10:40:45 -07:00
spin_lock_bh ( & adapter - > cmd_pending_q_lock ) ;
2011-03-21 18:00:50 -07:00
is_cmd_pend_q_empty = list_empty ( & adapter - > cmd_pending_q ) ;
2019-06-25 10:40:45 -07:00
spin_unlock_bh ( & adapter - > cmd_pending_q_lock ) ;
2011-03-21 18:00:50 -07:00
if ( ! is_cmd_pend_q_empty ) {
/* Send the first command in queue and return */
if ( mwifiex_main_process ( adapter ) ! = - 1 )
ret = - EINPROGRESS ;
} else {
adapter - > hw_status = MWIFIEX_HW_STATUS_READY ;
}
return ret ;
}
/*
* This function deletes the BSS priority tables .
*
* The function traverses through all the allocated BSS priority nodes
* in every BSS priority table and frees them .
*/
static void mwifiex_delete_bss_prio_tbl ( struct mwifiex_private * priv )
{
int i ;
struct mwifiex_adapter * adapter = priv - > adapter ;
2013-04-18 16:34:12 -07:00
struct mwifiex_bss_prio_node * bssprio_node , * tmp_node ;
2011-03-21 18:00:50 -07:00
struct list_head * head ;
2012-03-13 19:22:36 -07:00
spinlock_t * lock ; /* bss priority lock */
2011-03-21 18:00:50 -07:00
for ( i = 0 ; i < adapter - > priv_num ; + + i ) {
head = & adapter - > bss_prio_tbl [ i ] . bss_prio_head ;
lock = & adapter - > bss_prio_tbl [ i ] . bss_prio_lock ;
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , INFO ,
" info: delete BSS priority table, \t "
" bss_type = %d, bss_num = %d, i = %d, \t "
" head = %p \n " ,
priv - > bss_type , priv - > bss_num , i , head ) ;
2013-04-18 16:34:12 -07:00
{
2019-06-25 10:40:45 -07:00
spin_lock_bh ( lock ) ;
2011-03-21 18:00:50 -07:00
list_for_each_entry_safe ( bssprio_node , tmp_node , head ,
list ) {
if ( bssprio_node - > priv = = priv ) {
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , INFO ,
" info: Delete \t "
" node %p, next = %p \n " ,
bssprio_node , tmp_node ) ;
2011-03-21 18:00:50 -07:00
list_del ( & bssprio_node - > list ) ;
kfree ( bssprio_node ) ;
}
}
2019-06-25 10:40:45 -07:00
spin_unlock_bh ( lock ) ;
2011-03-21 18:00:50 -07:00
}
}
}
2012-09-25 20:23:42 -07:00
/*
* This function frees the private structure , including cleans
* up the TX and RX queues and frees the BSS priority tables .
*/
void mwifiex_free_priv ( struct mwifiex_private * priv )
{
mwifiex_clean_txrx ( priv ) ;
mwifiex_delete_bss_prio_tbl ( priv ) ;
mwifiex_free_curr_bcn ( priv ) ;
}
2011-03-21 18:00:50 -07:00
/*
* This function is used to shutdown the driver .
*
* The following operations are performed sequentially -
* - Check if already shut down
* - Make sure the main process has stopped
* - Clean up the Tx and Rx queues
* - Delete BSS priority tables
* - Free the adapter
* - Notify completion
*/
2016-11-16 18:39:05 +05:30
void
2011-03-21 18:00:50 -07:00
mwifiex_shutdown_drv ( struct mwifiex_adapter * adapter )
{
2011-05-03 20:11:46 -07:00
struct mwifiex_private * priv ;
s32 i ;
2012-04-18 20:08:28 -07:00
struct sk_buff * skb ;
2011-03-21 18:00:50 -07:00
/* mwifiex already shutdown */
if ( adapter - > hw_status = = MWIFIEX_HW_STATUS_NOT_READY )
2016-11-16 18:39:05 +05:30
return ;
2011-03-21 18:00:50 -07:00
2013-03-15 18:47:07 -07:00
/* cancel current command */
if ( adapter - > curr_cmd ) {
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , WARN ,
" curr_cmd is still in processing \n " ) ;
2014-02-18 15:47:55 -08:00
del_timer_sync ( & adapter - > cmd_timer ) ;
2013-04-01 12:44:46 -07:00
mwifiex_recycle_cmd_node ( adapter , adapter - > curr_cmd ) ;
2013-03-15 18:47:07 -07:00
adapter - > curr_cmd = NULL ;
}
2011-03-21 18:00:50 -07:00
/* shut down mwifiex */
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , MSG ,
" info: shutdown mwifiex... \n " ) ;
2011-03-21 18:00:50 -07:00
/* Clean up Tx/Rx queues and delete BSS priority table */
for ( i = 0 ; i < adapter - > priv_num ; i + + ) {
if ( adapter - > priv [ i ] ) {
priv = adapter - > priv [ i ] ;
2014-11-13 21:54:16 +05:30
mwifiex_clean_auto_tdls ( priv ) ;
2015-01-28 15:54:21 +05:30
mwifiex_abort_cac ( priv ) ;
2017-05-12 09:42:03 -07:00
mwifiex_free_priv ( priv ) ;
2011-03-21 18:00:50 -07:00
}
}
2015-03-13 17:37:57 +05:30
atomic_set ( & adapter - > tx_queued , 0 ) ;
while ( ( skb = skb_dequeue ( & adapter - > tx_data_q ) ) )
mwifiex_write_data_complete ( adapter , skb , 0 , 0 ) ;
2019-06-25 10:40:45 -07:00
spin_lock_bh ( & adapter - > rx_proc_lock ) ;
2014-09-12 20:08:59 +05:30
while ( ( skb = skb_dequeue ( & adapter - > rx_data_q ) ) ) {
struct mwifiex_rxinfo * rx_info = MWIFIEX_SKB_RXCB ( skb ) ;
atomic_dec ( & adapter - > rx_pending ) ;
priv = adapter - > priv [ rx_info - > bss_num ] ;
if ( priv )
priv - > stats . rx_dropped + + ;
dev_kfree_skb_any ( skb ) ;
}
2019-06-25 10:40:45 -07:00
spin_unlock_bh ( & adapter - > rx_proc_lock ) ;
2014-09-12 20:08:59 +05:30
2013-05-17 17:50:18 -07:00
mwifiex_adapter_cleanup ( adapter ) ;
2011-03-21 18:00:50 -07:00
2016-11-16 18:39:05 +05:30
adapter - > hw_status = MWIFIEX_HW_STATUS_NOT_READY ;
2011-03-21 18:00:50 -07:00
}
/*
* This function downloads the firmware to the card .
*
* The actual download is preceded by two sanity checks -
* - Check if firmware is already running
* - Check if the interface is the winner to download the firmware
*
* . . . and followed by another -
* - Check if the firmware is downloaded successfully
*
* After download is successfully completed , the host interrupts are enabled .
*/
int mwifiex_dnld_fw ( struct mwifiex_adapter * adapter ,
struct mwifiex_fw_image * pmfw )
{
2011-10-11 17:41:21 -07:00
int ret ;
2011-03-21 18:00:50 -07:00
u32 poll_num = 1 ;
2020-09-06 13:05:48 -07:00
/* check if firmware is already running */
ret = adapter - > if_ops . check_fw_status ( adapter , poll_num ) ;
if ( ! ret ) {
mwifiex_dbg ( adapter , MSG ,
" WLAN FW already running! Skip FW dnld \n " ) ;
return 0 ;
2016-01-06 23:40:47 -08:00
}
/* check if we are the winner for downloading FW */
if ( adapter - > if_ops . check_winner_status ) {
adapter - > winner = 0 ;
ret = adapter - > if_ops . check_winner_status ( adapter ) ;
2012-04-18 20:08:28 -07:00
poll_num = MAX_FIRMWARE_POLL_TRIES ;
2016-01-06 23:40:47 -08:00
if ( ret ) {
mwifiex_dbg ( adapter , MSG ,
" WLAN read winner status failed! \n " ) ;
return ret ;
}
2012-04-18 20:08:28 -07:00
if ( ! adapter - > winner ) {
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , MSG ,
2016-01-06 23:40:47 -08:00
" WLAN is not the winner! Skip FW dnld \n " ) ;
2012-04-18 20:08:28 -07:00
goto poll_fw ;
}
2011-03-21 18:00:50 -07:00
}
2012-04-18 20:08:28 -07:00
2011-03-21 18:00:50 -07:00
if ( pmfw ) {
/* Download firmware with helper */
ret = adapter - > if_ops . prog_fw ( adapter , pmfw ) ;
if ( ret ) {
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , ERROR ,
" prog_fw failed ret=%#x \n " , ret ) ;
2011-03-21 18:00:50 -07:00
return ret ;
}
}
poll_fw :
/* Check if the firmware is downloaded successfully or not */
2011-10-11 17:41:21 -07:00
ret = adapter - > if_ops . check_fw_status ( adapter , poll_num ) ;
2013-07-13 10:57:10 -04:00
if ( ret )
2015-05-12 00:48:20 +05:30
mwifiex_dbg ( adapter , ERROR ,
" FW failed to be active in time \n " ) ;
2012-04-18 20:08:28 -07:00
2011-03-21 18:00:50 -07:00
return ret ;
}
2016-06-16 11:01:10 +02:00
EXPORT_SYMBOL_GPL ( mwifiex_dnld_fw ) ;