rsi: Management frames internal to device
PATCH 8/9 rsi: Management frames internal to device
From: Jahnavi Meher <[email protected]>
This patch has the functions which prepare mgmt frames that are internal to the device and also handle exchange of these internal mgmt frames with the device.
Signed-off-by Jahnavi Meher <[email protected]>
---
rsi_91x_mgmt.c | 1345 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1345 insertions(+)
drivers/net/wireless/rsi/91x/rsi_91x_mgmt.c +1345 -0
@@ -0,0 +1,1345 @@ +/** +* @file rsi_91x_mgmt.c +* @author +* @version 1.0 +* +* @section LICENSE +* Copyright (c) 2013 Redpine Signals Inc. +* +* Permission to use, copy, modify, and/or distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +* +* @section DESCRIPTION +* +* The file contains the message information exchanged between the +* driver and underlying device. +*/ + +#include "../include/rsi_main.h" +#include "../include/rsi_hw_intf.h" +#include "../include/rsi_device_ops.h" +#include "../include/rsi_mgmt.h" +#include "../include/rsi_mac80211.h" + +static struct bootup_params boot_params_20 = { + .magic_number =cpu_to_le16 (0x5aa5 ), + .crystal_good_time =0x0 , + .valid =cpu_to_le32 (VALID_20 ), + .reserved_for_valids =0x0 , + .bootup_mode_info =0x0 , + .digital_loop_back_params =0x0 , + .rtls_timestamp_en =0x0 , + .host_spi_intr_cfg =0x0 , + .device_clk_info = {{ + .pll_config_g = { + .tapll_info_g = { + .pll_reg_1 =cpu_to_le16 ((TA_PLL_N_VAL_20 <<8 )| + (TA_PLL_M_VAL_20 )), + .pll_reg_2 =cpu_to_le16 (TA_PLL_P_VAL_20 ), + }, + .pll960_info_g = { + .pll_reg_1 =cpu_to_le16 ((PLL960_P_VAL_20 <<8 )| + (PLL960_N_VAL_20 )), + .pll_reg_2 =cpu_to_le16 (PLL960_M_VAL_20 ), + .pll_reg_3 =0x0 , + }, + .afepll_info_g = { + .pll_reg =cpu_to_le16 (0x9f0 ), + } + }, + .switch_clk_g = { + .switch_umac_clk =0x0 , + .switch_qspi_clk =0x0 , + .switch_slp_clk_2_32 =0x0 , + .switch_bbp_lmac_clk_reg =0x1 , + .switch_mem_ctrl_cfg =0x0 , + .reserved =0x0 , + .bbp_lmac_clk_reg_val =cpu_to_le16 (0x121 ), + .umac_clock_reg_config =0x0 , + .qspi_uart_clock_reg_config =0x0 + } + }, + { + .pll_config_g = { + .tapll_info_g = { + .pll_reg_1 =cpu_to_le16 ((TA_PLL_N_VAL_20 <<8 )| + (TA_PLL_M_VAL_20 )), + .pll_reg_2 =cpu_to_le16 (TA_PLL_P_VAL_20 ), + }, + .pll960_info_g = { + .pll_reg_1 =cpu_to_le16 ((PLL960_P_VAL_20 <<8 )| + (PLL960_N_VAL_20 )), + .pll_reg_2 =cpu_to_le16 (PLL960_M_VAL_20 ), + .pll_reg_3 =0x0 , + }, + .afepll_info_g = { + .pll_reg =cpu_to_le16 (0x9f0 ), + } + }, + .switch_clk_g = { + .switch_umac_clk =0x0 , + .switch_qspi_clk =0x0 , + .switch_slp_clk_2_32 =0x0 , + .switch_bbp_lmac_clk_reg =0x0 , + .switch_mem_ctrl_cfg =0x0 , + .reserved =0x0 , + .bbp_lmac_clk_reg_val =0x0 , + .umac_clock_reg_config =0x0 , + .qspi_uart_clock_reg_config =0x0 + } + }, + { + .pll_config_g = { + .tapll_info_g = { + .pll_reg_1 =cpu_to_le16 ((TA_PLL_N_VAL_20 <<8 )| + (TA_PLL_M_VAL_20 )), + .pll_reg_2 =cpu_to_le16 (TA_PLL_P_VAL_20 ), + }, + .pll960_info_g = { + .pll_reg_1 =cpu_to_le16 ((PLL960_P_VAL_20 <<8 )| + (PLL960_N_VAL_20 )), + .pll_reg_2 =cpu_to_le16 (PLL960_M_VAL_20 ), + .pll_reg_3 =0x0 , + }, + .afepll_info_g = { + .pll_reg =cpu_to_le16 (0x9f0 ), + } + }, + .switch_clk_g = { + .switch_umac_clk =0x0 , + .switch_qspi_clk =0x0 , + .switch_slp_clk_2_32 =0x0 , + .switch_bbp_lmac_clk_reg =0x0 , + .switch_mem_ctrl_cfg =0x0 , + .reserved =0x0 , + .bbp_lmac_clk_reg_val =0x0 , + .umac_clock_reg_config =0x0 , + .qspi_uart_clock_reg_config =0x0 + } + } }, + .buckboost_wakeup_cnt =0x0 , + .pmu_wakeup_wait =0x0 , + .shutdown_wait_time =0x0 , + .pmu_slp_clkout_sel =0x0 , + .wdt_prog_value =0x0 , + .wdt_soc_rst_delay =0x0 , + .dcdc_operation_mode =0x0 , + .soc_reset_wait_cnt =0x0 +}; + +static struct bootup_params boot_params_40 = { + .magic_number =0x5aa5 , + .crystal_good_time =0x0 , + .valid =VALID_40 , + .reserved_for_valids =0x0 , + .bootup_mode_info =0x0 , + .digital_loop_back_params =0x0 , + .rtls_timestamp_en =0x0 , + .host_spi_intr_cfg =0x0 , + .device_clk_info = {{ + .pll_config_g = { + .tapll_info_g = { + .pll_reg_1 = ((TA_PLL_N_VAL_40 <<8 ) | + (TA_PLL_M_VAL_40 )), + .pll_reg_2 = (TA_PLL_P_VAL_40 ), + }, + .pll960_info_g = { + .pll_reg_1 = ((PLL960_P_VAL_40 <<8 ) | + (PLL960_N_VAL_40 )), + .pll_reg_2 =PLL960_M_VAL_40 , + .pll_reg_3 =0x0 , + }, + .afepll_info_g = { + .pll_reg =0x9f0 , + } + }, + .switch_clk_g = { + .switch_umac_clk =0x1 , + .switch_qspi_clk =0x0 , + .switch_slp_clk_2_32 =0x0 , + .switch_bbp_lmac_clk_reg =0x1 , + .switch_mem_ctrl_cfg =0x0 , + .reserved =0x0 , + .bbp_lmac_clk_reg_val =0x1121 , + .umac_clock_reg_config =0x48 , + .qspi_uart_clock_reg_config =0x0 + } + }, + { + .pll_config_g = { + .tapll_info_g = { + .pll_reg_1 = ((TA_PLL_N_VAL_40 <<8 ) | + (TA_PLL_M_VAL_40 )), + .pll_reg_2 = (TA_PLL_P_VAL_40 ) + }, + .pll960_info_g = { + .pll_reg_1 = ((PLL960_P_VAL_40 <<8 ) | + (PLL960_N_VAL_40 )), + .pll_reg_2 =PLL960_M_VAL_40 , + .pll_reg_3 =0x0 , + }, + .afepll_info_g = { + .pll_reg =0x9f0 , + } + }, + .switch_clk_g = { + .switch_umac_clk =0x0 , + .switch_qspi_clk =0x0 , + .switch_slp_clk_2_32 =0x0 , + .switch_bbp_lmac_clk_reg =0x0 , + .switch_mem_ctrl_cfg =0x0 , + .reserved =0x0 , + .bbp_lmac_clk_reg_val =0x0 , + .umac_clock_reg_config =0x0 , + .qspi_uart_clock_reg_config =0x0 + } + }, + { + .pll_config_g = { + .tapll_info_g = { + .pll_reg_1 = ((TA_PLL_N_VAL_40 <<8 ) | + (TA_PLL_M_VAL_40 )), + .pll_reg_2 = (TA_PLL_P_VAL_40 ), + }, + .pll960_info_g = { + .pll_reg_1 = ((PLL960_P_VAL_40 <<8 ) | + (PLL960_N_VAL_40 )), + .pll_reg_2 =PLL960_M_VAL_40 , + .pll_reg_3 =0x0 , + }, + .afepll_info_g = { + .pll_reg =0x9f0 , + } + }, + .switch_clk_g = { + .switch_umac_clk =0x0 , + .switch_qspi_clk =0x0 , + .switch_slp_clk_2_32 =0x0 , + .switch_bbp_lmac_clk_reg =0x0 , + .switch_mem_ctrl_cfg =0x0 , + .reserved =0x0 , + .bbp_lmac_clk_reg_val =0x0 , + .umac_clock_reg_config =0x0 , + .qspi_uart_clock_reg_config =0x0 + } + } }, + .buckboost_wakeup_cnt =0x0 , + .pmu_wakeup_wait =0x0 , + .shutdown_wait_time =0x0 , + .pmu_slp_clkout_sel =0x0 , + .wdt_prog_value =0x0 , + .wdt_soc_rst_delay =0x0 , + .dcdc_operation_mode =0x0 , + .soc_reset_wait_cnt =0x0 +}; + +static unsigned short mcs[] = {13 ,26 ,39 ,52 ,78 ,104 ,117 ,130 }; + +/** +* This function sets the contention values for the backoff procedure. +* +* @param common Pointer to the driver common structure. +* @return None. +*/ +static void rsi_set_contention_vals (struct rsi_common *common) +{ +unsigned char ii =0 ; + +for (ii =0 ; ii <NUM_EDCA_QUEUES ; ii++) { + common->tx_qinfo[ii].wme_params = + (((common->edca_params[ii].cw_min /2 ) + + (common->edca_params[ii].aifs)) * +WMM_SHORT_SLOT_TIME +SIFS_DURATION ); + common->tx_qinfo[ii].weight = common->tx_qinfo[ii].wme_params; + common->tx_qinfo[ii].pkt_contended =0 ; + } +} + +/** +* This function sends management frame to firmware. +* Also schedules packet to queue for transmit. +* +* @param common Pointer to the driver private structure. +* @param addr Pointer to rsi mac frame structure. +* @param len Length. +* @return 0 on success, -1 on failure. +*/ +static int rsi_send_internal_mgmt_frame (struct rsi_common *common, +struct sk_buff *skb) +{ +struct skb_info *tx_params; + +if (skb ==NULL ) { +rsi_dbg (ERR_ZONE ,"%s: Unable to allocate skb\n" , __func__); +return -1 ; + } + tx_params = (struct skb_info *)&IEEE80211_SKB_CB (skb)->driver_data; + tx_params->flags |=INTERNAL_MGMT_PKT ; +skb_queue_tail (&common->tx_queue[MGMT_SOFT_Q ], skb); + common->common_ops->set_event (&common->tx_event); +return 0 ; +} + +/** +* This function used to send radio capabilities values to firmware. +* +* @param common Pointer to the driver private structure. +* @return 0 on success, corresponding negative error code on failure. +*/ +static int rsi_load_radio_caps (struct rsi_common *common) +{ +struct rsi_mac_frame *mgmt_frame; +struct rsi_hw *adapter = common->priv; +struct ieee80211_hw *hw = adapter->hw; +unsigned short inx =0 ; +unsigned char ii; +unsigned char radio_id =0 ; +unsigned short gc[20 ] = {0xf0 ,0xf0 ,0xf0 ,0xf0 , +0xf0 ,0xf0 ,0xf0 ,0xf0 , +0xf0 ,0xf0 ,0xf0 ,0xf0 , +0xf0 ,0xf0 ,0xf0 ,0xf0 , +0xf0 ,0xf0 ,0xf0 ,0xf0 }; +struct ieee80211_conf *conf = &hw->conf; +struct sk_buff *skb; + +rsi_dbg (INFO_ZONE , +"%s: Sending rate symbol req frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); + +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + + mgmt_frame->desc_word[1 ] =cpu_to_le16 (RADIO_CAPABILITIES ); + mgmt_frame->desc_word[4 ] =cpu_to_le16 (RSI_RF_TYPE <<8 ); + +if (common->channel_width ==BW_40MHZ ) { + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (RSI_LMAC_CLOCK_80MHZ ); + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (RSI_ENABLE_40MHZ ); +if (common->channel_width) { + mgmt_frame->desc_word[5 ] = +cpu_to_le16 (common->channel_width <<12 ); + mgmt_frame->desc_word[5 ] |=cpu_to_le16 (FULL40M_ENABLE ); + } + +if (conf_is_ht40_minus (conf)) { + mgmt_frame->desc_word[5 ] =0 ; + mgmt_frame->desc_word[5 ] |= +cpu_to_le16 (LOWER_20_ENABLE ); + mgmt_frame->desc_word[5 ] |= +cpu_to_le16 (LOWER_20_ENABLE >>12 ); + } + +if (conf_is_ht40_plus (conf)) { + mgmt_frame->desc_word[5 ] =0 ; + mgmt_frame->desc_word[5 ] |= +cpu_to_le16 (UPPER_20_ENABLE ); + mgmt_frame->desc_word[5 ] |= +cpu_to_le16 (UPPER_20_ENABLE >>12 ); + } + } + + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (radio_id <<8 ); + +for (ii =0 ; ii <MAX_HW_QUEUES ; ii++) { + mgmt_frame->u.radio_caps.qos_params[ii].cont_win_min_q = +cpu_to_le16 (3 ); + mgmt_frame->u.radio_caps.qos_params[ii].cont_win_max_q = +cpu_to_le16 (0x3f ); + mgmt_frame->u.radio_caps.qos_params[ii].aifsn_val_q = +cpu_to_le16 (2 ); + mgmt_frame->u.radio_caps.qos_params[ii].txop_q =0 ; + } + +for (ii =0 ; ii <MAX_HW_QUEUES -4 ; ii++) { + mgmt_frame->u.radio_caps.qos_params[ii].cont_win_min_q = +cpu_to_le16 (common->edca_params[ii].cw_min); + mgmt_frame->u.radio_caps.qos_params[ii].cont_win_max_q = +cpu_to_le16 (common->edca_params[ii].cw_max); + mgmt_frame->u.radio_caps.qos_params[ii].aifsn_val_q = +cpu_to_le16 ((common->edca_params[ii].aifs) <<8 ); + mgmt_frame->u.radio_caps.qos_params[ii].txop_q = +cpu_to_le16 (common->edca_params[ii].txop); + } + +memcpy (&common->rate_pwr[0 ], &gc[0 ],40 ); +for (ii =0 ; ii <20 ; ii++) + mgmt_frame->u.radio_caps.gcpd_per_rate[inx++] = +cpu_to_le16 (common->rate_pwr[ii] &0x00FF ); + + mgmt_frame->desc_word[0 ] =cpu_to_le16 (sizeof (mgmt_frame->u.radio_caps)| + (RSI_WIFI_MGMT_Q <<12 )); + + +skb_put (skb, (sizeof (mgmt_frame->u.radio_caps) +FRAME_DESC_SZ )); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function is the entry point of Management module. +* +* @param common Pointer to the driver private structure. +* @param msg Pointer to received packet. +* @param msg_len Length of the recieved packet. +* @param type Type of recieved packet. +* @return 0 on success, -1 on failure. +*/ +static int rsi_mgmt_pkt_to_core (struct rsi_common *common, +unsigned char *msg, +int msg_len, +unsigned char type) +{ +struct ieee80211_tx_info *info; +struct skb_info *rx_params; +unsigned char pad_bytes = msg[4 ]; +unsigned char pkt_recv; +struct sk_buff *skb; +char *buffer; + +if (type ==RX_DOT11_MGMT ) { + msg_len -= pad_bytes; +if ((msg_len <=0 ) || (!msg)) { +rsi_dbg (MGMT_RX_ZONE ,"Invalid rx msg of len = %d\n" , + __func__, msg_len); +return -1 ; + } + + skb =dev_alloc_skb (msg_len); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed to allocate skb\n" , + __func__); +return -1 ; + } + + buffer =skb_put (skb, msg_len); + +memcpy (buffer, + (unsigned char *)(msg +FRAME_DESC_SZ + pad_bytes), + msg_len); + + pkt_recv = buffer[0 ]; + +if ((pkt_recv !=0x50 ) && (pkt_recv !=0x80 ) && + (pkt_recv !=0x40 )) { +rsi_dbg (MGMT_RX_ZONE ,"%s: ===> MGMT PKT RCVD <===\n" , + __func__); + } + info =IEEE80211_SKB_CB (skb); + rx_params = (struct skb_info *)info->driver_data; + rx_params->rssi =rsi_get_rssi (msg); + rx_params->channel =rsi_get_channel (msg); +rsi_indicate_pkt_to_os (common, skb); + }else { +rsi_dbg (MGMT_TX_ZONE ,"%s: Internal Packet\n" , __func__); + } + +return 0 ; +} + +/** +* This function sends station notify frame to firmware. +* +* @param common Pointer to the driver private structure. +* @param opmode Operating mode of device. +* @param notify_event Notification about station connection. +* @param bssid bssid. +* @param qos_enable Qos is enabled. +* @param aid Aid (unique for all STA). +* @return status: 0 on success, corresponding negative error code on failure. +*/ +static int rsi_hal_send_sta_notify_frame (struct rsi_common *common, +unsigned char opmode, +unsigned char notify_event, +const unsigned char *bssid, +unsigned char qos_enable, +unsigned short aid) +{ +struct sk_buff *skb =NULL ; +struct rsi_mac_frame *mgmt_frame; +unsigned short vap_id =0 ; +int status; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending sta notify frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); + +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + + mgmt_frame->u.peer_notify.command =cpu_to_le16 (opmode <<1 ); + +switch (notify_event) { +case STA_CONNECTED : + mgmt_frame->u.peer_notify.command |=cpu_to_le16 (RSI_ADD_PEER ); +break ; +case STA_DISCONNECTED : + mgmt_frame->u.peer_notify.command |= +cpu_to_le16 (RSI_DELETE_PEER ); +break ; +case STA_TX_ADDBA_DONE : +case STA_TX_DELBA : +case STA_RX_ADDBA_DONE : +case STA_RX_DELBA : +break ; +default : +break ; + } + + mgmt_frame->u.peer_notify.command |=cpu_to_le16 ((aid &0xfff ) <<4 ); +memcpy (mgmt_frame->u.peer_notify.mac_addr, bssid,ETH_ALEN ); + mgmt_frame->u.peer_notify.sta_flags =cpu_to_le16 ((qos_enable) ?1 :0 ); + + mgmt_frame->desc_word[0 ] = +cpu_to_le16 (sizeof (mgmt_frame->u.peer_notify) | + (RSI_WIFI_MGMT_Q <<12 )); + mgmt_frame->desc_word[1 ] =cpu_to_le16 (PEER_NOTIFY ); + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (vap_id <<8 ); + +skb_put (skb,sizeof (mgmt_frame->u.peer_notify) +FRAME_DESC_SZ ); + + status =rsi_send_internal_mgmt_frame (common, skb); + +if ((!status) && (qos_enable)) { +rsi_set_contention_vals (common); + status =rsi_load_radio_caps (common); + } +return status; +} + +/** +* This function sends ampdu indication frame to firmware. +* +* @param common Pointer to the driver private structure. +* @param tid traffic identifier. +* @param ssn ssn. +* @param buf_size buffer size (for kernel version > 2.6.38). +* @param event notification about station connection. +* @return 0 on success, corresponding negative error code on failure. +*/ +int rsi_send_ampdu_indication_frame (struct rsi_common *common, +unsigned short tid, +unsigned short ssn, +unsigned char buf_size, +unsigned char event) +{ +struct sk_buff *skb =NULL ; +struct rsi_mac_frame *mgmt_frame; +unsigned char peer_id =0 ; + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); + +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending AMPDU indication frame\n" , __func__); + + mgmt_frame->desc_word[0 ] =cpu_to_le16 (RSI_WIFI_MGMT_Q <<12 ); + mgmt_frame->desc_word[1 ] =cpu_to_le16 (AMPDU_IND ); + +if (event ==STA_TX_ADDBA_DONE ) { + mgmt_frame->desc_word[4 ] =cpu_to_le16 (ssn); + mgmt_frame->desc_word[5 ] =cpu_to_le16 (buf_size); + mgmt_frame->desc_word[7 ] = +cpu_to_le16 ((tid | (START_AMPDU_AGGR <<4 ) | (peer_id <<8 ))); + }else if (event ==STA_RX_ADDBA_DONE ) { + mgmt_frame->desc_word[4 ] =cpu_to_le16 (ssn); + mgmt_frame->desc_word[7 ] =cpu_to_le16 (tid | + (START_AMPDU_AGGR <<4 ) | + (RX_BA_INDICATION <<5 ) | + (peer_id <<8 )); + }else if (event ==STA_TX_DELBA ) { + mgmt_frame->desc_word[7 ] =cpu_to_le16 (tid | + (STOP_AMPDU_AGGR <<4 ) | + (peer_id <<8 )); + }else if (event ==STA_RX_DELBA ) { + mgmt_frame->desc_word[7 ] =cpu_to_le16 (tid | + (STOP_AMPDU_AGGR <<4 ) | + (RX_BA_INDICATION <<5 ) | + (peer_id <<8 )); + } + +skb_put (skb,FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function starts base band and RF programming. +* This is called after initial configurations are done. +* +* @param common Pointer to the driver private structure. +* @return 0 on success, corresponding negative error code on failure. +*/ +static int rsi_program_bb_rf (struct rsi_common *common) +{ +struct sk_buff *skb; +struct rsi_mac_frame *mgmt_frame; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending program BB/RF frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + +#ifdef USE_USB_INTF + mgmt_frame->desc_word[0 ] =cpu_to_le16 (RSI_WIFI_MGMT_Q <<12 ); +#else + mgmt_frame->desc_word[0 ] =cpu_to_le16 ((FRAME_DESC_SZ ) | + (RSI_WIFI_MGMT_Q <<12 )); +#endif + mgmt_frame->desc_word[1 ] =cpu_to_le16 (BBP_PROG_IN_TA ); + mgmt_frame->desc_word[4 ] =cpu_to_le16 (common->endpoint <<8 ); + +if (common->rf_reset) { + mgmt_frame->desc_word[7 ] =cpu_to_le16 (RF_RESET_ENABLE ); +rsi_dbg (MGMT_TX_ZONE ,"%s: ===> RF RESET REQUEST SENT <===\n" , + __func__); + common->rf_reset =0 ; + } + common->bb_rf_prog_count =1 ; + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (PUT_BBP_RESET | +BBP_REG_WRITE | (RSI_RF_TYPE <<4 )); +skb_put (skb,FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function sends vap capabilities to firmware. +* +* @param common Pointer to the driver private structure. +* @param opmode Operating mode of device. +* @return 0 on success, corresponding negative error code on failure. +*/ +int rsi_set_vap_capabilities (struct rsi_common *common, +unsigned char opmode) +{ +struct sk_buff *skb =NULL ; +struct rsi_mac_frame *mgmt_frame; +unsigned short vap_id =0 ; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending VAP capabilities frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + + mgmt_frame->desc_word[0 ] =cpu_to_le16 ((sizeof (mgmt_frame->u.vap_caps))| + (RSI_WIFI_MGMT_Q <<12 )); + mgmt_frame->desc_word[1 ] =cpu_to_le16 (VAP_CAPABILITIES ); + mgmt_frame->desc_word[4 ] =cpu_to_le16 (opmode | + (common->channel_width <<8 )); + mgmt_frame->desc_word[7 ] =cpu_to_le16 ((vap_id <<8 ) | + (common->mac_id <<4 ) | + common->radio_id); + +memcpy (mgmt_frame->u.vap_caps.mac_addr, + common->mac_addr, +IEEE80211_ADDR_LEN ); + mgmt_frame->u.vap_caps.keep_alive_period =cpu_to_le16 (90 ); + mgmt_frame->u.vap_caps.frag_threshold =cpu_to_le16 (MAX_FRAG_LEN ); + + mgmt_frame->u.vap_caps.rts_threshold = +cpu_to_le16 (common->rts_threshold); + mgmt_frame->u.vap_caps.default_mgmt_rate_bbpinfo =0 ; +if (conf_is_ht40 (&common->priv->hw->conf)) { + mgmt_frame->u.vap_caps.default_ctrl_rate_bbpinfo = +cpu_to_le16 (RSI_RATE_6 |FULL40M_ENABLE <<16 ); + }else { + mgmt_frame->u.vap_caps.default_ctrl_rate_bbpinfo = +RSI_RATE_6 ; + } + mgmt_frame->u.vap_caps.default_data_rate_bbpinfo =cpu_to_le16 (0 ); + mgmt_frame->u.vap_caps.beacon_interval =cpu_to_le16 (200 ); + mgmt_frame->u.vap_caps.dtim_period =cpu_to_le16 (4 ); + +skb_put (skb,sizeof (mgmt_frame->u.vap_caps) +FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function is used to load the keys within the firmware. +* +* @param common Pointer to the driver private structure. +* @param data Pointer to the key data. +* @param key_len Key length to be loaded. +* @param key_type Type of key: GROUP/PAIRWISE. +* @param key_id Key index. +* @param cipher Type of cipher used. +* @return 0 on success, -1 on failure. +*/ +int rsi_hal_load_key (struct rsi_common *common, +unsigned char *data, +unsigned short key_len, +unsigned char key_type, +unsigned char key_id, +unsigned int cipher) +{ +struct sk_buff *skb =NULL ; +struct rsi_mac_frame *mgmt_frame; +unsigned char key_t1 =0 ; +unsigned short key_descriptor =0 ; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending load key frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + +switch (key_type) { +case RSI_GROUP_KEY : + key_t1 = (1 <<1 ); +break ; +case RSI_PAIRWISE_KEY : + key_t1 = (0 <<1 ); +if ((cipher !=WLAN_CIPHER_SUITE_WEP40 ) && + (cipher !=WLAN_CIPHER_SUITE_WEP104 )) + key_id =0 ; +break ; + } + + key_descriptor |= (key_t1 |BIT (13 ) | (key_id <<14 )); +if ((cipher ==WLAN_CIPHER_SUITE_WEP40 ) || + (cipher ==WLAN_CIPHER_SUITE_WEP104 )) { + key_len +=1 ; + key_descriptor |=BIT (2 ); +if (key_len >=13 ) + key_descriptor |=BIT (3 ); + }else if (cipher !=KEY_TYPE_CLEAR ) { + key_descriptor |=BIT (4 ); +if (cipher ==WLAN_CIPHER_SUITE_TKIP ) + key_descriptor |=BIT (5 ); + } + + mgmt_frame->desc_word[0 ] =cpu_to_le16 (sizeof (mgmt_frame->u.set_key) | + (RSI_WIFI_MGMT_Q <<12 )); + mgmt_frame->desc_word[1 ] =cpu_to_le16 (SET_KEY_REQ ); + mgmt_frame->desc_word[4 ] =cpu_to_le16 (key_descriptor); + +if ((cipher ==WLAN_CIPHER_SUITE_WEP40 ) || + (cipher ==WLAN_CIPHER_SUITE_WEP104 )) { +memcpy (&mgmt_frame->u.set_key.key[key_id][1 ], + data, + key_len *2 ); + }else { +memcpy (&mgmt_frame->u.set_key.key[0 ][0 ], data, key_len); + } + +memcpy (&mgmt_frame->u.set_key.tx_mic_key, &data[16 ],8 ); +memcpy (&mgmt_frame->u.set_key.rx_mic_key, &data[24 ],8 ); + +skb_put (skb,sizeof (mgmt_frame->u.set_key) +FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function sends bootup parameters to the firmware. +* +* @param common Pointer to the driver private structure. +* @return 0 on success, corresponding error code on failure. +*/ +static unsigned char rsi_load_bootup_params (struct rsi_common *common) +{ +struct sk_buff *skb; +struct rsi_mac_frame *mgmt_frame; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending boot params frame\n" , __func__); + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + +rsi_dbg (MGMT_TX_ZONE ,"%s:\n" , __func__); + +if (common->channel_width ==BW_40MHZ ) { +memcpy (&mgmt_frame->u.bootup_params, + &boot_params_40, +sizeof (struct bootup_params )); +rsi_dbg (MGMT_TX_ZONE ,"%s: Packet 40MHZ <=== %d\n" , __func__, +UMAC_CLK_40BW ); + mgmt_frame->desc_word[7 ] = (UMAC_CLK_40BW ); + }else { +memcpy (&mgmt_frame->u.bootup_params, + &boot_params_20, +sizeof (struct bootup_params )); +if (boot_params_20.valid !=VALID_20 ) { + mgmt_frame->desc_word[7 ] = (UMAC_CLK_20BW ); +rsi_dbg (MGMT_TX_ZONE , +"%s: Packet 20MHZ <=== %d\n" , __func__, +UMAC_CLK_20BW ); + }else { + mgmt_frame->desc_word[7 ] = (UMAC_CLK_40MHZ ); +rsi_dbg (MGMT_TX_ZONE , +"%s: Packet 20MHZ <=== %d\n" , __func__, +UMAC_CLK_40MHZ ); + } + } + +/* Bit{0:11} indicates length of the Packet +* Bit{12:15} indicates host queue number +*/ + mgmt_frame->desc_word[0 ] = (sizeof (struct bootup_params ) | + (RSI_WIFI_MGMT_Q <<12 )); + mgmt_frame->desc_word[1 ] = (BOOTUP_PARAMS_REQUEST ); + +skb_put (skb,sizeof (struct bootup_params ) +FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function prepares reset MAC request and sends a internal management +* frame to indicate it to firmware. +* +* @param common Pointer to the driver private structure. +* @return 0 on success, corresponding error code on failure. +*/ +static int rsi_send_reset_mac (struct rsi_common *common) +{ +struct sk_buff *skb; +struct rsi_mac_frame *mgmt_frame; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending reset MAC frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + + mgmt_frame->desc_word[0 ] =cpu_to_le16 (RSI_WIFI_MGMT_Q <<12 ); + mgmt_frame->desc_word[1 ] =cpu_to_le16 (RESET_MAC_REQ ); + mgmt_frame->desc_word[4 ] |=cpu_to_le16 (RETRY_COUNT <<8 ); + +skb_put (skb,FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function programs the channel. +* +* @param common Pointer to the driver private structure. +* @param channel Channel value to be set. +* @return 0 on success, corresponding error code on failure. +*/ +int rsi_set_channel (struct rsi_common *common,unsigned short channel) +{ +struct sk_buff *skb =NULL ; +struct rsi_mac_frame *mgmt_frame; + +rsi_dbg (MGMT_TX_ZONE , +"%s: Sending scan req frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + +if (common->band ==IEEE80211_BAND_5GHZ ) { +if ((channel >=36 ) && (channel <=64 )) + channel = ((channel -32 ) /4 ); +else if ((channel >64 ) && (channel <=140 )) + channel = ((channel -102 ) /4 ) +8 ; +else if (channel >=149 ) + channel = ((channel -151 ) /4 ) +18 ; +else +return -1 ; + }else { +if (channel >14 ) { +rsi_dbg (ERR_ZONE ,"%s: Invalid chno %d, band = %d\n" , + __func__, channel, common->band); +return 0 ; + } + } + + mgmt_frame->desc_word[0 ] = ((sizeof (mgmt_frame->u.rf_prog_req)) | + (RSI_WIFI_MGMT_Q <<12 )); + mgmt_frame->desc_word[1 ] = (SCAN_REQUEST ); + mgmt_frame->desc_word[4 ] = channel; + + mgmt_frame->desc_word[7 ] = (PUT_BBP_RESET | +BBP_REG_WRITE | + (RSI_RF_TYPE <<4 )); + + + mgmt_frame->desc_word[4 ] = channel; + mgmt_frame->desc_word[5 ] =0x01 ; + +if (common->channel_width ==BW_40MHZ ) + mgmt_frame->desc_word[5 ] |= (0x1 <<8 ); + + common->channel = channel; + +skb_put (skb,sizeof (mgmt_frame->u.rf_prog_req) +FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function is used to compare two integers +* +* @param pointer to the first integer +* @param pointer to the second integer +* @return 0 if both are equal, -1 if the first is smaller, else 1 +*/ +static int rsi_compare (const void *a,const void *b) +{ +unsigned short int_a = *(const unsigned short *)(a); +unsigned short int_b = *(const unsigned short *)(b); + +if (int_a > int_b) +return -1 ; + +if (int_a < int_b) +return 1 ; + +return 0 ; +} + +/** +* This function is used to map the selected rates to hw rates +* +* @param the standard rate to be mapped +* @param offset that will be returned +* @return 0 if it is a mcs rate, else 1 +*/ +static bool rsi_map_rates (unsigned short rate,int *offset) +{ +int kk; +for (kk =0 ; kk <ARRAY_SIZE (rsi_mcsrates); kk++) { +if (rate == mcs[kk]) { + *offset = kk; +return 0 ; + } + } + +for (kk =0 ; kk <ARRAY_SIZE (rsi_rates); kk++) { +if (rate == rsi_rates[kk].bitrate/5 ) { + *offset = kk; +break ; + } + } +return 1 ; +} + +/** +* This function sets rates for connection ,sends autorate request. +* +* @param common Pointer to the driver private structure. +* @return 0 on success, corresponding error code on failure. +*/ +static int rsi_send_auto_rate_request (struct rsi_common *common) +{ +struct sk_buff *skb; +struct rsi_mac_frame *mgmt_frame; +int ii, jj, kk; +struct ieee80211_hw *hw = common->priv->hw; +unsigned char band = hw->conf.chandef.chan->band; +unsigned char num_supported_rates =0 ; +unsigned char rate_offset =0 ; +unsigned int rate_bitmap = common->bitrate_mask[band]; + +unsigned short *selected_rates, min_rate; + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + + selected_rates =kmalloc (2 *RSI_TBL_SZ ,GFP_KERNEL ); + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); +memset (selected_rates,0 ,2 *RSI_TBL_SZ ); + + mgmt_frame = (struct rsi_mac_frame *)skb->data; + + mgmt_frame->u.auto_rate.aarf_rssi =cpu_to_le16 ((( + (unsigned short )3 <<6 ) | + (unsigned short )(18 &0x3f ))); + mgmt_frame->u.auto_rate.collision_tolerance =cpu_to_le16 (3 ); + mgmt_frame->u.auto_rate.failure_limit =cpu_to_le16 (3 ); + mgmt_frame->u.auto_rate.initial_boundary =cpu_to_le16 (3 ); + mgmt_frame->u.auto_rate.max_threshold_limt =cpu_to_le16 (27 ); + + mgmt_frame->desc_word[1 ] =cpu_to_le16 (AUTO_RATE_IND ); + +if (common->channel_width ==BW_40MHZ ) + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (1 ); + +if (band ==IEEE80211_BAND_2GHZ ) + min_rate =STD_RATE_01 ; +else + min_rate =STD_RATE_06 ; + +for (ii =0 , jj =0 ; ii <ARRAY_SIZE (rsi_rates); ii++) { +if (rate_bitmap &BIT (ii)) { + selected_rates[jj++] = (rsi_rates[ii].bitrate /5 ); + rate_offset++; + } + } + num_supported_rates = jj; + +if (common->vif_info[0 ].is_ht) { +for (ii =0 ; ii <ARRAY_SIZE (mcs); ii++) + selected_rates[jj++] = mcs[ii]; + num_supported_rates +=ARRAY_SIZE (mcs); + rate_offset +=ARRAY_SIZE (mcs); + } + +if (rate_offset < (RSI_TBL_SZ /2 ) -1 ) { +for (ii = jj; ii < (RSI_TBL_SZ /2 ); ii++) { + selected_rates[jj++] = min_rate; + rate_offset++; + } + } + +sort (selected_rates, jj,sizeof (unsigned short ), &rsi_compare,NULL ); + +/* mapping the rates to RSI rates */ +for (ii =0 ; ii < jj; ii++) { +if (rsi_map_rates (selected_rates[ii], &kk)) { + mgmt_frame->u.auto_rate.supported_rates[ii] = +cpu_to_le16 (rsi_rates[kk].hw_value); + }else { + mgmt_frame->u.auto_rate.supported_rates[ii] = +cpu_to_le16 (rsi_mcsrates[kk]); + } + } + +/* loading HT rates in the bottom half of the AR table */ +if (common->vif_info[0 ].is_ht) { +if (common->vif_info[0 ].sgi) + mgmt_frame->u.auto_rate.supported_rates[rate_offset++] = +cpu_to_le16 (RSI_RATE_MCS7_SG ); + +for (ii = rate_offset, kk =ARRAY_SIZE (rsi_mcsrates)-1 ; + ii < rate_offset +2 *ARRAY_SIZE (rsi_mcsrates); + ii++) { +if (common->vif_info[0 ].sgi) + mgmt_frame->u.auto_rate.supported_rates[ii++] = +cpu_to_le16 (rsi_mcsrates[kk] |BIT (9 )); + mgmt_frame->u.auto_rate.supported_rates[ii] = +cpu_to_le16 (rsi_mcsrates[kk--]); + } + +for (; ii <RSI_TBL_SZ ; ii++) { + mgmt_frame->u.auto_rate.supported_rates[ii] = +cpu_to_le16 (rsi_mcsrates[0 ]); + } + } + + mgmt_frame->u.auto_rate.num_supported_rates = +cpu_to_le16 (num_supported_rates *2 ); + mgmt_frame->u.auto_rate.moderate_rate_inx = +cpu_to_le16 (num_supported_rates /2 ); + mgmt_frame->desc_word[7 ] |=cpu_to_le16 (0 <<8 ); + num_supported_rates *=2 ; + + mgmt_frame->desc_word[0 ] =cpu_to_le16 ((sizeof (mgmt_frame->u.auto_rate) + + num_supported_rates + + (RSI_WIFI_MGMT_Q <<12 ))); + +skb_put (skb, +sizeof (mgmt_frame->u.auto_rate) + num_supported_rates + +FRAME_DESC_SZ ); +kfree (selected_rates); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function informs about bss status with the help of sta notify +* parameters by sending a internal management frame to firmware. +* +* @param common Pointer to the driver private structure. +* @param status Bss status type. +* @param bssid Bssid. +* @param qos_enable Qos is enabled. +* @param aid Aid (unique for all STA). +* @return None. +*/ +void rsi_inform_bss_status (struct rsi_common *common, +unsigned char status, +const unsigned char *bssid, +unsigned char qos_enable, +unsigned short aid) +{ +if (status) { +rsi_hal_send_sta_notify_frame (common, +NL80211_IFTYPE_STATION , +STA_CONNECTED , + bssid, + qos_enable, + aid); +if (common->min_rate ==0xffff ) +rsi_send_auto_rate_request (common); + }else { +rsi_hal_send_sta_notify_frame (common, +NL80211_IFTYPE_STATION , +STA_DISCONNECTED , + bssid, + qos_enable, + aid); + } +return ; +} + +/** +* This function send a frame to read the +* mac address from the eeprom. +* +* @param common Pointer to the driver private structure. +* @return 0 on success, -1 on failure. +*/ +static int rsi_eeprom_read (struct rsi_common *common) +{ +struct rsi_mac_frame *mgmt_frame; +struct sk_buff *skb; + +rsi_dbg (MGMT_TX_ZONE ,"%s: Sending EEPROM read req frame\n" , __func__); + + skb =dev_alloc_skb (MAX_MGMT_PKT_SIZE ); +if (!skb) { +rsi_dbg (ERR_ZONE ,"%s: Failed in allocation of skb\n" , + __func__); +return -1 ; + } + +memset (skb->data,0 ,MAX_MGMT_PKT_SIZE ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + +/* FrameType */ + mgmt_frame->desc_word[1 ] =cpu_to_le16 (EEPROM_READ_TYPE ); + mgmt_frame->desc_word[0 ] =cpu_to_le16 (RSI_WIFI_MGMT_Q <<12 ); +/* Number of bytes to read */ + mgmt_frame->desc_word[3 ] =cpu_to_le16 (ETH_ALEN + +WLAN_MAC_MAGIC_WORD_LEN + +WLAN_HOST_MODE_LEN ); +/* Address to read */ + mgmt_frame->desc_word[4 ] =cpu_to_le16 (WLAN_MAC_EEPROM_ADDR ); + +skb_put (skb,FRAME_DESC_SZ ); + +return rsi_send_internal_mgmt_frame (common, skb); +} + +/** +* This function handles the confirm frames. +* +* @param common Pointer to the driver private structure. +* @param msg Pointer to received packet. +* @return 0 on success, -1 on failure. +*/ +static int rsi_handle_ta_confirm_type (struct rsi_common *common, +unsigned char *msg) +{ +unsigned char sub_type = (msg[15 ] &0xff ); + +switch (sub_type) { +case BOOTUP_PARAMS_REQUEST : +rsi_dbg (FSM_ZONE ,"%s: Boot up params confirm received\n" , + __func__); +if (common->fsm_state ==FSM_BOOT_PARAMS_SENT ) { +if (rsi_eeprom_read (common)) { + common->fsm_state =FSM_CARD_NOT_READY ; + goto out; + }else { + common->fsm_state =FSM_EEPROM_READ_MAC_ADDR ; + } + }else { +rsi_dbg (ERR_ZONE , +"%s: Received bootup params cfm in %d state\n" , + __func__, common->fsm_state); +return 0 ; + } +break ; + +case EEPROM_READ_TYPE : +if (common->fsm_state ==FSM_EEPROM_READ_MAC_ADDR ) { +if (msg[16 ] ==MAGIC_WORD ) { +memcpy (common->mac_addr, + &msg[FRAME_DESC_SZ + +WLAN_HOST_MODE_LEN + +WLAN_MAC_MAGIC_WORD_LEN ], +ETH_ALEN ); + }else { + common->fsm_state =FSM_CARD_NOT_READY ; +break ; + } +if (rsi_send_reset_mac (common)) + goto out; +else + common->fsm_state =FSM_RESET_MAC_SENT ; + }else { +rsi_dbg (ERR_ZONE , +"%s: Received eeprom mac addr in %d state\n" , + __func__, common->fsm_state); +return 0 ; + } +break ; + +case RESET_MAC_REQ : +if (common->fsm_state ==FSM_RESET_MAC_SENT ) { +rsi_dbg (FSM_ZONE ,"%s: Reset MAC cfm received\n" , + __func__); + +if (rsi_load_radio_caps (common)) + goto out; +else + common->fsm_state =FSM_RADIO_CAPS_SENT ; + }else { +rsi_dbg (ERR_ZONE , +"%s: Received reset mac cfm in %d state\n" , + __func__, common->fsm_state); +return 0 ; + } +break ; + +case RADIO_CAPABILITIES : +if (common->fsm_state ==FSM_RADIO_CAPS_SENT ) { + common->rf_reset =1 ; +if (rsi_program_bb_rf (common)) { + goto out; + }else { + common->fsm_state =FSM_BB_RF_PROG_SENT ; +rsi_dbg (FSM_ZONE ,"%s: Radio cap cfm received\n" , + __func__); + } + }else { +rsi_dbg (ERR_ZONE , +"%s: Received radio caps cfm in %d state\n" , + __func__, common->fsm_state); +return 0 ; + } +break ; + +case BB_PROG_VALUES_REQUEST : +case RF_PROG_VALUES_REQUEST : +case BBP_PROG_IN_TA : +rsi_dbg (FSM_ZONE ,"%s: BB/RF cfm received\n" , __func__); +if (common->fsm_state ==FSM_BB_RF_PROG_SENT ) { + common->bb_rf_prog_count--; +if (!common->bb_rf_prog_count) { + common->fsm_state =FSM_MAC_INIT_DONE ; +return rsi_mac80211_attach (common); + } + }else { + goto out; + } +break ; + +default : +rsi_dbg (INFO_ZONE ,"%s: Invalid TA confirm pkt received\n" , + __func__); +break ; + } +return 0 ; +out: +rsi_dbg (ERR_ZONE ,"%s: Unable to send pkt/Invalid frame received\n" , + __func__); +return -1 ; +} + +/** +* This function process the management packets recieved from the hardware. +* +* @param common Pointer to the driver private structure. +* @param msg Pointer to the received packet. +* @return 0 on success, -1 on failure. +*/ +int rsi_mgmt_pkt_recv (struct rsi_common *common,unsigned char *msg) +{ +int msg_len = (*(unsigned short *)&msg[0 ] &0x0fff ); +unsigned short msg_type = (msg[2 ]); + +rsi_dbg (FSM_ZONE ,"%s: Msg Len: %d, Msg Type: %4x\n" , + __func__, msg_len, msg_type); + +if (msg_type ==TA_CONFIRM_TYPE ) { +return rsi_handle_ta_confirm_type (common, msg); + }else if (msg_type ==CARD_READY_IND ) { +rsi_dbg (FSM_ZONE ,"%s: Card ready indication received\n" , + __func__); +if (common->fsm_state ==FSM_CARD_NOT_READY ) { +if (rsi_load_bootup_params (common)) +return -1 ; +else + common->fsm_state =FSM_BOOT_PARAMS_SENT ; + }else { +return -1 ; + } + }else if (msg_type ==TX_STATUS_IND ) { +if (msg[15 ] ==PROBEREQ_CONFIRM ) + common->mgmt_q_block = false; +rsi_dbg (FSM_ZONE ,"%s: Probe confirm received\n" , + __func__); + }else { +return rsi_mgmt_pkt_to_core (common, msg, msg_len, msg_type); + } +return 0 ; +}