|
@@ -104,9 +104,12 @@ static void rtl_op_stop(struct ieee80211_hw *hw)
|
|
if (is_hal_stop(rtlhal))
|
|
if (is_hal_stop(rtlhal))
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ /* here is must, because adhoc do stop and start,
|
|
|
|
+ * but stop with RFOFF may cause something wrong,
|
|
|
|
+ * like adhoc TP
|
|
|
|
+ */
|
|
if (unlikely(ppsc->rfpwr_state == ERFOFF)) {
|
|
if (unlikely(ppsc->rfpwr_state == ERFOFF)) {
|
|
rtl_ips_nic_on(hw);
|
|
rtl_ips_nic_on(hw);
|
|
- mdelay(1);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
@@ -167,7 +170,11 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
|
rtl_ips_nic_on(hw);
|
|
rtl_ips_nic_on(hw);
|
|
|
|
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
- switch (vif->type) {
|
|
|
|
|
|
+
|
|
|
|
+ switch (ieee80211_vif_type_p2p(vif)) {
|
|
|
|
+ case NL80211_IFTYPE_P2P_CLIENT:
|
|
|
|
+ mac->p2p = P2P_ROLE_CLIENT;
|
|
|
|
+ /*fall through*/
|
|
case NL80211_IFTYPE_STATION:
|
|
case NL80211_IFTYPE_STATION:
|
|
if (mac->beacon_enabled == 1) {
|
|
if (mac->beacon_enabled == 1) {
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
@@ -192,6 +199,9 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
|
(u8 *) (&mac->basic_rates));
|
|
(u8 *) (&mac->basic_rates));
|
|
|
|
|
|
break;
|
|
break;
|
|
|
|
+ case NL80211_IFTYPE_P2P_GO:
|
|
|
|
+ mac->p2p = P2P_ROLE_GO;
|
|
|
|
+ /*fall through*/
|
|
case NL80211_IFTYPE_AP:
|
|
case NL80211_IFTYPE_AP:
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
"NL80211_IFTYPE_AP\n");
|
|
"NL80211_IFTYPE_AP\n");
|
|
@@ -205,6 +215,19 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
|
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
|
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
|
(u8 *) (&mac->basic_rates));
|
|
(u8 *) (&mac->basic_rates));
|
|
break;
|
|
break;
|
|
|
|
+ case NL80211_IFTYPE_MESH_POINT:
|
|
|
|
+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
|
|
+ "NL80211_IFTYPE_MESH_POINT\n");
|
|
|
|
+
|
|
|
|
+ mac->link_state = MAC80211_LINKED;
|
|
|
|
+ rtlpriv->cfg->ops->set_bcn_reg(hw);
|
|
|
|
+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
|
|
|
|
+ mac->basic_rates = 0xfff;
|
|
|
|
+ else
|
|
|
|
+ mac->basic_rates = 0xff0;
|
|
|
|
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
|
|
|
+ (u8 *)(&mac->basic_rates));
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
|
"operation mode %d is not supported!\n", vif->type);
|
|
"operation mode %d is not supported!\n", vif->type);
|
|
@@ -212,6 +235,13 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (mac->p2p) {
|
|
|
|
+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
|
|
+ "p2p role %x\n", vif->type);
|
|
|
|
+ mac->basic_rates = 0xff0;/*disable cck rate for p2p*/
|
|
|
|
+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
|
|
|
+ (u8 *)(&mac->basic_rates));
|
|
|
|
+ }
|
|
mac->vif = vif;
|
|
mac->vif = vif;
|
|
mac->opmode = vif->type;
|
|
mac->opmode = vif->type;
|
|
rtlpriv->cfg->ops->set_network_type(hw, vif->type);
|
|
rtlpriv->cfg->ops->set_network_type(hw, vif->type);
|
|
@@ -232,9 +262,9 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
|
|
|
|
/* Free beacon resources */
|
|
/* Free beacon resources */
|
|
- if ((mac->opmode == NL80211_IFTYPE_AP) ||
|
|
|
|
- (mac->opmode == NL80211_IFTYPE_ADHOC) ||
|
|
|
|
- (mac->opmode == NL80211_IFTYPE_MESH_POINT)) {
|
|
|
|
|
|
+ if ((vif->type == NL80211_IFTYPE_AP) ||
|
|
|
|
+ (vif->type == NL80211_IFTYPE_ADHOC) ||
|
|
|
|
+ (vif->type == NL80211_IFTYPE_MESH_POINT)) {
|
|
if (mac->beacon_enabled == 1) {
|
|
if (mac->beacon_enabled == 1) {
|
|
mac->beacon_enabled = 0;
|
|
mac->beacon_enabled = 0;
|
|
rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
|
|
rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
|
|
@@ -247,6 +277,7 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
|
|
*Note: We assume NL80211_IFTYPE_UNSPECIFIED as
|
|
*Note: We assume NL80211_IFTYPE_UNSPECIFIED as
|
|
*NO LINK for our hardware.
|
|
*NO LINK for our hardware.
|
|
*/
|
|
*/
|
|
|
|
+ mac->p2p = 0;
|
|
mac->vif = NULL;
|
|
mac->vif = NULL;
|
|
mac->link_state = MAC80211_NOLINK;
|
|
mac->link_state = MAC80211_NOLINK;
|
|
memset(mac->bssid, 0, 6);
|
|
memset(mac->bssid, 0, 6);
|
|
@@ -256,6 +287,22 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
|
|
mutex_unlock(&rtlpriv->locks.conf_mutex);
|
|
mutex_unlock(&rtlpriv->locks.conf_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int rtl_op_change_interface(struct ieee80211_hw *hw,
|
|
|
|
+ struct ieee80211_vif *vif,
|
|
|
|
+ enum nl80211_iftype new_type, bool p2p)
|
|
|
|
+{
|
|
|
|
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
|
|
+ int ret;
|
|
|
|
+ rtl_op_remove_interface(hw, vif);
|
|
|
|
+
|
|
|
|
+ vif->type = new_type;
|
|
|
|
+ vif->p2p = p2p;
|
|
|
|
+ ret = rtl_op_add_interface(hw, vif);
|
|
|
|
+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
|
|
+ "p2p %x\n", p2p);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
{
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
@@ -264,6 +311,9 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
|
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
|
struct ieee80211_conf *conf = &hw->conf;
|
|
struct ieee80211_conf *conf = &hw->conf;
|
|
|
|
|
|
|
|
+ if (mac->skip_scan)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
mutex_lock(&rtlpriv->locks.conf_mutex);
|
|
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/
|
|
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
|
@@ -323,6 +373,16 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
struct ieee80211_channel *channel = hw->conf.channel;
|
|
struct ieee80211_channel *channel = hw->conf.channel;
|
|
u8 wide_chan = (u8) channel->hw_value;
|
|
u8 wide_chan = (u8) channel->hw_value;
|
|
|
|
|
|
|
|
+ if (mac->act_scanning)
|
|
|
|
+ mac->n_channels++;
|
|
|
|
+
|
|
|
|
+ if (rtlpriv->dm.supp_phymode_switch &&
|
|
|
|
+ mac->link_state < MAC80211_LINKED &&
|
|
|
|
+ !mac->act_scanning) {
|
|
|
|
+ if (rtlpriv->cfg->ops->chk_switch_dmdp)
|
|
|
|
+ rtlpriv->cfg->ops->chk_switch_dmdp(hw);
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
*because we should back channel to
|
|
*because we should back channel to
|
|
*current_network.chan in in scanning,
|
|
*current_network.chan in in scanning,
|
|
@@ -373,13 +433,13 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
if (wide_chan <= 0)
|
|
if (wide_chan <= 0)
|
|
wide_chan = 1;
|
|
wide_chan = 1;
|
|
|
|
|
|
- /* In scanning, before we go offchannel we may send a ps=1 null
|
|
|
|
- * to AP, and then we may send a ps = 0 null to AP quickly, but
|
|
|
|
- * first null may have caused AP to put lots of packet to hw tx
|
|
|
|
- * buffer. These packets must be tx'd before we go off channel
|
|
|
|
- * so we must delay more time to let AP flush these packets
|
|
|
|
- * before going offchannel, or dis-association or delete BA will
|
|
|
|
- * happen by AP
|
|
|
|
|
|
+ /* In scanning, before we go offchannel we may send a ps = 1
|
|
|
|
+ * null to AP, and then we may send a ps = 0 null to AP quickly,
|
|
|
|
+ * but first null may have caused AP to put lots of packet to
|
|
|
|
+ * hw tx buffer. These packets must be tx'd before we go off
|
|
|
|
+ * channel so we must delay more time to let AP flush these
|
|
|
|
+ * packets before going offchannel, or dis-association or
|
|
|
|
+ * delete BA will be caused by AP
|
|
*/
|
|
*/
|
|
if (rtlpriv->mac80211.offchan_delay) {
|
|
if (rtlpriv->mac80211.offchan_delay) {
|
|
rtlpriv->mac80211.offchan_delay = false;
|
|
rtlpriv->mac80211.offchan_delay = false;
|
|
@@ -441,7 +501,8 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw,
|
|
* and nolink check bssid is set in set network_type */
|
|
* and nolink check bssid is set in set network_type */
|
|
if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) &&
|
|
if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) &&
|
|
(mac->link_state >= MAC80211_LINKED)) {
|
|
(mac->link_state >= MAC80211_LINKED)) {
|
|
- if (mac->opmode != NL80211_IFTYPE_AP) {
|
|
|
|
|
|
+ if (mac->opmode != NL80211_IFTYPE_AP &&
|
|
|
|
+ mac->opmode != NL80211_IFTYPE_MESH_POINT) {
|
|
if (*new_flags & FIF_BCN_PRBRESP_PROMISC) {
|
|
if (*new_flags & FIF_BCN_PRBRESP_PROMISC) {
|
|
rtlpriv->cfg->ops->set_chk_bssid(hw, false);
|
|
rtlpriv->cfg->ops->set_chk_bssid(hw, false);
|
|
} else {
|
|
} else {
|
|
@@ -481,32 +542,43 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
|
|
{
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
|
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
|
|
|
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
|
struct rtl_sta_info *sta_entry;
|
|
struct rtl_sta_info *sta_entry;
|
|
|
|
|
|
if (sta) {
|
|
if (sta) {
|
|
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
|
|
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
|
|
|
|
+ spin_lock_bh(&rtlpriv->locks.entry_list_lock);
|
|
|
|
+ list_add_tail(&sta_entry->list, &rtlpriv->entry_list);
|
|
|
|
+ spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
|
|
if (rtlhal->current_bandtype == BAND_ON_2_4G) {
|
|
if (rtlhal->current_bandtype == BAND_ON_2_4G) {
|
|
sta_entry->wireless_mode = WIRELESS_MODE_G;
|
|
sta_entry->wireless_mode = WIRELESS_MODE_G;
|
|
if (sta->supp_rates[0] <= 0xf)
|
|
if (sta->supp_rates[0] <= 0xf)
|
|
sta_entry->wireless_mode = WIRELESS_MODE_B;
|
|
sta_entry->wireless_mode = WIRELESS_MODE_B;
|
|
- if (sta->ht_cap.ht_supported)
|
|
|
|
|
|
+ if (sta->ht_cap.ht_supported == true)
|
|
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
|
|
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
|
|
|
|
+
|
|
|
|
+ if (vif->type == NL80211_IFTYPE_ADHOC)
|
|
|
|
+ sta_entry->wireless_mode = WIRELESS_MODE_G;
|
|
} else if (rtlhal->current_bandtype == BAND_ON_5G) {
|
|
} else if (rtlhal->current_bandtype == BAND_ON_5G) {
|
|
sta_entry->wireless_mode = WIRELESS_MODE_A;
|
|
sta_entry->wireless_mode = WIRELESS_MODE_A;
|
|
- if (sta->ht_cap.ht_supported)
|
|
|
|
|
|
+ if (sta->ht_cap.ht_supported == true)
|
|
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
|
|
sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
|
|
- }
|
|
|
|
|
|
|
|
- /* I found some times mac80211 give wrong supp_rates for adhoc*/
|
|
|
|
- if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
|
|
|
|
- sta_entry->wireless_mode = WIRELESS_MODE_G;
|
|
|
|
|
|
+ if (vif->type == NL80211_IFTYPE_ADHOC)
|
|
|
|
+ sta_entry->wireless_mode = WIRELESS_MODE_A;
|
|
|
|
+ }
|
|
|
|
+ /*disable cck rate for p2p*/
|
|
|
|
+ if (mac->p2p)
|
|
|
|
+ sta->supp_rates[0] &= 0xfffffff0;
|
|
|
|
|
|
|
|
+ memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN);
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
|
|
"Add sta addr is %pM\n", sta->addr);
|
|
"Add sta addr is %pM\n", sta->addr);
|
|
rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
|
|
rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
static int rtl_op_sta_remove(struct ieee80211_hw *hw,
|
|
static int rtl_op_sta_remove(struct ieee80211_hw *hw,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta)
|
|
struct ieee80211_sta *sta)
|
|
@@ -519,9 +591,14 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
|
|
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
|
|
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
|
|
sta_entry->wireless_mode = 0;
|
|
sta_entry->wireless_mode = 0;
|
|
sta_entry->ratr_index = 0;
|
|
sta_entry->ratr_index = 0;
|
|
|
|
+
|
|
|
|
+ spin_lock_bh(&rtlpriv->locks.entry_list_lock);
|
|
|
|
+ list_del(&sta_entry->list);
|
|
|
|
+ spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
static int _rtl_get_hal_qnum(u16 queue)
|
|
static int _rtl_get_hal_qnum(u16 queue)
|
|
{
|
|
{
|
|
int qnum;
|
|
int qnum;
|
|
@@ -547,8 +624,8 @@ static int _rtl_get_hal_qnum(u16 queue)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- *for mac80211 VO=0, VI=1, BE=2, BK=3
|
|
|
|
- *for rtl819x BE=0, BK=1, VI=2, VO=3
|
|
|
|
|
|
+ *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3
|
|
|
|
+ *for rtl819x BE = 0, BK = 1, VI = 2, VO = 3
|
|
*/
|
|
*/
|
|
static int rtl_op_conf_tx(struct ieee80211_hw *hw,
|
|
static int rtl_op_conf_tx(struct ieee80211_hw *hw,
|
|
struct ieee80211_vif *vif, u16 queue,
|
|
struct ieee80211_vif *vif, u16 queue,
|
|
@@ -630,6 +707,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
/*TODO: reference to enum ieee80211_bss_change */
|
|
/*TODO: reference to enum ieee80211_bss_change */
|
|
if (changed & BSS_CHANGED_ASSOC) {
|
|
if (changed & BSS_CHANGED_ASSOC) {
|
|
if (bss_conf->assoc) {
|
|
if (bss_conf->assoc) {
|
|
|
|
+ struct ieee80211_sta *sta = NULL;
|
|
/* we should reset all sec info & cam
|
|
/* we should reset all sec info & cam
|
|
* before set cam after linked, we should not
|
|
* before set cam after linked, we should not
|
|
* reset in disassoc, that will cause tkip->wep
|
|
* reset in disassoc, that will cause tkip->wep
|
|
@@ -647,23 +725,37 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
|
|
|
|
if (rtlpriv->cfg->ops->linked_set_reg)
|
|
if (rtlpriv->cfg->ops->linked_set_reg)
|
|
rtlpriv->cfg->ops->linked_set_reg(hw);
|
|
rtlpriv->cfg->ops->linked_set_reg(hw);
|
|
- if (mac->opmode == NL80211_IFTYPE_STATION && sta)
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+ sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
|
|
|
|
+
|
|
|
|
+ if (vif->type == NL80211_IFTYPE_STATION && sta)
|
|
rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
|
|
rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
|
|
|
|
+ RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD,
|
|
|
|
+ "send PS STATIC frame\n");
|
|
|
|
+ if (rtlpriv->dm.supp_phymode_switch) {
|
|
|
|
+ if (sta->ht_cap.ht_supported)
|
|
|
|
+ rtl_send_smps_action(hw, sta,
|
|
|
|
+ IEEE80211_SMPS_STATIC);
|
|
|
|
+ }
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
|
|
"BSS_CHANGED_ASSOC\n");
|
|
"BSS_CHANGED_ASSOC\n");
|
|
} else {
|
|
} else {
|
|
if (mac->link_state == MAC80211_LINKED)
|
|
if (mac->link_state == MAC80211_LINKED)
|
|
- rtl_lps_leave(hw);
|
|
|
|
|
|
+ schedule_work(&rtlpriv->works.lps_leave_work);
|
|
|
|
|
|
|
|
+ if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
|
|
|
|
+ rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
|
|
mac->link_state = MAC80211_NOLINK;
|
|
mac->link_state = MAC80211_NOLINK;
|
|
memset(mac->bssid, 0, 6);
|
|
memset(mac->bssid, 0, 6);
|
|
-
|
|
|
|
- /* reset sec info */
|
|
|
|
- rtl_cam_reset_sec_info(hw);
|
|
|
|
-
|
|
|
|
- rtl_cam_reset_all_entry(hw);
|
|
|
|
mac->vendor = PEER_UNKNOWN;
|
|
mac->vendor = PEER_UNKNOWN;
|
|
|
|
|
|
|
|
+ if (rtlpriv->dm.supp_phymode_switch) {
|
|
|
|
+ if (rtlpriv->cfg->ops->chk_switch_dmdp)
|
|
|
|
+ rtlpriv->cfg->ops->chk_switch_dmdp(hw);
|
|
|
|
+ }
|
|
|
|
+
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
|
|
"BSS_CHANGED_UN_ASSOC\n");
|
|
"BSS_CHANGED_UN_ASSOC\n");
|
|
}
|
|
}
|
|
@@ -778,7 +870,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
}
|
|
}
|
|
|
|
|
|
if (changed & BSS_CHANGED_BASIC_RATES) {
|
|
if (changed & BSS_CHANGED_BASIC_RATES) {
|
|
- /* for 5G must << RATE_6M_INDEX=4,
|
|
|
|
|
|
+ /* for 5G must << RATE_6M_INDEX = 4,
|
|
* because 5G have no cck rate*/
|
|
* because 5G have no cck rate*/
|
|
if (rtlhal->current_bandtype == BAND_ON_5G)
|
|
if (rtlhal->current_bandtype == BAND_ON_5G)
|
|
basic_rates = sta->supp_rates[1] << 4;
|
|
basic_rates = sta->supp_rates[1] << 4;
|
|
@@ -815,6 +907,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
ppsc->report_linked = false;
|
|
ppsc->report_linked = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ if (rtlpriv->cfg->ops->bt_wifi_media_status_notify)
|
|
|
|
+ rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw,
|
|
|
|
+ ppsc->report_linked);
|
|
}
|
|
}
|
|
|
|
|
|
out:
|
|
out:
|
|
@@ -885,7 +980,6 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
"IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
|
|
"IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
|
|
return rtl_tx_agg_stop(hw, sta, tid);
|
|
return rtl_tx_agg_stop(hw, sta, tid);
|
|
- break;
|
|
|
|
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
|
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
"IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
|
|
"IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
|
|
@@ -894,11 +988,11 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
|
|
case IEEE80211_AMPDU_RX_START:
|
|
case IEEE80211_AMPDU_RX_START:
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
"IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
|
|
"IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
|
|
- break;
|
|
|
|
|
|
+ return rtl_rx_agg_start(hw, sta, tid);
|
|
case IEEE80211_AMPDU_RX_STOP:
|
|
case IEEE80211_AMPDU_RX_STOP:
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
|
|
"IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
|
|
"IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
|
|
- break;
|
|
|
|
|
|
+ return rtl_rx_agg_stop(hw, sta, tid);
|
|
default:
|
|
default:
|
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
|
"IEEE80211_AMPDU_ERR!!!!:\n");
|
|
"IEEE80211_AMPDU_ERR!!!!:\n");
|
|
@@ -912,12 +1006,19 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
|
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
|
|
|
|
|
- mac->act_scanning = true;
|
|
|
|
-
|
|
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
|
|
|
|
+ mac->act_scanning = true;
|
|
|
|
+ if (rtlpriv->link_info.higher_busytraffic) {
|
|
|
|
+ mac->skip_scan = true;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ if (rtlpriv->dm.supp_phymode_switch) {
|
|
|
|
+ if (rtlpriv->cfg->ops->chk_switch_dmdp)
|
|
|
|
+ rtlpriv->cfg->ops->chk_switch_dmdp(hw);
|
|
|
|
+ }
|
|
if (mac->link_state == MAC80211_LINKED) {
|
|
if (mac->link_state == MAC80211_LINKED) {
|
|
- rtl_lps_leave(hw);
|
|
|
|
|
|
+ schedule_work(&rtlpriv->works.lps_leave_work);
|
|
mac->link_state = MAC80211_LINKED_SCANNING;
|
|
mac->link_state = MAC80211_LINKED_SCANNING;
|
|
} else {
|
|
} else {
|
|
rtl_ips_nic_on(hw);
|
|
rtl_ips_nic_on(hw);
|
|
@@ -937,6 +1038,16 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
|
|
|
|
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
|
|
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
|
|
mac->act_scanning = false;
|
|
mac->act_scanning = false;
|
|
|
|
+ mac->skip_scan = false;
|
|
|
|
+ if (rtlpriv->link_info.higher_busytraffic)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /*p2p will use 1/6/11 to scan */
|
|
|
|
+ if (mac->n_channels == 3)
|
|
|
|
+ mac->p2p_in_use = true;
|
|
|
|
+ else
|
|
|
|
+ mac->p2p_in_use = false;
|
|
|
|
+ mac->n_channels = 0;
|
|
/* Dual mac */
|
|
/* Dual mac */
|
|
rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false;
|
|
rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false;
|
|
|
|
|
|
@@ -970,6 +1081,11 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
"not open hw encryption\n");
|
|
"not open hw encryption\n");
|
|
return -ENOSPC; /*User disabled HW-crypto */
|
|
return -ENOSPC; /*User disabled HW-crypto */
|
|
}
|
|
}
|
|
|
|
+ /* To support IBSS, use sw-crypto for GTK */
|
|
|
|
+ if (((vif->type == NL80211_IFTYPE_ADHOC) ||
|
|
|
|
+ (vif->type == NL80211_IFTYPE_MESH_POINT)) &&
|
|
|
|
+ !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
|
|
|
+ return -ENOSPC;
|
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
|
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
|
|
"%s hardware based encryption for keyidx: %d, mac: %pM\n",
|
|
"%s hardware based encryption for keyidx: %d, mac: %pM\n",
|
|
cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
|
|
cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
|
|
@@ -996,6 +1112,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
key_type = AESCCMP_ENCRYPTION;
|
|
key_type = AESCCMP_ENCRYPTION;
|
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
|
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
|
|
break;
|
|
break;
|
|
|
|
+ case WLAN_CIPHER_SUITE_AES_CMAC:
|
|
|
|
+ /*HW doesn't support CMAC encryption, use software CMAC */
|
|
|
|
+ key_type = AESCMAC_ENCRYPTION;
|
|
|
|
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n");
|
|
|
|
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
|
|
|
|
+ "HW don't support CMAC encryption, use software CMAC\n");
|
|
|
|
+ err = -EOPNOTSUPP;
|
|
|
|
+ goto out_unlock;
|
|
default:
|
|
default:
|
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n",
|
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n",
|
|
key->cipher);
|
|
key->cipher);
|
|
@@ -1017,13 +1141,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
* 1) wep only: is just for wep enc, in this condition
|
|
* 1) wep only: is just for wep enc, in this condition
|
|
* rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION
|
|
* rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION
|
|
* will be true & enable_hw_sec will be set when wep
|
|
* will be true & enable_hw_sec will be set when wep
|
|
- * ke setting.
|
|
|
|
|
|
+ * key setting.
|
|
* 2) wep(group) + AES(pairwise): some AP like cisco
|
|
* 2) wep(group) + AES(pairwise): some AP like cisco
|
|
* may use it, in this condition enable_hw_sec will not
|
|
* may use it, in this condition enable_hw_sec will not
|
|
* be set when wep key setting */
|
|
* be set when wep key setting */
|
|
/* we must reset sec_info after lingked before set key,
|
|
/* we must reset sec_info after lingked before set key,
|
|
* or some flag will be wrong*/
|
|
* or some flag will be wrong*/
|
|
- if (mac->opmode == NL80211_IFTYPE_AP) {
|
|
|
|
|
|
+ if (vif->type == NL80211_IFTYPE_AP ||
|
|
|
|
+ vif->type == NL80211_IFTYPE_MESH_POINT) {
|
|
if (!group_key || key_type == WEP40_ENCRYPTION ||
|
|
if (!group_key || key_type == WEP40_ENCRYPTION ||
|
|
key_type == WEP104_ENCRYPTION) {
|
|
key_type == WEP104_ENCRYPTION) {
|
|
if (group_key)
|
|
if (group_key)
|
|
@@ -1098,12 +1223,16 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
key->hw_key_idx = key_idx;
|
|
key->hw_key_idx = key_idx;
|
|
if (key_type == TKIP_ENCRYPTION)
|
|
if (key_type == TKIP_ENCRYPTION)
|
|
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
|
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
|
|
|
+ /*use software CCMP encryption for management frames (MFP) */
|
|
|
|
+ if (key_type == AESCCMP_ENCRYPTION)
|
|
|
|
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
|
|
break;
|
|
break;
|
|
case DISABLE_KEY:
|
|
case DISABLE_KEY:
|
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
|
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
|
|
"disable key delete one entry\n");
|
|
"disable key delete one entry\n");
|
|
/*set local buf about wep key. */
|
|
/*set local buf about wep key. */
|
|
- if (mac->opmode == NL80211_IFTYPE_AP) {
|
|
|
|
|
|
+ if (vif->type == NL80211_IFTYPE_AP ||
|
|
|
|
+ vif->type == NL80211_IFTYPE_MESH_POINT) {
|
|
if (sta)
|
|
if (sta)
|
|
rtl_cam_del_entry(hw, sta->addr);
|
|
rtl_cam_del_entry(hw, sta->addr);
|
|
}
|
|
}
|
|
@@ -1163,7 +1292,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
|
|
}
|
|
}
|
|
|
|
|
|
/* this function is called by mac80211 to flush tx buffer
|
|
/* this function is called by mac80211 to flush tx buffer
|
|
- * before switch channle or power save, or tx buffer packet
|
|
|
|
|
|
+ * before switch channel or power save, or tx buffer packet
|
|
* maybe send after offchannel or rf sleep, this may cause
|
|
* maybe send after offchannel or rf sleep, this may cause
|
|
* dis-association by AP */
|
|
* dis-association by AP */
|
|
static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
|
static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
|
@@ -1180,6 +1309,7 @@ const struct ieee80211_ops rtl_ops = {
|
|
.tx = rtl_op_tx,
|
|
.tx = rtl_op_tx,
|
|
.add_interface = rtl_op_add_interface,
|
|
.add_interface = rtl_op_add_interface,
|
|
.remove_interface = rtl_op_remove_interface,
|
|
.remove_interface = rtl_op_remove_interface,
|
|
|
|
+ .change_interface = rtl_op_change_interface,
|
|
.config = rtl_op_config,
|
|
.config = rtl_op_config,
|
|
.configure_filter = rtl_op_configure_filter,
|
|
.configure_filter = rtl_op_configure_filter,
|
|
.sta_add = rtl_op_sta_add,
|
|
.sta_add = rtl_op_sta_add,
|