Exemple #1
0
bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	bool is92c = IS_92C_SERIAL(rtlhal->version);
	bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw);

	if (is92c)
		rtl_write_byte(rtlpriv, 0x14, 0x71);
	return rtstatus;
}
Exemple #2
0
void rtl_ips_nic_off_wq_callback(void *data)
{
	struct rtl_works *rtlworks =
	    container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq);
	struct ieee80211_hw *hw = rtlworks->hw;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	enum rf_pwrstate rtstate;

	if (mac->opmode != NL80211_IFTYPE_STATION) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
			 ("not station return\n"));
		return;
	}

	if (mac->link_state > MAC80211_NOLINK)
		return;

	if (is_hal_stop(rtlhal))
		return;

	if (rtlpriv->sec.being_setkey)
		return;

	if (ppsc->inactiveps) {
		rtstate = ppsc->rfpwr_state;

		/*
		 *Do not enter IPS in the following conditions:
		 *(1) RF is already OFF or Sleep
		 *(2) swrf_processing (indicates the IPS is still under going)
		 *(3) Connectted (only disconnected can trigger IPS)
		 *(4) IBSS (send Beacon)
		 *(5) AP mode (send Beacon)
		 *(6) monitor mode (rcv packet)
		 */

		if (rtstate == ERFON &&
		    !ppsc->swrf_processing &&
		    (mac->link_state == MAC80211_NOLINK) &&
		    !mac->act_scanning) {
			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
				 ("IPSEnter(): Turn off RF.\n"));

			ppsc->inactive_pwrstate = ERFOFF;
			ppsc->in_powersavemode = true;

			/*rtl_pci_reset_trx_ring(hw); */
			_rtl_ps_inactive_ps(hw);
		}
	}
}
Exemple #3
0
static void rtl_usb_stop(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	/* should after adapter start and interrupt enable. */
	set_hal_stop(rtlhal);
	/* Enable software */
	SET_USB_STOP(rtlusb);
	rtlpriv->cfg->ops->hw_disable(hw);
}
Exemple #4
0
static void rtl_usb_stop(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	
	set_hal_stop(rtlhal);
	
	SET_USB_STOP(rtlusb);
	rtl_usb_deinit(hw);
	rtlpriv->cfg->ops->hw_disable(hw);
}
Exemple #5
0
int netdev_close(struct net_device *ndev)
{
	struct rtl_priv *rtlpriv = rtl_priv(ndev);
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);	

	if (rtlpriv->pwrctrlpriv.bInternalAutoSuspend == _TRUE) {
		/*rtw_pwr_wakeup(rtlpriv); */
		if (rtlpriv->pwrctrlpriv.rf_pwrstate == rf_off)
			rtlpriv->pwrctrlpriv.ps_flag = _TRUE;
	}
	rtlpriv->net_closed = _TRUE;

