10c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger/****************************************************************************** 20c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * 3a8d760668eebc98915383481cb3d9eaf74c2a615Larry Finger * Copyright(c) 2009-2012 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" 34b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger#include "pci.h" 350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger#include "ps.h" 360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 37b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger#include <linux/export.h> 38b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger 39b0302aba812bcc39291cdab9ad7e37008f352a91Larry Fingervoid rtl_fw_cb(const struct firmware *firmware, void *context) 40b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger{ 41b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger struct ieee80211_hw *hw = context; 42b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 43b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger int err; 44b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger 45b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 46b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger "Firmware callback routine entered!\n"); 47b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger complete(&rtlpriv->firmware_loading_complete); 48b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger if (!firmware) { 49b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); 50b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger rtlpriv->max_fw_size = 0; 51b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger return; 52b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger } 53b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger if (firmware->size > rtlpriv->max_fw_size) { 54b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 55b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger "Firmware is too big!\n"); 56b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger release_firmware(firmware); 57b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger return; 58b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger } 59b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); 60b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger rtlpriv->rtlhal.fwsize = firmware->size; 61b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger release_firmware(firmware); 62b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger 63b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger err = ieee80211_register_hw(hw); 64b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger if (err) { 65b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 66b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger "Can't register mac80211 hw\n"); 67b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger return; 68b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger } else { 69b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger rtlpriv->mac80211.mac80211_registered = 1; 70b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger } 71b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); 72b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger 73b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger /*init rfkill */ 74b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger rtl_init_rfkill(hw); 75b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger} 76b0302aba812bcc39291cdab9ad7e37008f352a91Larry FingerEXPORT_SYMBOL(rtl_fw_cb); 77b0302aba812bcc39291cdab9ad7e37008f352a91Larry Finger 780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger/*mutex for start & stop is must here. */ 790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_start(struct ieee80211_hw *hw) 800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 81324732848c42bf79988479ee1b4359e15f08154bLarry Finger int err; 820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!is_hal_stop(rtlhal)) 860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 898a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger err = rtlpriv->intf_ops->adapter_start(hw); 91324732848c42bf79988479ee1b4359e15f08154bLarry Finger if (!err) 92324732848c42bf79988479ee1b4359e15f08154bLarry Finger rtl_watch_dog_timer_callback((unsigned long)hw); 938a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return err; 950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_stop(struct ieee80211_hw *hw) 980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 1000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 1010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 1030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (is_hal_stop(rtlhal)) 1050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return; 1060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(ppsc->rfpwr_state == ERFOFF)) { 1080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 1090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mdelay(1); 1100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1128a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 1130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_NOLINK; 1150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(mac->bssid, 0, 6); 1160baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 1170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*reset sec info */ 1190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_cam_reset_sec_info(hw); 1200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_deinit_deferred_work(hw); 1220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->intf_ops->adapter_stop(hw); 1230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1248a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 1250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 1260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1277bb4568372856688bc070917265bce0b88bb7d4dJohannes Bergstatic void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 1280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 1290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 1300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 1320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_tcb_desc tcb_desc; 1330baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); 1340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) 1360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto err_free; 1370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 1390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto err_free; 1400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) 1420baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); 1430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1447bb4568372856688bc070917265bce0b88bb7d4dJohannes Berg return; 1450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingererr_free: 1470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger dev_kfree_skb_any(skb); 1480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 1490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_add_interface(struct ieee80211_hw *hw, 1510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif) 1520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 1530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 1540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 1550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int err = 0; 1560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 157c1288b1278d00169e12495eb53ad128e09560b69Johannes Berg vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; 158c1288b1278d00169e12495eb53ad128e09560b69Johannes Berg 1590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->vif) { 1600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 161f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "vif has been set!! mac->vif = 0x%p\n", mac->vif); 1620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -EOPNOTSUPP; 1630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 1660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1678a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 1680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (vif->type) { 1690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_IFTYPE_STATION: 1700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 1) { 1710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 172f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "NL80211_IFTYPE_STATION\n"); 1730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 0; 1740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, 1750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 1760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS]); 1770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 1780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 1790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_IFTYPE_ADHOC: 1800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 181f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "NL80211_IFTYPE_ADHOC\n"); 1820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 1830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED; 1840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_bcn_reg(hw); 1850baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) 1860baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xfff; 1870baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 1880baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xff0; 1890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, 1900baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (u8 *) (&mac->basic_rates)); 1910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 1920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 1930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_IFTYPE_AP: 1940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 195f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "NL80211_IFTYPE_AP\n"); 1960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 1970baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->link_state = MAC80211_LINKED; 1980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_bcn_reg(hw); 1990baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) 2000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xfff; 2010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 2020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->basic_rates = 0xff0; 2030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, 2040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (u8 *) (&mac->basic_rates)); 2050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 2060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 2070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 208f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "operation mode %d is not supported!\n", vif->type); 2090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger err = -EOPNOTSUPP; 2100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out; 2110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->vif = vif; 2140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->opmode = vif->type; 2150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_network_type(hw, vif->type); 2160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac->mac_addr, vif->addr, ETH_ALEN); 2170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); 2180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerout: 2208a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 2210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return err; 2220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 2230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_remove_interface(struct ieee80211_hw *hw, 2250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif) 2260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 2270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 2280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 2290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2308a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 2310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* Free beacon resources */ 2330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if ((mac->opmode == NL80211_IFTYPE_AP) || 2340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (mac->opmode == NL80211_IFTYPE_ADHOC) || 2350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (mac->opmode == NL80211_IFTYPE_MESH_POINT)) { 2360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 1) { 2370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 0; 2380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, 2390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 2400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS]); 2410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 2450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *Note: We assume NL80211_IFTYPE_UNSPECIFIED as 2460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *NO LINK for our hardware. 2470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 2480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->vif = NULL; 2490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_NOLINK; 2500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(mac->bssid, 0, 6); 2510baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 2520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->opmode = NL80211_IFTYPE_UNSPECIFIED; 2530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); 2548a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 2550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 2560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_config(struct ieee80211_hw *hw, u32 changed) 2580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 2590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 2600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_phy *rtlphy = &(rtlpriv->phy); 2610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 2620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 2630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_conf *conf = &hw->conf; 2640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2658a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 2660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ 2670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 268f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"); 2690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*For IPS */ 2720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_IDLE) { 2730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (hw->conf.flags & IEEE80211_CONF_IDLE) 2740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_off(hw); 2750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger else 2760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 2770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 2780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 2790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *although rfoff may not cause by ips, but we will 2800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *check the reason in set_rf_power_state function 2810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 2820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(ppsc->rfpwr_state == ERFOFF)) 2830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 2840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 2850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 2860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*For LPS */ 2870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_PS) { 2880baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li cancel_delayed_work(&rtlpriv->works.ps_work); 2890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); 2900baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (conf->flags & IEEE80211_CONF_PS) { 2910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->psc.sw_ps_enabled = true; 2920baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* sleep here is must, or we may recv the beacon and 2930baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * cause mac80211 into wrong ps state, this will cause 2940baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * power save nullfunc send fail, and further cause 2950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * pkt loss, So sleep must quickly but not immediatly 2960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * because that will cause nullfunc send by mac80211 2970baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * fail, and cause pkt loss, we have tested that 5mA 2980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * is worked very well */ 2993eda95de19e1781612091869e866a5014257f462Larry Finger if (!rtlpriv->psc.multi_buffered) 3000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li queue_delayed_work(rtlpriv->works.rtl_wq, 3010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li &rtlpriv->works.ps_work, 3020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li MSECS(5)); 3030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 3040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_swlps_rf_awake(hw); 3050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->psc.sw_ps_enabled = false; 3060baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 3070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { 3100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 311f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n", 312f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches hw->conf.long_frame_max_tx_count); 3130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->retry_long = hw->conf.long_frame_max_tx_count; 3140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->retry_short = hw->conf.long_frame_max_tx_count; 3150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, 3160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&hw->conf. 3170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger long_frame_max_tx_count)); 3180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 3210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_channel *channel = hw->conf.channel; 3220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 wide_chan = (u8) channel->hw_value; 3230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 3250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *because we should back channel to 3260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *current_network.chan in in scanning, 3270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *So if set_chan == current_network.chan 3280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *we should set it. 3290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *because mac80211 tell us wrong bw40 3300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *info for cisco1253 bw20, so we modify 3310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *it here based on UPPER & LOWER 3320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 3330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (hw->conf.channel_type) { 3340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_HT20: 3350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_NO_HT: 3360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* SC */ 3370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cur_40_prime_sc = 3380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li PRIME_CHNL_OFFSET_DONT_CARE; 3390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; 3400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = false; 3410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_HT40MINUS: 3430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* SC */ 3440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; 3450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_chan_bw = 3460baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li HT_CHANNEL_WIDTH_20_40; 3470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = true; 3480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*wide channel */ 3500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wide_chan -= 2; 3510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case NL80211_CHAN_HT40PLUS: 3540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* SC */ 3550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; 3560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_chan_bw = 3570baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li HT_CHANNEL_WIDTH_20_40; 3580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = true; 3590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*wide channel */ 3610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wide_chan += 2; 3620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 3650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->bw_40 = false; 3660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 367f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "switch case not processed\n"); 3680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 3690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (wide_chan <= 0) 3720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wide_chan = 1; 3730baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 3740baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* In scanning, before we go offchannel we may send a ps=1 null 3750baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * to AP, and then we may send a ps = 0 null to AP quickly, but 3760baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * first null may have caused AP to put lots of packet to hw tx 3770baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * buffer. These packets must be tx'd before we go off channel 3780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * so we must delay more time to let AP flush these packets 3790baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * before going offchannel, or dis-association or delete BA will 3800baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * happen by AP 3810baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li */ 3829c0504403725ca77153a0bdad2f3bef0a05e32f0Mike McCormack if (rtlpriv->mac80211.offchan_delay) { 3839c0504403725ca77153a0bdad2f3bef0a05e32f0Mike McCormack rtlpriv->mac80211.offchan_delay = false; 3840baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mdelay(50); 3850baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 3860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlphy->current_channel = wide_chan; 3870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->switch_channel(hw); 3890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_channel_access(hw); 3900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_bw_mode(hw, 3910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger hw->conf.channel_type); 3920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 3930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3948a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 3950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 3970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 3980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 3990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_configure_filter(struct ieee80211_hw *hw, 4000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger unsigned int changed_flags, 4010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger unsigned int *new_flags, u64 multicast) 4020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 4030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 4040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 4050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *new_flags &= RTL_SUPPORTED_FILTERS; 4070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!changed_flags) 4080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return; 4090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*TODO: we disable broadcase now, so enable here */ 4110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_ALLMULTI) { 4120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_ALLMULTI) { 4130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | 4140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps[MAC_RCR_AB]; 4150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 416f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Enable receive multicast frame\n"); 4170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 4180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] | 4190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps[MAC_RCR_AB]); 4200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 421f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Disable receive multicast frame\n"); 4220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_FCSFAIL) { 4260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_FCSFAIL) { 4270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32]; 4280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 429f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Enable receive FCS error frame\n"); 4300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 4310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32]; 4320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 433f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Disable receive FCS error frame\n"); 4340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* if ssid not set to hw don't check bssid 4380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * here just used for linked scanning, & linked 4390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * and nolink check bssid is set in set network_type */ 4400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && 4410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (mac->link_state >= MAC80211_LINKED)) { 4420baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode != NL80211_IFTYPE_AP) { 4430baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { 4440baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_chk_bssid(hw, false); 4450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 4460baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_chk_bssid(hw, true); 4470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4480baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_CONTROL) { 4520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_CONTROL) { 4530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; 4540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 456f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Enable receive control frame\n"); 4570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 4580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; 4590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 460f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Disable receive control frame\n"); 4610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 4640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed_flags & FIF_OTHER_BSS) { 4650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (*new_flags & FIF_OTHER_BSS) { 4660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP]; 4670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 468f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Enable receive other BSS's frame\n"); 4690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 4700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP]; 4710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 472f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Disable receive other BSS's frame\n"); 4730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 4750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 4760baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Listatic int rtl_op_sta_add(struct ieee80211_hw *hw, 4770baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_vif *vif, 4780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_sta *sta) 4790baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li{ 4800baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_priv *rtlpriv = rtl_priv(hw); 4810baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 4820baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_sta_info *sta_entry; 4830baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 4840baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta) { 4850baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry = (struct rtl_sta_info *) sta->drv_priv; 4860baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_2_4G) { 4870baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_G; 4880baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->supp_rates[0] <= 0xf) 4890baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_B; 490e10542c447abf7c840931ff12f7d0dee976ca2eaMike McCormack if (sta->ht_cap.ht_supported) 4910baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_N_24G; 4920baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else if (rtlhal->current_bandtype == BAND_ON_5G) { 4930baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_A; 494e10542c447abf7c840931ff12f7d0dee976ca2eaMike McCormack if (sta->ht_cap.ht_supported) 4950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_N_24G; 4960baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 4970baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 4980baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* I found some times mac80211 give wrong supp_rates for adhoc*/ 4990baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) 5000baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = WIRELESS_MODE_G; 5010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 503f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Add sta addr is %pM\n", sta->addr); 5040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); 5050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 5060baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return 0; 5070baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li} 5080baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Listatic int rtl_op_sta_remove(struct ieee80211_hw *hw, 5090baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_vif *vif, 5100baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_sta *sta) 5110baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li{ 5120baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_priv *rtlpriv = rtl_priv(hw); 5130baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_sta_info *sta_entry; 5140baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta) { 5150baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 516f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "Remove sta addr is %pM\n", sta->addr); 5170baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry = (struct rtl_sta_info *) sta->drv_priv; 5180baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = 0; 5190baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->ratr_index = 0; 5200baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 5210baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return 0; 5220baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li} 5230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int _rtl_get_hal_qnum(u16 queue) 5240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 5250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int qnum; 5260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (queue) { 5280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 0: 5290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC3_VO; 5300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 5310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 1: 5320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC2_VI; 5330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 5340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 2: 5350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC0_BE; 5360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 5370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case 3: 5380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC1_BK; 5390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 5400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 5410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger qnum = AC0_BE; 5420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 5430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return qnum; 5450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 5460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger/* 5480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *for mac80211 VO=0, VI=1, BE=2, BK=3 5490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *for rtl819x BE=0, BK=1, VI=2, VO=3 5500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 5518a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Pellerstatic int rtl_op_conf_tx(struct ieee80211_hw *hw, 5528a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Peller struct ieee80211_vif *vif, u16 queue, 5530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger const struct ieee80211_tx_queue_params *param) 5540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 5550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 5560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 5570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int aci; 5580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (queue >= AC_MAX) { 5600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 561f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "queue number %d is incorrect!\n", queue); 5620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -EINVAL; 5630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 5640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger aci = _rtl_get_hal_qnum(queue); 5660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->ac[aci].aifs = param->aifs; 56717c9ac62812b58aacefc7336215aecbb522f6547Larry Finger mac->ac[aci].cw_min = cpu_to_le16(param->cw_min); 56817c9ac62812b58aacefc7336215aecbb522f6547Larry Finger mac->ac[aci].cw_max = cpu_to_le16(param->cw_max); 56917c9ac62812b58aacefc7336215aecbb522f6547Larry Finger mac->ac[aci].tx_op = cpu_to_le16(param->txop); 5700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(&mac->edca_param[aci], param, sizeof(*param)); 5710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_qos(hw, aci); 5720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 5730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 5740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_bss_info_changed(struct ieee80211_hw *hw, 5760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, 5770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_bss_conf *bss_conf, u32 changed) 5780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 5790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 5800baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 5810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 5820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 5830baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct ieee80211_sta *sta = NULL; 5840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5858a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 5860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if ((vif->type == NL80211_IFTYPE_ADHOC) || 5870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (vif->type == NL80211_IFTYPE_AP) || 5880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (vif->type == NL80211_IFTYPE_MESH_POINT)) { 5890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if ((changed & BSS_CHANGED_BEACON) || 5900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (changed & BSS_CHANGED_BEACON_ENABLED && 5910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bss_conf->enable_beacon)) { 5920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 0) { 5930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 594f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_BEACON_ENABLED\n"); 5950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 5960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*start hw beacon interrupt. */ 5970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*rtlpriv->cfg->ops->set_bcn_reg(hw); */ 5980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 1; 5990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 6000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 6010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS], 6020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 0); 6030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 6040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->cfg->ops->linked_set_reg) 6050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->linked_set_reg(hw); 6060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6070baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 6080baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if ((changed & BSS_CHANGED_BEACON_ENABLED && 6090baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li !bss_conf->enable_beacon)) { 6100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->beacon_enabled == 1) { 6110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 612f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "ADHOC DISABLE BEACON\n"); 6130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_enabled = 0; 6150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, 6160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->maps 6170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger [RTL_IBSS_INT_MASKS]); 6180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_BEACON_INT) { 6210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, 622f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_BEACON_INT\n"); 6230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->beacon_interval = bss_conf->beacon_int; 6240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_bcn_intv(hw); 6250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*TODO: reference to enum ieee80211_bss_change */ 6290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ASSOC) { 6300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (bss_conf->assoc) { 6310baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* we should reset all sec info & cam 6320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * before set cam after linked, we should not 6330baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * reset in disassoc, that will cause tkip->wep 6340baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * fail because some flag will be wrong */ 6350baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* reset sec info */ 6360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_cam_reset_sec_info(hw); 6370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* reset cam to fix wep fail issue 6380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * when change from wpa to wep */ 6390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_cam_reset_all_entry(hw); 6400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 6410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED; 6420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->cnt_after_linked = 0; 6430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->assoc_id = bss_conf->aid; 6440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac->bssid, bss_conf->bssid, 6); 6450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6460baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->cfg->ops->linked_set_reg) 6470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->linked_set_reg(hw); 6480baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_STATION && sta) 6490baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); 6500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 651f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_ASSOC\n"); 6520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 6530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->link_state == MAC80211_LINKED) 6540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_lps_leave(hw); 6550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_NOLINK; 6570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(mac->bssid, 0, 6); 658bac2555c6d86387132930af4d14cb47c4dd3f4f7George 659bac2555c6d86387132930af4d14cb47c4dd3f4f7George /* reset sec info */ 660bac2555c6d86387132930af4d14cb47c4dd3f4f7George rtl_cam_reset_sec_info(hw); 661bac2555c6d86387132930af4d14cb47c4dd3f4f7George 662bac2555c6d86387132930af4d14cb47c4dd3f4f7George rtl_cam_reset_all_entry(hw); 6630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 6640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, 666f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_UN_ASSOC\n"); 6670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ERP_CTS_PROT) { 6710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 672f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_ERP_CTS_PROT\n"); 6730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->use_cts_protect = bss_conf->use_cts_prot; 6740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ERP_PREAMBLE) { 6770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, 678f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n", 679f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches bss_conf->use_short_preamble); 6800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->short_preamble = bss_conf->use_short_preamble; 6820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE, 6830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mac->short_preamble)); 6840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ERP_SLOT) { 6870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 688f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "BSS_CHANGED_ERP_SLOT\n"); 6890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (bss_conf->use_short_slot) 6910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->slot_time = RTL_SLOT_TIME_9; 6920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger else 6930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->slot_time = RTL_SLOT_TIME_20; 6940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, 6960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mac->slot_time)); 6970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 6980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 6990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_HT) { 700f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, "BSS_CHANGED_HT\n"); 701701c2be03aac62a54decaa685c70d2b734afde67Alessio Igor Bogani rcu_read_lock(); 7027101f4043cdaa5dc2bf8974313744246f3955de7Larry Finger sta = get_sta(hw, vif, bss_conf->bssid); 7030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (sta) { 7040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (sta->ht_cap.ampdu_density > 7050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_density) 7060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_density = 7070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger sta->ht_cap.ampdu_density; 7080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (sta->ht_cap.ampdu_factor < 7090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_factor) 7100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->current_ampdu_factor = 7110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger sta->ht_cap.ampdu_factor; 7120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 713701c2be03aac62a54decaa685c70d2b734afde67Alessio Igor Bogani rcu_read_unlock(); 7140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, 7160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mac->max_mss_density)); 7170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR, 7180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger &mac->current_ampdu_factor); 7190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE, 7200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger &mac->current_ampdu_density); 7210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7220c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_BSSID) { 7240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u32 basic_rates; 7250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, 7270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) bss_conf->bssid); 7280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 729f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "%pM\n", 730f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches bss_conf->bssid); 7310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->vendor = PEER_UNKNOWN; 7330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac->bssid, bss_conf->bssid, 6); 7340baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_network_type(hw, vif->type); 7350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 736701c2be03aac62a54decaa685c70d2b734afde67Alessio Igor Bogani rcu_read_lock(); 7377101f4043cdaa5dc2bf8974313744246f3955de7Larry Finger sta = get_sta(hw, vif, bss_conf->bssid); 7380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!sta) { 7390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rcu_read_unlock(); 7400baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li goto out; 7410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7430baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_5G) { 7440baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_A; 7450baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 7460baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->supp_rates[0] <= 0xf) 7470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_B; 7480baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 7490baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_G; 7500baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7510baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 7520baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->ht_cap.ht_supported) { 7530baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_2_4G) 7540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->mode = WIRELESS_MODE_N_24G; 7550baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li else 7560baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->mode = WIRELESS_MODE_N_5G; 7570baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7590baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* just station need it, because ibss & ap mode will 7600baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * set in sta_add, and will be NULL here */ 7610baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_STATION) { 7620baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_sta_info *sta_entry; 7630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry = (struct rtl_sta_info *) sta->drv_priv; 7640baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li sta_entry->wireless_mode = mac->mode; 7650baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 7660baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 7670baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta->ht_cap.ht_supported) { 7680baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->ht_enable = true; 7690baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 7700baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* 7710baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * for cisco 1252 bw20 it's wrong 7720baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { 7730baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * mac->bw_40 = true; 7740baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * } 7750baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * */ 7760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_BASIC_RATES) { 7790baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* for 5G must << RATE_6M_INDEX=4, 7800baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * because 5G have no cck rate*/ 7810baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlhal->current_bandtype == BAND_ON_5G) 7820baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li basic_rates = sta->supp_rates[1] << 4; 7830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger else 7840baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li basic_rates = sta->supp_rates[0]; 7850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->basic_rates = basic_rates; 7870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, 7880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&basic_rates)); 7890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7900baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rcu_read_unlock(); 7910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 7920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 7930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 7940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * For FW LPS: 7950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * To tell firmware we have connected 7960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger * to an AP. For 92SE/CE power save v2. 7970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 7980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (changed & BSS_CHANGED_ASSOC) { 7990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (bss_conf->assoc) { 8007ea4724036ed17ec811cb8082af7760f04484ef7Larry Finger if (ppsc->fwctrl_lps) { 8010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 mstatus = RT_MEDIA_CONNECT; 8020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, 8030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger HW_VAR_H2C_FW_JOINBSSRPT, 8040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *) (&mstatus)); 8050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ppsc->report_linked = true; 8060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { 8087ea4724036ed17ec811cb8082af7760f04484ef7Larry Finger if (ppsc->fwctrl_lps) { 8090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 mstatus = RT_MEDIA_DISCONNECT; 8100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, 8110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger HW_VAR_H2C_FW_JOINBSSRPT, 8120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger (u8 *)(&mstatus)); 8130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger ppsc->report_linked = false; 8140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8180c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerout: 8198a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 8200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 82237a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 8230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u64 tsf; 8260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&tsf)); 8280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return tsf; 8290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 83137a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 83237a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Peller u64 tsf) 8330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 8366eab04a87677a37cf15b52e2b4b4fd57917102adJustin P. Mattock u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; 8370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->tsf = tsf; 8390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss)); 8400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8410c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 84237a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic void rtl_op_reset_tsf(struct ieee80211_hw *hw, 84337a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Peller struct ieee80211_vif *vif) 8440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 tmp = 0; 8470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *) (&tmp)); 8490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_sta_notify(struct ieee80211_hw *hw, 8520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, 8530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger enum sta_notify_cmd cmd, 8540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_sta *sta) 8550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (cmd) { 8570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case STA_NOTIFY_SLEEP: 8580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case STA_NOTIFY_AWAKE: 8600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 8620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 8640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 8650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_ampdu_action(struct ieee80211_hw *hw, 8670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, 8680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger enum ieee80211_ampdu_mlme_action action, 8690b01f030d38e00650e2db42da083d8647aad40a5Johannes Berg struct ieee80211_sta *sta, u16 tid, u16 *ssn, 8700b01f030d38e00650e2db42da083d8647aad40a5Johannes Berg u8 buf_size) 8710c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 8720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 8730c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 8740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (action) { 8750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_TX_START: 8760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 877f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_AMPDU_TX_START: TID:%d\n", tid); 8780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return rtl_tx_agg_start(hw, sta, tid, ssn); 8790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_TX_STOP: 8810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 882f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); 8830baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li return rtl_tx_agg_stop(hw, sta, tid); 8840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_TX_OPERATIONAL: 8860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 887f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); 8880baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_tx_agg_oper(hw, sta, tid); 8890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_RX_START: 8910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 892f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); 8930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case IEEE80211_AMPDU_RX_STOP: 8950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 896f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); 8970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 8980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 8990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 900f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "IEEE80211_AMPDU_ERR!!!!:\n"); 9010c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -EOPNOTSUPP; 9020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 9030c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return 0; 9040c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 9050c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_sw_scan_start(struct ieee80211_hw *hw) 9070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 9080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 9090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 9100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->act_scanning = true; 9120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 913f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); 9140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->link_state == MAC80211_LINKED) { 9160c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_lps_leave(hw); 9170c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED_SCANNING; 9180baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 9190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 9200baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 9210baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 9220baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* Dual mac */ 9230baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; 9240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9250c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); 9260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); 9270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 9280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) 9300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 9310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 9320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 9330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 934f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); 9350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->act_scanning = false; 9360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* Dual mac */ 9370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; 9380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 9390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (mac->link_state == MAC80211_LINKED_SCANNING) { 9400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger mac->link_state = MAC80211_LINKED; 9410baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_STATION) { 9420baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* fix fwlps issue */ 9430baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); 9440baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 9450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 9460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9470baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); 9480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 9490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 9510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_vif *vif, struct ieee80211_sta *sta, 9520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct ieee80211_key_conf *key) 9530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 9540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 9550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 9560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 key_type = NO_ENCRYPTION; 9570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 key_idx; 9580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool group_key = false; 9590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool wep_only = false; 9600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger int err = 0; 9610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 mac_addr[ETH_ALEN]; 9620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 9630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 zero_addr[ETH_ALEN] = { 0 }; 9640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 9650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { 9660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 967f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "not open hw encryption\n"); 9680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return -ENOSPC; /*User disabled HW-crypto */ 9690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 9700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 971f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "%s hardware based encryption for keyidx: %d, mac: %pM\n", 972f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, 973f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches sta ? sta->addr : bcast_addr); 9740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.being_setkey = true; 9750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_ips_nic_on(hw); 9768a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 9770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <1> get encryption alg */ 9780baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 9790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (key->cipher) { 9800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_WEP40: 9810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = WEP40_ENCRYPTION; 982f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n"); 9830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_WEP104: 985f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n"); 9860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = WEP104_ENCRYPTION; 9870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_TKIP: 9890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = TKIP_ENCRYPTION; 990f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n"); 9910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case WLAN_CIPHER_SUITE_CCMP: 9930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_type = AESCCMP_ENCRYPTION; 994f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); 9950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 9960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 997f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", 998f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches key->cipher); 9990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out_unlock; 10000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10010baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (key_type == WEP40_ENCRYPTION || 10020baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li key_type == WEP104_ENCRYPTION || 10030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li mac->opmode == NL80211_IFTYPE_ADHOC) 10040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->sec.use_defaultkey = true; 10050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 10060c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <2> get key_idx */ 10070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key_idx = (u8) (key->keyidx); 10080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (key_idx > 3) 10090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out_unlock; 10100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <3> if pairwise key enable_hw_sec */ 10110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); 10120baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 10130baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* wep always be group key, but there are two conditions: 10140baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * 1) wep only: is just for wep enc, in this condition 10150baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION 10160baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * will be true & enable_hw_sec will be set when wep 10170baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * ke setting. 10180baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * 2) wep(group) + AES(pairwise): some AP like cisco 10190baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * may use it, in this condition enable_hw_sec will not 10200baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * be set when wep key setting */ 10210baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li /* we must reset sec_info after lingked before set key, 10220baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * or some flag will be wrong*/ 10230baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_AP) { 10240baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (!group_key || key_type == WEP40_ENCRYPTION || 10250baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li key_type == WEP104_ENCRYPTION) { 10260baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (group_key) 10270baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li wep_only = true; 10280baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->enable_hw_sec(hw); 10290baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 10300baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } else { 10310baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || 10320baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { 10330baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->sec.pairwise_enc_algorithm == 10340baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li NO_ENCRYPTION && 10350baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li (key_type == WEP40_ENCRYPTION || 10360baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li key_type == WEP104_ENCRYPTION)) 10370baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li wep_only = true; 10380baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->sec.pairwise_enc_algorithm = key_type; 10390baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 1040f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n", 1041f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches key_type); 10420baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->cfg->ops->enable_hw_sec(hw); 10430baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 10440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <4> set key based on cmd */ 10460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger switch (cmd) { 10470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case SET_KEY: 10480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (wep_only) { 10490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 1050f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "set WEP(group/pairwise) key\n"); 10510c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* Pairwise key with an assigned MAC address. */ 10520c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.pairwise_enc_algorithm = key_type; 10530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.group_enc_algorithm = key_type; 10540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about wep key. */ 10550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(rtlpriv->sec.key_buf[key_idx], 10560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->key, key->keylen); 10570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[key_idx] = key->keylen; 10580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, zero_addr, ETH_ALEN); 10590c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else if (group_key) { /* group key */ 10600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 1061f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "set group key\n"); 10620c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* group key */ 10630c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.group_enc_algorithm = key_type; 10640c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about group key. */ 10650c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(rtlpriv->sec.key_buf[key_idx], 10660c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->key, key->keylen); 10670c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[key_idx] = key->keylen; 10680c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, bcast_addr, ETH_ALEN); 10690c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } else { /* pairwise key */ 10700c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 1071f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "set pairwise key\n"); 10720c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!sta) { 10739d833ed752e91c71792dd8ebfd0f865e6a568a37Joe Perches RT_ASSERT(false, 10749d833ed752e91c71792dd8ebfd0f865e6a568a37Joe Perches "pairwise key without mac_addr\n"); 10750baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 10760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger err = -EOPNOTSUPP; 10770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger goto out_unlock; 10780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* Pairwise key with an assigned MAC address. */ 10800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.pairwise_enc_algorithm = key_type; 10810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about pairwise key. */ 10820c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], 10830c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->key, key->keylen); 10840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; 10850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.pairwise_key = 10860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; 10870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, sta->addr, ETH_ALEN); 10880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 10890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr, 10900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger group_key, key_type, wep_only, 10910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger false); 10920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* <5> tell mac80211 do something: */ 10930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*must use sw generate IV, or can not work !!!!. */ 10940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 10950c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->hw_key_idx = key_idx; 10960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (key_type == TKIP_ENCRYPTION) 10970c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 10980c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 10990c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger case DISABLE_KEY: 11000c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, 1101f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "disable key delete one entry\n"); 11020c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*set local buf about wep key. */ 11030baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (mac->opmode == NL80211_IFTYPE_AP) { 11040baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (sta) 11050baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtl_cam_del_entry(hw, sta->addr); 11060baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li } 11070c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); 11080c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.key_len[key_idx] = 0; 11090c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger memcpy(mac_addr, zero_addr, ETH_ALEN); 11100c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /* 11110c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *mac80211 will delete entrys one by one, 11120c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *so don't use rtl_cam_reset_all_entry 11130c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger *or clear all entry here. 11140c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger */ 11150c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtl_cam_delete_one_entry(hw, mac_addr, key_idx); 1116bac2555c6d86387132930af4d14cb47c4dd3f4f7George 1117bac2555c6d86387132930af4d14cb47c4dd3f4f7George rtl_cam_reset_sec_info(hw); 1118bac2555c6d86387132930af4d14cb47c4dd3f4f7George 11190c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger break; 11200c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger default: 11210c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 1122f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "cmd_err:%x!!!!\n", cmd); 11230c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 11240c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerout_unlock: 11258a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 11260c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->sec.being_setkey = false; 11270c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return err; 11280c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 11290c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11300c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerstatic void rtl_op_rfkill_poll(struct ieee80211_hw *hw) 11310c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger{ 11320c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw); 11330c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11340c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool radio_state; 11350c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger bool blocked; 11360c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger u8 valid = 0; 11370c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11380c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 11390c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger return; 11400c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11418a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_lock(&rtlpriv->locks.conf_mutex); 11420c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11430c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger /*if Radio On return true here */ 11440c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); 11450c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11460c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (valid) { 11470c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) { 11480c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger rtlpriv->rfkill.rfkill_state = radio_state; 11490c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11500c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, 1151f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches "wireless radio switch turned %s\n", 1152f30d7507a8116e2099a9135c873411db8c0a3dc6Joe Perches radio_state ? "on" : "off"); 11530c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11540c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; 11550c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger wiphy_rfkill_set_hw_state(hw->wiphy, blocked); 11560c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 11570c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger } 11580c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11598a09d6d80c90c02f2f8c89f69c702cab0c8d9b42Larry Finger mutex_unlock(&rtlpriv->locks.conf_mutex); 11600c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger} 11610c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger 11620baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li/* this function is called by mac80211 to flush tx buffer 11630baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * before switch channle or power save, or tx buffer packet 11640baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * maybe send after offchannel or rf sleep, this may cause 11650baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li * dis-association by AP */ 11660baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Listatic void rtl_op_flush(struct ieee80211_hw *hw, bool drop) 11670baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li{ 11680baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li struct rtl_priv *rtlpriv = rtl_priv(hw); 11690baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 11700baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li if (rtlpriv->intf_ops->flush) 11710baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li rtlpriv->intf_ops->flush(hw, drop); 11720baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li} 11730baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li 11740c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Fingerconst struct ieee80211_ops rtl_ops = { 11750c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .start = rtl_op_start, 11760c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .stop = rtl_op_stop, 11770c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .tx = rtl_op_tx, 11780c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .add_interface = rtl_op_add_interface, 11790c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .remove_interface = rtl_op_remove_interface, 11800c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .config = rtl_op_config, 11810c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .configure_filter = rtl_op_configure_filter, 11820baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li .sta_add = rtl_op_sta_add, 11830baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li .sta_remove = rtl_op_sta_remove, 11840c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .set_key = rtl_op_set_key, 11850c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .conf_tx = rtl_op_conf_tx, 11860c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .bss_info_changed = rtl_op_bss_info_changed, 11870c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .get_tsf = rtl_op_get_tsf, 11880c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .set_tsf = rtl_op_set_tsf, 11890c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .reset_tsf = rtl_op_reset_tsf, 11900c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .sta_notify = rtl_op_sta_notify, 11910c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .ampdu_action = rtl_op_ampdu_action, 11920c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .sw_scan_start = rtl_op_sw_scan_start, 11930c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .sw_scan_complete = rtl_op_sw_scan_complete, 11940c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger .rfkill_poll = rtl_op_rfkill_poll, 11950baa0fd76f3f5a134461d6cf30294f6bb1bb824cChaoming_Li .flush = rtl_op_flush, 11960c8173385e549f95cd80c3fff5aab87b4f881d8dLarry Finger}; 1197