10c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger/****************************************************************************** 20c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 30c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * Copyright(c) 2009-2010 Realtek Corporation. 40c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 50c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * This program is free software; you can redistribute it and/or modify it 60c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * under the terms of version 2 of the GNU General Public License as 70c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * published by the Free Software Foundation. 80c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 90c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT 100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * more details. 130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * You should have received a copy of the GNU General Public License along with 150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * this program; if not, write to the Free Software Foundation, Inc., 160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * The full GNU General Public License is included in this distribution in the 190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * file called LICENSE. 200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * Contact Information: 220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * wlanfae <wlanfae@realtek.com> 230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, 240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * Hsinchu 300, Taiwan. 250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * Larry Finger <Larry.Finger@lwfinger.net> 270baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * 280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *****************************************************************************/ 290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger#include "wifi.h" 310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger#include "core.h" 320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger#include "cam.h" 330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger#include "base.h" 340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger#include "ps.h" 350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger/*mutex for start & stop is must here. */ 370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_start(struct ieee80211_hw *hw) 380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 39324732848c42bf79988479ee1b4359e15f08154bLarry Finger int err; 400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!is_hal_stop(rtlhal)) 440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 478a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger err = rtlpriv->intf_ops->adapter_start(hw); 49324732848c42bf79988479ee1b4359e15f08154bLarry Finger if (!err) 50324732848c42bf79988479ee1b4359e15f08154bLarry Finger rtl_watch_dog_timer_callback((unsigned long)hw); 518a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return err; 530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_stop(struct ieee80211_hw *hw) 560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (is_hal_stop(rtlhal)) 630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return; 640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(ppsc->rfpwr_state == ERFOFF)) { 660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mdelay(1); 680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 708a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_NOLINK; 730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(mac->bssid, 0, 6); 740baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*reset sec info */ 770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_cam_reset_sec_info(hw); 780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_deinit_deferred_work(hw); 800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->intf_ops->adapter_stop(hw); 810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 828a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 857bb4568372856688bc070917265bce0b88bb7d4dJohannes Bergstatic void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 900baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_tcb_desc tcb_desc; 910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); 920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) 940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto err_free; 950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto err_free; 980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 990baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) 1000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); 1010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1027bb4568372856688bc070917265bce0b88bb7d4dJohannes Berg return; 1030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingererr_free: 1050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger dev_kfree_skb_any(skb); 1060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 1070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_add_interface(struct ieee80211_hw *hw, 1090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif) 1100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 1110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 1120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 1130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int err = 0; 1140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->vif) { 1160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 1170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("vif has been set!! mac->vif = 0x%p\n", mac->vif)); 1180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -EOPNOTSUPP; 1190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 1220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1238a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 1240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (vif->type) { 1250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_IFTYPE_STATION: 1260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 1) { 1270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 1280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("NL80211_IFTYPE_STATION\n")); 1290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 0; 1300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, 1310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 1320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS]); 1330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 1350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_IFTYPE_ADHOC: 1360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 1370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("NL80211_IFTYPE_ADHOC\n")); 1380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED; 1400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_bcn_reg(hw); 1410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) 1420baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xfff; 1430baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 1440baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xff0; 1450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, 1460baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (u8 *) (&mac->basic_rates)); 1470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 1480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 1490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_IFTYPE_AP: 1500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 1510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("NL80211_IFTYPE_AP\n")); 1520baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 1530baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->link_state = MAC80211_LINKED; 1540baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_bcn_reg(hw); 1550baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) 1560baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xfff; 1570baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 1580baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xff0; 1590baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, 1600baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (u8 *) (&mac->basic_rates)); 1610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 1620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 1630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 1640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("operation mode %d is not support!\n", vif->type)); 1650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger err = -EOPNOTSUPP; 1660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out; 1670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->vif = vif; 1700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->opmode = vif->type; 1710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_network_type(hw, vif->type); 1720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac->mac_addr, vif->addr, ETH_ALEN); 1730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); 1740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerout: 1768a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 1770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return err; 1780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 1790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_remove_interface(struct ieee80211_hw *hw, 1810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif) 1820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 1830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 1840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 1850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1868a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 1870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* Free beacon resources */ 1890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if ((mac->opmode == NL80211_IFTYPE_AP) || 1900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (mac->opmode == NL80211_IFTYPE_ADHOC) || 1910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (mac->opmode == NL80211_IFTYPE_MESH_POINT)) { 1920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 1) { 1930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 0; 1940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, 1950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 1960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS]); 1970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 2010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *Note: We assume NL80211_IFTYPE_UNSPECIFIED as 2020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *NO LINK for our hardware. 2030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 2040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->vif = NULL; 2050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_NOLINK; 2060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(mac->bssid, 0, 6); 2070baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 2080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->opmode = NL80211_IFTYPE_UNSPECIFIED; 2090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); 2108a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 2110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 2120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_config(struct ieee80211_hw *hw, u32 changed) 2140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 2150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 2160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_phy *rtlphy = &(rtlpriv->phy); 2170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 2180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 2190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_conf *conf = &hw->conf; 2200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2218a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 2220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ 2230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 2240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n")); 2250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*For IPS */ 2280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_IDLE) { 2290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (hw->conf.flags & IEEE80211_CONF_IDLE) 2300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_off(hw); 2310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger else 2320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 2330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 2340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 2350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *although rfoff may not cause by ips, but we will 2360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *check the reason in set_rf_power_state function 2370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 2380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(ppsc->rfpwr_state == ERFOFF)) 2390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 2400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*For LPS */ 2430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_PS) { 2440baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li cancel_delayed_work(&rtlpriv->works.ps_work); 2450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); 2460baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (conf->flags & IEEE80211_CONF_PS) { 2470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->psc.sw_ps_enabled = true; 2480baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* sleep here is must, or we may recv the beacon and 2490baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * cause mac80211 into wrong ps state, this will cause 2500baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * power save nullfunc send fail, and further cause 2510baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * pkt loss, So sleep must quickly but not immediatly 2520baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * because that will cause nullfunc send by mac80211 2530baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * fail, and cause pkt loss, we have tested that 5mA 2540baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * is worked very well */ 2550baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!rtlpriv->psc.multi_buffered) 2560baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li queue_delayed_work(rtlpriv->works.rtl_wq, 2570baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li &rtlpriv->works.ps_work, 2580baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li MSECS(5)); 2590baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 2600baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_swlps_rf_awake(hw); 2610baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->psc.sw_ps_enabled = false; 2620baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 2630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { 2660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 2670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n", 2680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger hw->conf.long_frame_max_tx_count)); 2690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->retry_long = hw->conf.long_frame_max_tx_count; 2700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->retry_short = hw->conf.long_frame_max_tx_count; 2710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, 2720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&hw->conf. 2730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger long_frame_max_tx_count)); 2740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 2770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_channel *channel = hw->conf.channel; 2780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 wide_chan = (u8) channel->hw_value; 2790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 2810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *because we should back channel to 2820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *current_network.chan in in scanning, 2830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *So if set_chan == current_network.chan 2840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *we should set it. 2850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *because mac80211 tell us wrong bw40 2860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *info for cisco1253 bw20, so we modify 2870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *it here based on UPPER & LOWER 2880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 2890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (hw->conf.channel_type) { 2900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_HT20: 2910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_NO_HT: 2920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* SC */ 2930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cur_40_prime_sc = 2940baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li PRIME_CHNL_OFFSET_DONT_CARE; 2950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; 2960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = false; 2970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 2980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_HT40MINUS: 2990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* SC */ 3000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; 3010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_chan_bw = 3020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li HT_CHANNEL_WIDTH_20_40; 3030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = true; 3040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*wide channel */ 3060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wide_chan -= 2; 3070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_HT40PLUS: 3100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* SC */ 3110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; 3120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_chan_bw = 3130baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li HT_CHANNEL_WIDTH_20_40; 3140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = true; 3150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*wide channel */ 3170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wide_chan += 2; 3180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 3210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = false; 3220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 3230baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li ("switch case not processed\n")); 3240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (wide_chan <= 0) 3280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wide_chan = 1; 3290baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 3300baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* In scanning, before we go offchannel we may send a ps=1 null 3310baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * to AP, and then we may send a ps = 0 null to AP quickly, but 3320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * first null may have caused AP to put lots of packet to hw tx 3330baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * buffer. These packets must be tx'd before we go off channel 3340baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * so we must delay more time to let AP flush these packets 3350baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * before going offchannel, or dis-association or delete BA will 3360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * happen by AP 3370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li */ 3389c0504403725ca77153a0bdad2f3bef0a05e32f0Mike McCormack if (rtlpriv->mac80211.offchan_delay) { 3399c0504403725ca77153a0bdad2f3bef0a05e32f0Mike McCormack rtlpriv->mac80211.offchan_delay = false; 3400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mdelay(50); 3410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 3420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_channel = wide_chan; 3430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->switch_channel(hw); 3450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_channel_access(hw); 3460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_bw_mode(hw, 3470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger hw->conf.channel_type); 3480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3508a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 3510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 3530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 3540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_configure_filter(struct ieee80211_hw *hw, 3560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger unsigned int changed_flags, 3570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger unsigned int *new_flags, u64 multicast) 3580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 3590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 3600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 3610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *new_flags &= RTL_SUPPORTED_FILTERS; 3630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!changed_flags) 3640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return; 3650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*TODO: we disable broadcase now, so enable here */ 3670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_ALLMULTI) { 3680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_ALLMULTI) { 3690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | 3700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps[MAC_RCR_AB]; 3710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 3720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Enable receive multicast frame.\n")); 3730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 3740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] | 3750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps[MAC_RCR_AB]); 3760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 3770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Disable receive multicast frame.\n")); 3780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_FCSFAIL) { 3820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_FCSFAIL) { 3830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32]; 3840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 3850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Enable receive FCS error frame.\n")); 3860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 3870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32]; 3880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 3890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Disable receive FCS error frame.\n")); 3900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3930baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* if ssid not set to hw don't check bssid 3940baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * here just used for linked scanning, & linked 3950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * and nolink check bssid is set in set network_type */ 3960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && 3970baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (mac->link_state >= MAC80211_LINKED)) { 3980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode != NL80211_IFTYPE_AP) { 3990baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { 4000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_chk_bssid(hw, false); 4010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 4020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_chk_bssid(hw, true); 4030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_CONTROL) { 4080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_CONTROL) { 4090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; 4100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 4120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Enable receive control frame.\n")); 4130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 4140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; 4150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 4160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Disable receive control frame.\n")); 4170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_OTHER_BSS) { 4210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_OTHER_BSS) { 4220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP]; 4230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 4240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Enable receive other BSS's frame.\n")); 4250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 4260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP]; 4270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 4280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("Disable receive other BSS's frame.\n")); 4290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 4320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Listatic int rtl_op_sta_add(struct ieee80211_hw *hw, 4330baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_vif *vif, 4340baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_sta *sta) 4350baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li{ 4360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_priv *rtlpriv = rtl_priv(hw); 4370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 4380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_sta_info *sta_entry; 4390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 4400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta) { 4410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry = (struct rtl_sta_info *) sta->drv_priv; 4420baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_2_4G) { 4430baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_G; 4440baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->supp_rates[0] <= 0xf) 4450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_B; 446e10542c447abf7c840931ff12f7d0dee976ca2eaMike McCormack if (sta->ht_cap.ht_supported) 4470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_N_24G; 4480baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else if (rtlhal->current_bandtype == BAND_ON_5G) { 4490baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_A; 450e10542c447abf7c840931ff12f7d0dee976ca2eaMike McCormack if (sta->ht_cap.ht_supported) 4510baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_N_24G; 4520baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4530baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 4540baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* I found some times mac80211 give wrong supp_rates for adhoc*/ 4550baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) 4560baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_G; 4570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4580baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 4591d15b5f2d380186761d49588de27b2a6538afacbAndy Shevchenko ("Add sta addr is %pM\n", sta->addr)); 4600baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); 4610baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4620baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return 0; 4630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li} 4640baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Listatic int rtl_op_sta_remove(struct ieee80211_hw *hw, 4650baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_vif *vif, 4660baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_sta *sta) 4670baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li{ 4680baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_priv *rtlpriv = rtl_priv(hw); 4690baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_sta_info *sta_entry; 4700baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta) { 4710baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 4721d15b5f2d380186761d49588de27b2a6538afacbAndy Shevchenko ("Remove sta addr is %pM\n", sta->addr)); 4730baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry = (struct rtl_sta_info *) sta->drv_priv; 4740baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = 0; 4750baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->ratr_index = 0; 4760baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4770baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return 0; 4780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li} 4790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int _rtl_get_hal_qnum(u16 queue) 4800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 4810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int qnum; 4820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (queue) { 4840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 0: 4850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC3_VO; 4860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 4870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 1: 4880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC2_VI; 4890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 4900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 2: 4910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC0_BE; 4920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 4930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 3: 4940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC1_BK; 4950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 4960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 4970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC0_BE; 4980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 4990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return qnum; 5010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 5020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger/* 5040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *for mac80211 VO=0, VI=1, BE=2, BK=3 5050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *for rtl819x BE=0, BK=1, VI=2, VO=3 5060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 5078a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Pellerstatic int rtl_op_conf_tx(struct ieee80211_hw *hw, 5088a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Peller struct ieee80211_vif *vif, u16 queue, 5090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger const struct ieee80211_tx_queue_params *param) 5100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 5110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 5120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 5130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int aci; 5140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (queue >= AC_MAX) { 5160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 5170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("queue number %d is incorrect!\n", queue)); 5180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -EINVAL; 5190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger aci = _rtl_get_hal_qnum(queue); 5220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->ac[aci].aifs = param->aifs; 52317c9ac62812b58aacefc7336215aecbb522f6547Larry Finger mac->ac[aci].cw_min = cpu_to_le16(param->cw_min); 52417c9ac62812b58aacefc7336215aecbb522f6547Larry Finger mac->ac[aci].cw_max = cpu_to_le16(param->cw_max); 52517c9ac62812b58aacefc7336215aecbb522f6547Larry Finger mac->ac[aci].tx_op = cpu_to_le16(param->txop); 5260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(&mac->edca_param[aci], param, sizeof(*param)); 5270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_qos(hw, aci); 5280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 5290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 5300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_bss_info_changed(struct ieee80211_hw *hw, 5320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, 5330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_bss_conf *bss_conf, u32 changed) 5340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 5350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 5360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 5370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 5380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 5390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_sta *sta = NULL; 5400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5418a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 5420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if ((vif->type == NL80211_IFTYPE_ADHOC) || 5430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (vif->type == NL80211_IFTYPE_AP) || 5440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (vif->type == NL80211_IFTYPE_MESH_POINT)) { 5450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if ((changed & BSS_CHANGED_BEACON) || 5460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (changed & BSS_CHANGED_BEACON_ENABLED && 5470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bss_conf->enable_beacon)) { 5480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 0) { 5490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 5500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_BEACON_ENABLED\n")); 5510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*start hw beacon interrupt. */ 5530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*rtlpriv->cfg->ops->set_bcn_reg(hw); */ 5540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 1; 5550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 5560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 5570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS], 5580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 0); 5590baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 5600baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->cfg->ops->linked_set_reg) 5610baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->linked_set_reg(hw); 5620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 5640baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if ((changed & BSS_CHANGED_BEACON_ENABLED && 5650baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li !bss_conf->enable_beacon)) { 5660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 1) { 5670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 5680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("ADHOC DISABLE BEACON\n")); 5690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 0; 5710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, 5720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 5730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS]); 5740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_BEACON_INT) { 5770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, 5780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_BEACON_INT\n")); 5790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_interval = bss_conf->beacon_int; 5800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_bcn_intv(hw); 5810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*TODO: reference to enum ieee80211_bss_change */ 5850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ASSOC) { 5860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (bss_conf->assoc) { 5870baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* we should reset all sec info & cam 5880baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * before set cam after linked, we should not 5890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * reset in disassoc, that will cause tkip->wep 5900baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * fail because some flag will be wrong */ 5910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* reset sec info */ 5920baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_cam_reset_sec_info(hw); 5930baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* reset cam to fix wep fail issue 5940baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * when change from wpa to wep */ 5950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_cam_reset_all_entry(hw); 5960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 5970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED; 5980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cnt_after_linked = 0; 5990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->assoc_id = bss_conf->aid; 6000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac->bssid, bss_conf->bssid, 6); 6010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->cfg->ops->linked_set_reg) 6030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->linked_set_reg(hw); 6040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_STATION && sta) 6050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); 6060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 6070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_ASSOC\n")); 6080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 6090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->link_state == MAC80211_LINKED) 6100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_lps_leave(hw); 6110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_NOLINK; 6130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(mac->bssid, 0, 6); 614bac2555c6d86387132930af4d14cb47c4dd3f4f7George 615bac2555c6d86387132930af4d14cb47c4dd3f4f7George /* reset sec info */ 616bac2555c6d86387132930af4d14cb47c4dd3f4f7George rtl_cam_reset_sec_info(hw); 617bac2555c6d86387132930af4d14cb47c4dd3f4f7George 618bac2555c6d86387132930af4d14cb47c4dd3f4f7George rtl_cam_reset_all_entry(hw); 6190baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 6200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 6220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_UN_ASSOC\n")); 6230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ERP_CTS_PROT) { 6270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 6280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_ERP_CTS_PROT\n")); 6290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->use_cts_protect = bss_conf->use_cts_prot; 6300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ERP_PREAMBLE) { 6330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 6340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n", 6350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bss_conf->use_short_preamble)); 6360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->short_preamble = bss_conf->use_short_preamble; 6380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE, 6390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mac->short_preamble)); 6400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ERP_SLOT) { 6430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 6440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_ERP_SLOT\n")); 6450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (bss_conf->use_short_slot) 6470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->slot_time = RTL_SLOT_TIME_9; 6480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger else 6490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->slot_time = RTL_SLOT_TIME_20; 6500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, 6520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mac->slot_time)); 6530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_HT) { 6560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 6570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("BSS_CHANGED_HT\n")); 658701c2be03aac62a54decaa685c70d2b734afde67Alessio Igor Bogani rcu_read_lock(); 6597101f4043cdaa5dc2bf8974313744246f3955de7Larry Finger sta = get_sta(hw, vif, bss_conf->bssid); 6600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (sta) { 6610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (sta->ht_cap.ampdu_density > 6620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_density) 6630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_density = 6640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger sta->ht_cap.ampdu_density; 6650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (sta->ht_cap.ampdu_factor < 6660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_factor) 6670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_factor = 6680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger sta->ht_cap.ampdu_factor; 6690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 670701c2be03aac62a54decaa685c70d2b734afde67Alessio Igor Bogani rcu_read_unlock(); 6710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, 6730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mac->max_mss_density)); 6740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR, 6750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger &mac->current_ampdu_factor); 6760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE, 6770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger &mac->current_ampdu_density); 6780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_BSSID) { 6810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u32 basic_rates; 6820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, 6840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) bss_conf->bssid); 6850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 6871d15b5f2d380186761d49588de27b2a6538afacbAndy Shevchenko ("%pM\n", bss_conf->bssid)); 6880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 6900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac->bssid, bss_conf->bssid, 6); 6910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_network_type(hw, vif->type); 6920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 693701c2be03aac62a54decaa685c70d2b734afde67Alessio Igor Bogani rcu_read_lock(); 6947101f4043cdaa5dc2bf8974313744246f3955de7Larry Finger sta = get_sta(hw, vif, bss_conf->bssid); 6950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!sta) { 6960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rcu_read_unlock(); 6970baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li goto out; 6980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 6990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_5G) { 7010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_A; 7020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 7030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->supp_rates[0] <= 0xf) 7040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_B; 7050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 7060baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_G; 7070baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7080baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 7090baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->ht_cap.ht_supported) { 7100baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_2_4G) 7110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->mode = WIRELESS_MODE_N_24G; 7120baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 7130baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_N_5G; 7140baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7160baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* just station need it, because ibss & ap mode will 7170baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * set in sta_add, and will be NULL here */ 7180baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_STATION) { 7190baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_sta_info *sta_entry; 7200baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry = (struct rtl_sta_info *) sta->drv_priv; 7210baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = mac->mode; 7220baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7230baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 7240baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->ht_cap.ht_supported) { 7250baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->ht_enable = true; 7260baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 7270baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* 7280baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * for cisco 1252 bw20 it's wrong 7290baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { 7300baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * mac->bw_40 = true; 7310baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * } 7320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * */ 7330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_BASIC_RATES) { 7360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* for 5G must << RATE_6M_INDEX=4, 7370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * because 5G have no cck rate*/ 7380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_5G) 7390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li basic_rates = sta->supp_rates[1] << 4; 7400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger else 7410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li basic_rates = sta->supp_rates[0]; 7420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->basic_rates = basic_rates; 7440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, 7450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&basic_rates)); 7460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rcu_read_unlock(); 7480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 7510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * For FW LPS: 7520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * To tell firmware we have connected 7530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * to an AP. For 92SE/CE power save v2. 7540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 7550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ASSOC) { 7560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (bss_conf->assoc) { 7577ea4724036ed17ec811cb8082af7760f04484ef7Larry Finger if (ppsc->fwctrl_lps) { 7580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 mstatus = RT_MEDIA_CONNECT; 7590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, 7600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger HW_VAR_H2C_FW_JOINBSSRPT, 7610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mstatus)); 7620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ppsc->report_linked = true; 7630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 7657ea4724036ed17ec811cb8082af7760f04484ef7Larry Finger if (ppsc->fwctrl_lps) { 7660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 mstatus = RT_MEDIA_DISCONNECT; 7670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, 7680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger HW_VAR_H2C_FW_JOINBSSRPT, 7690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *)(&mstatus)); 7700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ppsc->report_linked = false; 7710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerout: 7768a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 7770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 7780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 77937a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 7800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 7810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 7820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u64 tsf; 7830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&tsf)); 7850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return tsf; 7860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 7870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 78837a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 78937a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Peller u64 tsf) 7900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 7910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 7920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 7936eab04a87677a37cf15b52e2b4b4fd57917102adJustin P. Mattock u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; 7940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->tsf = tsf; 7960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss)); 7970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 7980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 79937a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic void rtl_op_reset_tsf(struct ieee80211_hw *hw, 80037a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Peller struct ieee80211_vif *vif) 8010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 tmp = 0; 8040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *) (&tmp)); 8060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_sta_notify(struct ieee80211_hw *hw, 8090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, 8100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger enum sta_notify_cmd cmd, 8110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_sta *sta) 8120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (cmd) { 8140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case STA_NOTIFY_SLEEP: 8150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case STA_NOTIFY_AWAKE: 8170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 8190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_ampdu_action(struct ieee80211_hw *hw, 8240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, 8250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger enum ieee80211_ampdu_mlme_action action, 8260b01f030d38e00650e2db42da083d8647aad40a5Johannes Berg struct ieee80211_sta *sta, u16 tid, u16 *ssn, 8270b01f030d38e00650e2db42da083d8647aad40a5Johannes Berg u8 buf_size) 8280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (action) { 8320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_TX_START: 8330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 8340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid)); 8350baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return rtl_tx_agg_start(hw, sta, tid, ssn); 8360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_TX_STOP: 8380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 8390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid)); 8400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return rtl_tx_agg_stop(hw, sta, tid); 8410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_TX_OPERATIONAL: 8430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 8440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid)); 8450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_tx_agg_oper(hw, sta, tid); 8460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_RX_START: 8480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 8490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_AMPDU_RX_START:TID:%d\n", tid)); 8500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_RX_STOP: 8520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 8530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid)); 8540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 8560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 8570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("IEEE80211_AMPDU_ERR!!!!:\n")); 8580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -EOPNOTSUPP; 8590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 8610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_sw_scan_start(struct ieee80211_hw *hw) 8640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 8670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->act_scanning = true; 8690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); 8710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->link_state == MAC80211_LINKED) { 8730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_lps_leave(hw); 8740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED_SCANNING; 8750baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 8760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 8770baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 8780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 8790baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* Dual mac */ 8800baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; 8810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); 8830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); 8840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) 8870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 8900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); 8920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->act_scanning = false; 8930baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* Dual mac */ 8940baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; 8950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 8960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->link_state == MAC80211_LINKED_SCANNING) { 8970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED; 8980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_STATION) { 8990baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* fix fwlps issue */ 9000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); 9010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 9020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 9030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); 9050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 9060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 9080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, struct ieee80211_sta *sta, 9090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_key_conf *key) 9100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 9110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 9120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 9130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 key_type = NO_ENCRYPTION; 9140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 key_idx; 9150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool group_key = false; 9160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool wep_only = false; 9170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int err = 0; 9180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 mac_addr[ETH_ALEN]; 9190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 9200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 zero_addr[ETH_ALEN] = { 0 }; 9210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { 9230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 9240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("not open hw encryption\n")); 9250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -ENOSPC; /*User disabled HW-crypto */ 9260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 9270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 9280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("%s hardware based encryption for keyidx: %d, mac: %pM\n", 9290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, 9300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger sta ? sta->addr : bcast_addr)); 9310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.being_setkey = true; 9320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 9338a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 9340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <1> get encryption alg */ 9350baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 9360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (key->cipher) { 9370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_WEP40: 9380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = WEP40_ENCRYPTION; 9390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n")); 9400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_WEP104: 9420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 9430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("alg:WEP104\n")); 9440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = WEP104_ENCRYPTION; 9450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_TKIP: 9470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = TKIP_ENCRYPTION; 9480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n")); 9490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_CCMP: 9510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = AESCCMP_ENCRYPTION; 9520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n")); 9530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 9550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 9560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("alg_err:%x!!!!:\n", key->cipher)); 9570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out_unlock; 9580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 9590baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (key_type == WEP40_ENCRYPTION || 9600baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li key_type == WEP104_ENCRYPTION || 9610baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->opmode == NL80211_IFTYPE_ADHOC) 9620baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->sec.use_defaultkey = true; 9630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 9640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <2> get key_idx */ 9650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_idx = (u8) (key->keyidx); 9660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (key_idx > 3) 9670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out_unlock; 9680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <3> if pairwise key enable_hw_sec */ 9690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); 9700baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 9710baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* wep always be group key, but there are two conditions: 9720baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * 1) wep only: is just for wep enc, in this condition 9730baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION 9740baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * will be true & enable_hw_sec will be set when wep 9750baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * ke setting. 9760baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * 2) wep(group) + AES(pairwise): some AP like cisco 9770baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * may use it, in this condition enable_hw_sec will not 9780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * be set when wep key setting */ 9790baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* we must reset sec_info after lingked before set key, 9800baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * or some flag will be wrong*/ 9810baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_AP) { 9820baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!group_key || key_type == WEP40_ENCRYPTION || 9830baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li key_type == WEP104_ENCRYPTION) { 9840baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (group_key) 9850baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li wep_only = true; 9860baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->enable_hw_sec(hw); 9870baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 9880baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 9890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || 9900baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { 9910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->sec.pairwise_enc_algorithm == 9920baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li NO_ENCRYPTION && 9930baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (key_type == WEP40_ENCRYPTION || 9940baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li key_type == WEP104_ENCRYPTION)) 9950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li wep_only = true; 9960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->sec.pairwise_enc_algorithm = key_type; 9970baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 9980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li ("set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1" 9990baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li " TKIP:2 AES:4 WEP104:5)\n", key_type)); 10000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->enable_hw_sec(hw); 10010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 10020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <4> set key based on cmd */ 10040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (cmd) { 10050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case SET_KEY: 10060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (wep_only) { 10070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 10080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("set WEP(group/pairwise) key\n")); 10090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* Pairwise key with an assigned MAC address. */ 10100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.pairwise_enc_algorithm = key_type; 10110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.group_enc_algorithm = key_type; 10120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about wep key. */ 10130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(rtlpriv->sec.key_buf[key_idx], 10140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->key, key->keylen); 10150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[key_idx] = key->keylen; 10160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, zero_addr, ETH_ALEN); 10170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else if (group_key) { /* group key */ 10180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 10190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("set group key\n")); 10200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* group key */ 10210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.group_enc_algorithm = key_type; 10220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about group key. */ 10230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(rtlpriv->sec.key_buf[key_idx], 10240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->key, key->keylen); 10250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[key_idx] = key->keylen; 10260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, bcast_addr, ETH_ALEN); 10270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { /* pairwise key */ 10280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 10290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("set pairwise key\n")); 10300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!sta) { 10310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_ASSERT(false, ("pairwise key withnot" 10320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger "mac_addr\n")); 10330baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 10340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger err = -EOPNOTSUPP; 10350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out_unlock; 10360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* Pairwise key with an assigned MAC address. */ 10380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.pairwise_enc_algorithm = key_type; 10390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about pairwise key. */ 10400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], 10410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->key, key->keylen); 10420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; 10430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.pairwise_key = 10440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; 10450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, sta->addr, ETH_ALEN); 10460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr, 10480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger group_key, key_type, wep_only, 10490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger false); 10500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <5> tell mac80211 do something: */ 10510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*must use sw generate IV, or can not work !!!!. */ 10520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 10530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->hw_key_idx = key_idx; 10540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (key_type == TKIP_ENCRYPTION) 10550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 10560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 10570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case DISABLE_KEY: 10580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 10590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("disable key delete one entry\n")); 10600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about wep key. */ 10610baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_AP) { 10620baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta) 10630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_cam_del_entry(hw, sta->addr); 10640baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 10650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); 10660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[key_idx] = 0; 10670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, zero_addr, ETH_ALEN); 10680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 10690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *mac80211 will delete entrys one by one, 10700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *so don't use rtl_cam_reset_all_entry 10710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *or clear all entry here. 10720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 10730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_cam_delete_one_entry(hw, mac_addr, key_idx); 1074bac2555c6d86387132930af4d14cb47c4dd3f4f7George 1075bac2555c6d86387132930af4d14cb47c4dd3f4f7George rtl_cam_reset_sec_info(hw); 1076bac2555c6d86387132930af4d14cb47c4dd3f4f7George 10770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 10780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 10790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 10800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ("cmd_err:%x!!!!:\n", cmd)); 10810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerout_unlock: 10838a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 10840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.being_setkey = false; 10850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return err; 10860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 10870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 10880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_rfkill_poll(struct ieee80211_hw *hw) 10890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 10900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 10910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 10920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool radio_state; 10930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool blocked; 10940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 valid = 0; 10950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 10960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 10970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return; 10980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 10998a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 11000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*if Radio On return true here */ 11020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); 11030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (valid) { 11050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) { 11060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->rfkill.rfkill_state = radio_state; 11070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, 11090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (KERN_INFO "wireless radio switch turned %s\n", 11100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger radio_state ? "on" : "off")); 11110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; 11130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wiphy_rfkill_set_hw_state(hw->wiphy, blocked); 11140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 11150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 11160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11178a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 11180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 11190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11200baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li/* this function is called by mac80211 to flush tx buffer 11210baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * before switch channle or power save, or tx buffer packet 11220baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * maybe send after offchannel or rf sleep, this may cause 11230baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * dis-association by AP */ 11240baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Listatic void rtl_op_flush(struct ieee80211_hw *hw, bool drop) 11250baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li{ 11260baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_priv *rtlpriv = rtl_priv(hw); 11270baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 11280baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->intf_ops->flush) 11290baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->intf_ops->flush(hw, drop); 11300baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li} 11310baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 11320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerconst struct ieee80211_ops rtl_ops = { 11330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .start = rtl_op_start, 11340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .stop = rtl_op_stop, 11350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .tx = rtl_op_tx, 11360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .add_interface = rtl_op_add_interface, 11370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .remove_interface = rtl_op_remove_interface, 11380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .config = rtl_op_config, 11390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .configure_filter = rtl_op_configure_filter, 11400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li .sta_add = rtl_op_sta_add, 11410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li .sta_remove = rtl_op_sta_remove, 11420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .set_key = rtl_op_set_key, 11430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .conf_tx = rtl_op_conf_tx, 11440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .bss_info_changed = rtl_op_bss_info_changed, 11450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .get_tsf = rtl_op_get_tsf, 11460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .set_tsf = rtl_op_set_tsf, 11470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .reset_tsf = rtl_op_reset_tsf, 11480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .sta_notify = rtl_op_sta_notify, 11490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .ampdu_action = rtl_op_ampdu_action, 11500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .sw_scan_start = rtl_op_sw_scan_start, 11510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .sw_scan_complete = rtl_op_sw_scan_complete, 11520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .rfkill_poll = rtl_op_rfkill_poll, 11530baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li .flush = rtl_op_flush, 11540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger}; 1155