/*	if (!rtlpriv->hw_init_completed)
	{
		DBG_871X("(1)871x_drv - drv_close, bup=%d, hw_init_completed=%d\n", rtlpriv->bup, rtlpriv->hw_init_completed);

		rtlpriv->bDriverStopped = _TRUE;

		rtw_dev_unload(rtlpriv);
	}
	else*/
	if (rtlpriv->pwrctrlpriv.rf_pwrstate == rf_on) {
		DBG_871X("(2)871x_drv - drv_close, bup=%d, hw_init_completed=%d\n", rtlpriv->bup, rtlpriv->hw_init_completed);

		/* s1. */
		if (ndev) {
			if (!rtw_netif_queue_stopped(ndev))
				rtw_netif_stop_queue(ndev);
		}

		/* s2. */
		LeaveAllPowerSaveMode(rtlpriv);
		rtw_disassoc_cmd(rtlpriv, 500, _FALSE);
		/* s2-2.  indicate disconnect to os */
		rtw_indicate_disconnect(rtlpriv);
		/* s2-3. */
		rtw_free_assoc_resources(rtlpriv, 1);
		/* s2-4. */
		rtw_free_network_queue(rtlpriv, _TRUE);
		/* Close LED */
		rtw_hal_led_control(rtlpriv, LED_CTL_POWER_OFF);
	}

	kfree(rtlhal->pfirmware);
	rtlhal->pfirmware = NULL;

	DBG_871X("-871x_drv - drv_close, bup=%d\n", rtlpriv->bup);

	return 0;

}
Exemple #6
0
static bool _rtl92s_firmware_set_h2c_cmd( struct ieee80211_hw *hw, u8 h2c_cmd,
		u8 *pcmd_buffer )
{
	struct rtl_priv *rtlpriv = rtl_priv( hw );
	struct rtl_hal *rtlhal = rtl_hal( rtl_priv( hw ) );
	struct rtl_tcb_desc *cb_desc;
	struct sk_buff *skb;
	u32	element_id = 0;
	u32	cmd_len = 0;
	u32	len;

	switch ( h2c_cmd ) {
	case FW_H2C_SETPWRMODE:
		element_id = H2C_SETPWRMODE_CMD ;
		cmd_len = sizeof( struct h2c_set_pwrmode_parm );
		break;
	case FW_H2C_JOINBSSRPT:
		element_id = H2C_JOINBSSRPT_CMD;
		cmd_len = sizeof( struct h2c_joinbss_rpt_parm );
		break;
	case FW_H2C_WOWLAN_UPDATE_GTK:
		element_id = H2C_WOWLAN_UPDATE_GTK_CMD;
		cmd_len = sizeof( struct h2c_wpa_two_way_parm );
		break;
	case FW_H2C_WOWLAN_UPDATE_IV:
		element_id = H2C_WOWLAN_UPDATE_IV_CMD;
		cmd_len = sizeof( unsigned long long );
		break;
	case FW_H2C_WOWLAN_OFFLOAD:
		element_id = H2C_WOWLAN_FW_OFFLOAD;
		cmd_len = sizeof( u8 );
		break;
	default:
		break;
	}

	len = _rtl92s_get_h2c_cmdlen( MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len );
	skb = dev_alloc_skb( len );
	cb_desc = ( struct rtl_tcb_desc* )( skb->cb );
	cb_desc->queue_index = TXCMD_QUEUE;
	cb_desc->b_cmd_or_init = DESC_PACKET_TYPE_NORMAL;
	cb_desc->b_last_inipkt = false;

	_rtl92s_fill_h2c_cmd( skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id,
			&cmd_len, &pcmd_buffer,	&rtlhal->h2c_txcmd_seq );
	_rtl92s_cmd_send_packet( hw, skb, false );
	rtlpriv->cfg->ops->tx_polling( hw, TXCMD_QUEUE );

	return true;
}
Exemple #7
0
Fichier : mac.c Projet : 7799/linux
void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
				   enum version_8192c version)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);

	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
	if (IS_NORMAL_CHIP(rtlhal->version))
		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
	else
		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
}
Exemple #8
0
int rtl8723_download_fw(struct ieee80211_hw *hw,
			bool is_8723be, int max_count)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtlwifi_firmware_header *pfwheader;
	u8 *pfwdata;
	u32 fwsize;
	int err;
	enum version_8723e version = rtlhal->version;
	int max_page;

	if (!rtlhal->pfirmware)
		return 1;

	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
	pfwdata = rtlhal->pfirmware;
	fwsize = rtlhal->fwsize;

	if (!is_8723be)
		max_page = 6;
	else
		max_page = 8;
	if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) {
		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
			 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
			 pfwheader->version, pfwheader->signature,
			 (int)sizeof(struct rtlwifi_firmware_header));

		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
	}

	if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
		if (is_8723be)
			rtl8723be_firmware_selfreset(hw);
		else
			rtl8723ae_firmware_selfreset(hw);
		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
	}
	rtl8723_enable_fw_download(hw, true);
	rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page);
	rtl8723_enable_fw_download(hw, false);

	err = rtl8723_fw_free_to_go(hw, is_8723be, max_count);
	if (err)
		pr_err("Firmware is not ready to run!\n");
	return 0;
}
Exemple #9
0
static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
		struct pci_dev *pdev)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));

	rtlpci->up_first_time = true;
	rtlpci->being_init_adapter = false;

	rtlhal->hw = hw;
	rtlpci->pdev = pdev;

	ppsc->inactiveps = false;
	ppsc->leisure_ps = true;
	ppsc->fwctrl_lps = true;
	ppsc->reg_fwctrl_lps = 3;
	ppsc->reg_max_lps_awakeintvl = 5;

	if (ppsc->reg_fwctrl_lps == 1)
		ppsc->fwctrl_psmode = FW_PS_MIN_MODE;
	else if (ppsc->reg_fwctrl_lps == 2)
		ppsc->fwctrl_psmode = FW_PS_MAX_MODE;
	else if (ppsc->reg_fwctrl_lps == 3)
		ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;

	/*Tx/Rx related var */
	_rtl_pci_init_trx_var(hw);

	 /*IBSS*/ mac->beacon_interval = 100;

	 /*AMPDU*/ mac->min_space_cfg = 0;
	mac->max_mss_density = 0;
	/*set sane AMPDU defaults */
	mac->current_ampdu_density = 7;
	mac->current_ampdu_factor = 3;

	 /*QOS*/ rtlpci->acm_method = eAcmWay2_SW;

	/*task */
	tasklet_init(&rtlpriv->works.irq_tasklet,
		     (void (*)(unsigned long))_rtl_pci_irq_tasklet,
		     (unsigned long)hw);
	tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
		     (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
		     (unsigned long)hw);
}
Exemple #10
0
static void PHY_GetTxPowerIndexByRateArray_8812A(struct rtl_priv *rtlpriv,
        uint8_t RFPath, enum CHANNEL_WIDTH BandWidth,
        uint8_t Channel, uint8_t *Rate, uint8_t *power_index,
        uint8_t	ArraySize)
{
    struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
    struct _rtw_hal *pHalData = GET_HAL_DATA(rtlpriv);
    uint8_t i;
    for (i = 0; i < ArraySize; i++) {
        power_index[i] = _rtl8821au_get_txpower_index(rtlpriv, RFPath, Rate[i], BandWidth, Channel);
        if ((power_index[i] % 2 == 1) &&  !IS_NORMAL_CHIP(rtlhal->version))
            power_index[i] -= 1;
    }

}
Exemple #11
0
void rtl8821au_fill_h2c_cmd(struct rtl_priv *rtlpriv, 
					u8 element_id, u32 cmd_len, 
					u8 *cmdbuffer)
{
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	u32 tmp_cmdbuf[2];

	if (rtlhal->fw_ready == false) {
		RT_ASSERT(false,
			  "return H2C cmd because of Fw download fail!!!\n");
		return;
	}

	memset(tmp_cmdbuf, 0, 8);
	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
	_rtl8821au_fill_h2c_cmd(rtlpriv, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
}
bool _rtl92cu_phy_config_bb_with_headerfile( struct ieee80211_hw *hw,
					    u8 configtype )
{
	int i;
	u32 *phy_regarray_table;
	u32 *agctab_array_table;
	u16 phy_reg_arraylen, agctab_arraylen;
	struct rtl_priv *rtlpriv = rtl_priv( hw );
	struct rtl_hal *rtlhal = rtl_hal( rtl_priv( hw ) );
	struct rtl_phy *rtlphy = &( rtlpriv->phy );

	if ( IS_92C_SERIAL( rtlhal->version ) ) {
		agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length;
		agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_2T].pdata;
		phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length;
		phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata;
	} else {
		agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length;
		agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_1T].pdata;
		phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length;
		phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata;
	}
	if ( configtype == BASEBAND_CONFIG_PHY_REG ) {
		for ( i = 0; i < phy_reg_arraylen; i = i + 2 ) {
			rtl_addr_delay( phy_regarray_table[i] );
			rtl_set_bbreg( hw, phy_regarray_table[i], MASKDWORD,
				      phy_regarray_table[i + 1] );
			udelay( 1 );
			RT_TRACE( rtlpriv, COMP_INIT, DBG_TRACE,
				 "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
				 phy_regarray_table[i],
				 phy_regarray_table[i + 1] );
		}
	} else if ( configtype == BASEBAND_CONFIG_AGC_TAB ) {
		for ( i = 0; i < agctab_arraylen; i = i + 2 ) {
			rtl_set_bbreg( hw, agctab_array_table[i], MASKDWORD,
				      agctab_array_table[i + 1] );
			udelay( 1 );
			RT_TRACE( rtlpriv, COMP_INIT, DBG_TRACE,
				 "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
				 agctab_array_table[i],
				 agctab_array_table[i + 1] );
		}
	}
	return true;
}
/*mutex for start & stop is must here. */
static int rtl_op_start(struct ieee80211_hw *hw)
{
	int err;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));

	if (!is_hal_stop(rtlhal))
		return 0;
	if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
		return 0;
	mutex_lock(&rtlpriv->locks.conf_mutex);
	err = rtlpriv->intf_ops->adapter_start(hw);
	if (!err)
		rtl_watch_dog_timer_callback((unsigned long)hw);
	mutex_unlock(&rtlpriv->locks.conf_mutex);
	return err;
}
void rtl_ips_nic_off_wq_callback(void *data)
{
	struct rtl_works *rtlworks =
	    container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq);
	struct ieee80211_hw *hw = rtlworks->hw;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	enum rf_pwrstate rtstate;

	if (mac->opmode != NL80211_IFTYPE_STATION) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
			 "not station return\n");
		return;
	}

	if (mac->link_state > MAC80211_NOLINK)
		return;

	if (is_hal_stop(rtlhal))
		return;

	if (rtlpriv->sec.being_setkey)
		return;

	if (ppsc->inactiveps) {
		rtstate = ppsc->rfpwr_state;


		if (rtstate == ERFON &&
		    !ppsc->swrf_processing &&
		    (mac->link_state == MAC80211_NOLINK) &&
		    !mac->act_scanning) {
			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
				 "IPSEnter(): Turn off RF\n");

			ppsc->inactive_pwrstate = ERFOFF;
			ppsc->in_powersavemode = true;

			
			_rtl_ps_inactive_ps(hw);
		}
	}
}
Exemple #15
0
void ODM_ConfigRFWithHeaderFile(struct rtl_priv *rtlpriv,
	ODM_RF_Config_Type ConfigType, enum radio_path eRFPath)
{
	struct rtl_hal	*rtlhal = rtl_hal(rtlpriv);

	RT_TRACE(rtlpriv, ODM_COMP_INIT, ODM_DBG_LOUD,
		"===>ODM_ConfigRFWithHeaderFile (%s)\n", (IS_NORMAL_CHIP(rtlhal->version)) ? "MPChip" : "TestChip");
	RT_TRACE(rtlpriv, ODM_COMP_INIT, ODM_DBG_LOUD,
		"pDM_Odm->SupportInterface: 0x%X, pDM_Odm->BoardType: 0x%X\n",
		rtlhal->interface, rtlhal->board_type);

	if (IS_HARDWARE_TYPE_8812AU(rtlhal))
		rtl8812au_phy_config_rf_with_headerfile(rtlpriv, eRFPath);

	if (IS_HARDWARE_TYPE_8821U(rtlhal)) {
		rtl8821au_phy_config_rf_with_headerfile(rtlpriv, RF90_PATH_A);
	}
}
Exemple #16
0
Fichier : mac.c Projet : 7799/linux
void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
		rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] &
				0xFFFFFFFF);
		rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
				0xFFFFFFFF);
	} else {
		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
				0xFFFFFFFF);
		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
				0xFFFFFFFF);
	}
}
Exemple #17
0
static int rtl_op_sta_add(struct ieee80211_hw *hw,
			 struct ieee80211_vif *vif,
			 struct ieee80211_sta *sta)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal= rtl_hal(rtl_priv(hw));
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_sta_info *sta_entry;

	if (sta) {
		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
		list_add_tail(&sta_entry->list, &rtlpriv->entry_list);
		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
			sta_entry->wireless_mode = WIRELESS_MODE_G;
			if (sta->supp_rates[0] <= 0xf)
				sta_entry->wireless_mode = WIRELESS_MODE_B;
			if (sta->ht_cap.ht_supported == true)
				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;

			if (vif->type == NL80211_IFTYPE_ADHOC)
				sta_entry->wireless_mode = WIRELESS_MODE_G;
		} else if (rtlhal->current_bandtype == BAND_ON_5G) {
			sta_entry->wireless_mode = WIRELESS_MODE_A;
			if (sta->ht_cap.ht_supported == true)
				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;

			if (vif->type == NL80211_IFTYPE_ADHOC)
				sta_entry->wireless_mode = WIRELESS_MODE_A;
		}
		/*disable cck rate for p2p*/
		if (mac->p2p)
			sta->supp_rates[0] &= 0xfffffff0;

		memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN);
		RT_TRACE(COMP_MAC80211, DBG_DMESG,
			("Add sta addr is %pM\n",sta->addr));
		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
	}

	return 0;
}
static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
		      struct rtl_tcb_desc *dummy)
{
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	__le16 fc = hdr->frame_control;
	u16 hw_queue;

	if (unlikely(is_hal_stop(rtlhal)))
		goto err_free;
	hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb));
	_rtl_usb_tx_preprocess(hw, skb, hw_queue);
	_rtl_usb_transmit(hw, skb, hw_queue);
	return NETDEV_TX_OK;

err_free:
	dev_kfree_skb_any(skb);
	return NETDEV_TX_OK;
}
Exemple #19
0
static void rtl_pci_stop(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	unsigned long flags;
	u8 RFInProgressTimeOut = 0;

	/*
	 *should before disable interrrupt&adapter
	 *and will do it immediately.
	 */
	set_hal_stop(rtlhal);

	rtlpriv->cfg->ops->disable_interrupt(hw);

	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
	while (ppsc->rfchange_inprogress) {
		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
		if (RFInProgressTimeOut > 100) {
			spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
			break;
		}
		mdelay(1);
		RFInProgressTimeOut++;
		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
	}
	ppsc->rfchange_inprogress = true;
	spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);

	rtlpci->driver_is_goingto_unload = true;
	rtlpriv->cfg->ops->hw_disable(hw);
	rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);

	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
	ppsc->rfchange_inprogress = false;
	spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);

	rtl_pci_enable_aspm(hw);
}
Exemple #20
0
int rtl_send_smps_action(struct ieee80211_hw *hw,
		struct ieee80211_sta *sta, u8 *da, u8 *bssid,
		enum ieee80211_smps_mode smps)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid);
	struct rtl_tcb_desc tcb_desc;
	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));

	if (rtlpriv->mac80211.act_scanning)
		goto err_free;

	if (!sta)
		goto err_free;

	if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
		goto err_free;

	if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
		goto err_free;

	/* this is a type = mgmt * stype = action frame */
	if (skb) {
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
		struct rtl_sta_info *sta_entry =
			(struct rtl_sta_info *) sta->drv_priv;
		sta_entry->mimo_ps = smps;
		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);

		info->control.rates[0].idx = 0;
		info->control.sta = sta;
		info->band = hw->conf.channel->band;
		rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc);
	}
err_free:
	return 0;
}
static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct rtl_tcb_desc tcb_desc;
	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));

	if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
		goto err_free;

	if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
		goto err_free;

	if (!rtlpriv->intf_ops->waitq_insert(hw, skb))
		rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc);

	return;

err_free:
	dev_kfree_skb_any(skb);
}
Exemple #22
0
static int _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u32 h2c_cmd,
					 u32 cmd_len, u8 *pcmd_buffer)
{
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_tcb_desc *cb_desc;
	struct sk_buff *skb;
	u32 len;

	len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
	skb = dev_alloc_skb(len);
	if (!skb)
		return -ENOMEM;

	cb_desc = (struct rtl_tcb_desc *)(skb->cb);
	cb_desc->queue_index = TXCMD_QUEUE;
	cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
	cb_desc->last_inipkt = false;

	_rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &h2c_cmd,
			&cmd_len, &pcmd_buffer,	&rtlhal->h2c_txcmd_seq);
	return _rtl92s_cmd_send_packet(hw, skb, false);
}
Exemple #23
0
static int rtl_usb_start(struct ieee80211_hw *hw)
{
	int err;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	err = rtlpriv->cfg->ops->hw_init(hw);
	if (!err) {
		atomic_set(&rtlusb->tx_pending_urbs, 0);
		rtl_init_rx_config(hw);

		/* Enable software */
		SET_USB_START(rtlusb);
		/* should after adapter start and interrupt enable. */
		set_hal_start(rtlhal);

		/* Start bulk IN */
		err = _rtl_usb_receive(hw);
	}

	return err;
}
Exemple #24
0
static void rtl_usb_init_sw(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtlpriv);
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(rtlpriv));

	rtlhal->hw = hw;
	ppsc->inactiveps = false;
	ppsc->leisure_ps = false;
	ppsc->fwctrl_lps = false;
	ppsc->reg_fwctrl_lps = 3;
	ppsc->reg_max_lps_awakeintvl = 5;
	ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;

	 /* IBSS */
	mac->beacon_interval = 100;

	 /* AMPDU */
	mac->min_space_cfg = 0;
	mac->max_mss_density = 0;

	/* set sane AMPDU defaults */
	mac->current_ampdu_density = 7;
	mac->current_ampdu_factor = 3;

	/* QOS */
	rtlusb->acm_method = EACMWAY2_SW;

	/* IRQ */
	/* HIMR - turn all on */
	rtlusb->irq_mask[0] = 0xFFFFFFFF;
	/* HIMR_EX - turn all on */
	rtlusb->irq_mask[1] = 0xFFFFFFFF;
	rtlusb->disableHWSM =  true;
}
Exemple #25
0
/*<delete in kernel end>*/
static void rtl_op_tx(struct ieee80211_hw *hw,
		      struct ieee80211_tx_control *control,
		      struct sk_buff *skb)
/*<delete in kernel start>*/
#endif
/*<delete in kernel end>*/
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct rtl_tcb_desc tcb_desc;
	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));

	if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
		goto err_free;

	if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
		goto err_free;

/*<delete in kernel start>*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
	if (!rtlpriv->intf_ops->waitq_insert(hw, skb))
		rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc);
#else
/*<delete in kernel end>*/
	if (!rtlpriv->intf_ops->waitq_insert(hw, control->sta, skb))
	        rtlpriv->intf_ops->adapter_tx(hw, control->sta, skb, &tcb_desc);
/*<delete in kernel start>*/
#endif
/*<delete in kernel end>*/
	return;

err_free:
	dev_kfree_skb_any(skb);
	return;
}
Exemple #26
0
static void rtl_usb_init_sw(struct ieee80211_hw *hw)
{
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));

	rtlhal->hw = hw;
	ppsc->inactiveps = false;
	ppsc->leisure_ps = false;
	ppsc->fwctrl_lps = false;
	ppsc->reg_fwctrl_lps = 3;
	ppsc->reg_max_lps_awakeintvl = 5;
	ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;

	 
	mac->beacon_interval = 100;

	 
	mac->min_space_cfg = 0;
	mac->max_mss_density = 0;

	
	mac->current_ampdu_density = 7;
	mac->current_ampdu_factor = 3;

	
	rtlusb->acm_method = eAcmWay2_SW;

	
	
	rtlusb->irq_mask[0] = 0xFFFFFFFF;
	
	rtlusb->irq_mask[1] = 0xFFFFFFFF;
	rtlusb->disableHWSM =  true;
}
Exemple #27
0
static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
		struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct pci_dev *bridge_pdev = pdev->bus->self;
	u16 venderid;
	u16 deviceid;
	u16 irqline;
	u8 tmp;

	venderid = pdev->vendor;
	deviceid = pdev->device;
	pci_read_config_word(pdev, 0x3C, &irqline);

	if (deviceid == RTL_PCI_8192_DID ||
	    deviceid == RTL_PCI_0044_DID ||
	    deviceid == RTL_PCI_0047_DID ||
	    deviceid == RTL_PCI_8192SE_DID ||
	    deviceid == RTL_PCI_8174_DID ||
	    deviceid == RTL_PCI_8173_DID ||
	    deviceid == RTL_PCI_8172_DID ||
	    deviceid == RTL_PCI_8171_DID) {
		switch (pdev->revision) {
		case RTL_PCI_REVISION_ID_8192PCIE:
			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
				 ("8192 PCI-E is found - "
				  "vid/did=%x/%x\n", venderid, deviceid));
			rtlhal->hw_type = HARDWARE_TYPE_RTL8192E;
			break;
		case RTL_PCI_REVISION_ID_8192SE:
			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
				 ("8192SE is found - "
				  "vid/did=%x/%x\n", venderid, deviceid));
			rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE;
			break;
		default:
			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
				 ("Err: Unknown device - "
				  "vid/did=%x/%x\n", venderid, deviceid));
			rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE;
			break;

		}
	} else if (deviceid == RTL_PCI_8192CET_DID ||
		   deviceid == RTL_PCI_8192CE_DID ||
		   deviceid == RTL_PCI_8191CE_DID ||
		   deviceid == RTL_PCI_8188CE_DID) {
		rtlhal->hw_type = HARDWARE_TYPE_RTL8192CE;
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
			 ("8192C PCI-E is found - "
			  "vid/did=%x/%x\n", venderid, deviceid));
	} else {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
			 ("Err: Unknown device -"
			  " vid/did=%x/%x\n", venderid, deviceid));

		rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE;
	}

	/*find bus info */
	pcipriv->ndis_adapter.busnumber = pdev->bus->number;
	pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn);
	pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn);

	/*find bridge info */
	pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
	for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
		if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
			pcipriv->ndis_adapter.pcibridge_vendor = tmp;
			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
				 ("Pci Bridge Vendor is found index: %d\n",
				  tmp));
			break;
		}
	}

	if (pcipriv->ndis_adapter.pcibridge_vendor !=
		PCI_BRIDGE_VENDOR_UNKNOWN) {
		pcipriv->ndis_adapter.pcibridge_busnum =
		    bridge_pdev->bus->number;
		pcipriv->ndis_adapter.pcibridge_devnum =
		    PCI_SLOT(bridge_pdev->devfn);
		pcipriv->ndis_adapter.pcibridge_funcnum =
		    PCI_FUNC(bridge_pdev->devfn);
		pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
		    pci_pcie_cap(bridge_pdev);
		pcipriv->ndis_adapter.pcicfg_addrport =
		    (pcipriv->ndis_adapter.pcibridge_busnum << 16) |
		    (pcipriv->ndis_adapter.pcibridge_devnum << 11) |
		    (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31);
		pcipriv->ndis_adapter.num4bytes =
		    (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4;

		rtl_pci_get_linkcontrol_field(hw);

		if (pcipriv->ndis_adapter.pcibridge_vendor ==
		    PCI_BRIDGE_VENDOR_AMD) {
			pcipriv->ndis_adapter.amd_l1_patch =
			    rtl_pci_get_amd_l1_patch(hw);
		}
	}

	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
		 ("pcidev busnumber:devnumber:funcnumber:"
		  "vendor:link_ctl %d:%d:%d:%x:%x\n",
		  pcipriv->ndis_adapter.busnumber,
		  pcipriv->ndis_adapter.devnumber,
		  pcipriv->ndis_adapter.funcnumber,
		  pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg));

	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
		 ("pci_bridge busnumber:devnumber:funcnumber:vendor:"
		  "pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n",
		  pcipriv->ndis_adapter.pcibridge_busnum,
		  pcipriv->ndis_adapter.pcibridge_devnum,
		  pcipriv->ndis_adapter.pcibridge_funcnum,
		  pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor],
		  pcipriv->ndis_adapter.pcibridge_pciehdr_offset,
		  pcipriv->ndis_adapter.pcibridge_linkctrlreg,
		  pcipriv->ndis_adapter.amd_l1_patch));

	rtl_pci_parse_configuration(pdev, hw);

	return true;
}
Exemple #28
0
void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_phy *rtlphy = &(rtlpriv->phy);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	u8 reg_bw_opmode;
	u8 reg_prsr_rsc;

	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
		 ("Switch to %s bandwidth\n",
		  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
		  "20MHz" : "40MHz"))

	if (is_hal_stop(rtlhal)) {
		rtlphy->set_bwmode_inprogress = false;
		return;
	}

	reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
	reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);

	switch (rtlphy->current_chan_bw) {
	case HT_CHANNEL_WIDTH_20:
		reg_bw_opmode |= BW_OPMODE_20MHZ;
		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
		break;
	case HT_CHANNEL_WIDTH_20_40:
		reg_bw_opmode &= ~BW_OPMODE_20MHZ;
		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
		reg_prsr_rsc =
		    (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
		break;
	default:
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
		break;
	}

	switch (rtlphy->current_chan_bw) {
	case HT_CHANNEL_WIDTH_20:
		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
		break;
	case HT_CHANNEL_WIDTH_20_40:
		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);

		rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
			      (mac->cur_40_prime_sc >> 1));
		rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);

		rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
			      (mac->cur_40_prime_sc ==
			       HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
		break;
	default:
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
		break;
	}
	rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
	rtlphy->set_bwmode_inprogress = false;
	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
}
Exemple #29
0
bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
					  enum radio_path rfpath)
{

	int i;
	bool rtstatus = true;
	u32 *radioa_array_table;
	u32 *radiob_array_table;
	u16 radioa_arraylen, radiob_arraylen;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));

	if (IS_92C_SERIAL(rtlhal->version)) {
		radioa_arraylen = RADIOA_2TARRAYLENGTH;
		radioa_array_table = RTL8192CERADIOA_2TARRAY;
		radiob_arraylen = RADIOB_2TARRAYLENGTH;
		radiob_array_table = RTL8192CE_RADIOB_2TARRAY;
		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
			 ("Radio_A:RTL8192CERADIOA_2TARRAY\n"));
		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
			 ("Radio_B:RTL8192CE_RADIOB_2TARRAY\n"));
	} else {
		radioa_arraylen = RADIOA_1TARRAYLENGTH;
		radioa_array_table = RTL8192CE_RADIOA_1TARRAY;
		radiob_arraylen = RADIOB_1TARRAYLENGTH;
		radiob_array_table = RTL8192CE_RADIOB_1TARRAY;
		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
			 ("Radio_A:RTL8192CE_RADIOA_1TARRAY\n"));
		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
			 ("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
	}
	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
	rtstatus = true;
	switch (rfpath) {
	case RF90_PATH_A:
		for (i = 0; i < radioa_arraylen; i = i + 2) {
			if (radioa_array_table[i] == 0xfe)
				mdelay(50);
			else if (radioa_array_table[i] == 0xfd)
				mdelay(5);
			else if (radioa_array_table[i] == 0xfc)
				mdelay(1);
			else if (radioa_array_table[i] == 0xfb)
				udelay(50);
			else if (radioa_array_table[i] == 0xfa)
				udelay(5);
			else if (radioa_array_table[i] == 0xf9)
				udelay(1);
			else {
				rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
					      RFREG_OFFSET_MASK,
					      radioa_array_table[i + 1]);
				udelay(1);
			}
		}
		break;
	case RF90_PATH_B:
		for (i = 0; i < radiob_arraylen; i = i + 2) {
			if (radiob_array_table[i] == 0xfe) {
				mdelay(50);
			} else if (radiob_array_table[i] == 0xfd)
				mdelay(5);
			else if (radiob_array_table[i] == 0xfc)
				mdelay(1);
			else if (radiob_array_table[i] == 0xfb)
				udelay(50);
			else if (radiob_array_table[i] == 0xfa)
				udelay(5);
			else if (radiob_array_table[i] == 0xf9)
				udelay(1);
			else {
				rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
					      RFREG_OFFSET_MASK,
					      radiob_array_table[i + 1]);
				udelay(1);
			}
		}
		break;
	case RF90_PATH_C:
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
			 ("switch case not process\n"));
		break;
	case RF90_PATH_D:
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
			 ("switch case not process\n"));
		break;
	}
	return true;
}
static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif,
			     struct ieee80211_bss_conf *bss_conf, u32 changed)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct ieee80211_sta *sta = NULL;

	mutex_lock(&rtlpriv->locks.conf_mutex);
	if ((vif->type == NL80211_IFTYPE_ADHOC) ||
	    (vif->type == NL80211_IFTYPE_AP) ||
	    (vif->type == NL80211_IFTYPE_MESH_POINT)) {
		if ((changed & BSS_CHANGED_BEACON) ||
		    (changed & BSS_CHANGED_BEACON_ENABLED &&
		     bss_conf->enable_beacon)) {
			if (mac->beacon_enabled == 0) {
				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
					 ("BSS_CHANGED_BEACON_ENABLED\n"));

				/*start hw beacon interrupt. */
				/*rtlpriv->cfg->ops->set_bcn_reg(hw); */
				mac->beacon_enabled = 1;
				rtlpriv->cfg->ops->update_interrupt_mask(hw,
						rtlpriv->cfg->maps
						[RTL_IBSS_INT_MASKS],
						0);

				if (rtlpriv->cfg->ops->linked_set_reg)
					rtlpriv->cfg->ops->linked_set_reg(hw);
			}
		}
		if ((changed & BSS_CHANGED_BEACON_ENABLED &&
			!bss_conf->enable_beacon)) {
			if (mac->beacon_enabled == 1) {
				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
					 ("ADHOC DISABLE BEACON\n"));

				mac->beacon_enabled = 0;
				rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
						rtlpriv->cfg->maps
						[RTL_IBSS_INT_MASKS]);
			}
		}
		if (changed & BSS_CHANGED_BEACON_INT) {
			RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE,
				 ("BSS_CHANGED_BEACON_INT\n"));
			mac->beacon_interval = bss_conf->beacon_int;
			rtlpriv->cfg->ops->set_bcn_intv(hw);
		}
	}

	/*TODO: reference to enum ieee80211_bss_change */
	if (changed & BSS_CHANGED_ASSOC) {
		if (bss_conf->assoc) {
			/* we should reset all sec info & cam
			 * before set cam after linked, we should not
			 * reset in disassoc, that will cause tkip->wep
			 * fail because some flag will be wrong */
			/* reset sec info */
			rtl_cam_reset_sec_info(hw);
			/* reset cam to fix wep fail issue
			 * when change from wpa to wep */
			rtl_cam_reset_all_entry(hw);

			mac->link_state = MAC80211_LINKED;
			mac->cnt_after_linked = 0;
			mac->assoc_id = bss_conf->aid;
			memcpy(mac->bssid, bss_conf->bssid, 6);

			if (rtlpriv->cfg->ops->linked_set_reg)
				rtlpriv->cfg->ops->linked_set_reg(hw);
			if (mac->opmode == NL80211_IFTYPE_STATION && sta)
				rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
				 ("BSS_CHANGED_ASSOC\n"));
		} else {
			if (mac->link_state == MAC80211_LINKED)
				rtl_lps_leave(hw);

			mac->link_state = MAC80211_NOLINK;
			memset(mac->bssid, 0, 6);
			mac->vendor = PEER_UNKNOWN;

			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
				 ("BSS_CHANGED_UN_ASSOC\n"));
		}
	}

	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
			 ("BSS_CHANGED_ERP_CTS_PROT\n"));
		mac->use_cts_protect = bss_conf->use_cts_prot;
	}

	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
			 ("BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
			  bss_conf->use_short_preamble));

		mac->short_preamble = bss_conf->use_short_preamble;
		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE,
					      (u8 *) (&mac->short_preamble));
	}

	if (changed & BSS_CHANGED_ERP_SLOT) {
		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
			 ("BSS_CHANGED_ERP_SLOT\n"));

		if (bss_conf->use_short_slot)
			mac->slot_time = RTL_SLOT_TIME_9;
		else
			mac->slot_time = RTL_SLOT_TIME_20;

		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
					      (u8 *) (&mac->slot_time));
	}

	if (changed & BSS_CHANGED_HT) {
		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
			 ("BSS_CHANGED_HT\n"));
		rcu_read_lock();
		sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
		if (sta) {
			if (sta->ht_cap.ampdu_density >
			    mac->current_ampdu_density)
				mac->current_ampdu_density =
				    sta->ht_cap.ampdu_density;
			if (sta->ht_cap.ampdu_factor <
			    mac->current_ampdu_factor)
				mac->current_ampdu_factor =
				    sta->ht_cap.ampdu_factor;
		}
		rcu_read_unlock();

		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY,
					      (u8 *) (&mac->max_mss_density));
		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR,
					      &mac->current_ampdu_factor);
		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE,
					      &mac->current_ampdu_density);
	}

	if (changed & BSS_CHANGED_BSSID) {
		u32 basic_rates;

		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID,
					      (u8 *) bss_conf->bssid);

		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
			 (MAC_FMT "\n", MAC_ARG(bss_conf->bssid)));

		mac->vendor = PEER_UNKNOWN;
		memcpy(mac->bssid, bss_conf->bssid, 6);
		rtlpriv->cfg->ops->set_network_type(hw, vif->type);

		rcu_read_lock();
		sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
		if (!sta) {
			rcu_read_unlock();
			goto out;
		}

		if (rtlhal->current_bandtype == BAND_ON_5G) {
			mac->mode = WIRELESS_MODE_A;
		} else {
			if (sta->supp_rates[0] <= 0xf)
				mac->mode = WIRELESS_MODE_B;
			else
				mac->mode = WIRELESS_MODE_G;
		}

		if (sta->ht_cap.ht_supported) {
			if (rtlhal->current_bandtype == BAND_ON_2_4G)
				mac->mode = WIRELESS_MODE_N_24G;
			else
				mac->mode = WIRELESS_MODE_N_5G;
		}

		/* just station need it, because ibss & ap mode will
		 * set in sta_add, and will be NULL here */
		if (mac->opmode == NL80211_IFTYPE_STATION) {
			struct rtl_sta_info *sta_entry;
			sta_entry = (struct rtl_sta_info *) sta->drv_priv;
			sta_entry->wireless_mode = mac->mode;
		}

		if (sta->ht_cap.ht_supported) {
			mac->ht_enable = true;

			/*
			 * for cisco 1252 bw20 it's wrong
			 * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
			 *	mac->bw_40 = true;
			 * }
			 * */
		}

		if (changed & BSS_CHANGED_BASIC_RATES) {
			/* for 5G must << RATE_6M_INDEX=4,
			 * because 5G have no cck rate*/
			if (rtlhal->current_bandtype == BAND_ON_5G)
				basic_rates = sta->supp_rates[1] << 4;
			else
				basic_rates = sta->supp_rates[0];

			mac->basic_rates = basic_rates;
			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
					(u8 *) (&basic_rates));
		}
		rcu_read_unlock();
	}

	/*
	 * For FW LPS:
	 * To tell firmware we have connected
	 * to an AP. For 92SE/CE power save v2.
	 */
	if (changed & BSS_CHANGED_ASSOC) {
		if (bss_conf->assoc) {
			if (ppsc->fwctrl_lps) {
				u8 mstatus = RT_MEDIA_CONNECT;
				rtlpriv->cfg->ops->set_hw_reg(hw,
						      HW_VAR_H2C_FW_JOINBSSRPT,
						      (u8 *) (&mstatus));
				ppsc->report_linked = true;
			}
		} else {
			if (ppsc->fwctrl_lps) {
				u8 mstatus = RT_MEDIA_DISCONNECT;
				rtlpriv->cfg->ops->set_hw_reg(hw,
						      HW_VAR_H2C_FW_JOINBSSRPT,
						      (u8 *)(&mstatus));
				ppsc->report_linked = false;
			}
		}
	}

out:
	mutex_unlock(&rtlpriv->locks.conf_mutex);
}