diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-05-05 13:32:35 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-05 13:32:35 -0400 |
commit | a70171dce9cd44cb06c7d299eba9fa87a8933045 (patch) | |
tree | 5425df5f33fadc617c7dec99578d06f0d933578e /drivers/net/wireless/rtlwifi | |
parent | 5a412ad7f4c95bb5b756aa12b52646e857e7c75d (diff) | |
parent | eaef6a93bd52a2cc47b9fce201310010707afdb4 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/rtlwifi/pci.c
net/bluetooth/l2cap_sock.c
Diffstat (limited to 'drivers/net/wireless/rtlwifi')
50 files changed, 3420 insertions, 1587 deletions
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index b259f807ad2..ccb6da38fe2 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -50,8 +50,9 @@ *3) functions called by core.c *4) wq & timer callback functions *5) frame process functions - *6) sysfs functions - *7) ... + *6) IOT functions + *7) sysfs functions + *8) ... */ /********************************************************* @@ -59,7 +60,7 @@ * mac80211 init functions * *********************************************************/ -static struct ieee80211_channel rtl_channeltable[] = { +static struct ieee80211_channel rtl_channeltable_2g[] = { {.center_freq = 2412, .hw_value = 1,}, {.center_freq = 2417, .hw_value = 2,}, {.center_freq = 2422, .hw_value = 3,}, @@ -76,7 +77,34 @@ static struct ieee80211_channel rtl_channeltable[] = { {.center_freq = 2484, .hw_value = 14,}, }; -static struct ieee80211_rate rtl_ratetable[] = { +static struct ieee80211_channel rtl_channeltable_5g[] = { + {.center_freq = 5180, .hw_value = 36,}, + {.center_freq = 5200, .hw_value = 40,}, + {.center_freq = 5220, .hw_value = 44,}, + {.center_freq = 5240, .hw_value = 48,}, + {.center_freq = 5260, .hw_value = 52,}, + {.center_freq = 5280, .hw_value = 56,}, + {.center_freq = 5300, .hw_value = 60,}, + {.center_freq = 5320, .hw_value = 64,}, + {.center_freq = 5500, .hw_value = 100,}, + {.center_freq = 5520, .hw_value = 104,}, + {.center_freq = 5540, .hw_value = 108,}, + {.center_freq = 5560, .hw_value = 112,}, + {.center_freq = 5580, .hw_value = 116,}, + {.center_freq = 5600, .hw_value = 120,}, + {.center_freq = 5620, .hw_value = 124,}, + {.center_freq = 5640, .hw_value = 128,}, + {.center_freq = 5660, .hw_value = 132,}, + {.center_freq = 5680, .hw_value = 136,}, + {.center_freq = 5700, .hw_value = 140,}, + {.center_freq = 5745, .hw_value = 149,}, + {.center_freq = 5765, .hw_value = 153,}, + {.center_freq = 5785, .hw_value = 157,}, + {.center_freq = 5805, .hw_value = 161,}, + {.center_freq = 5825, .hw_value = 165,}, +}; + +static struct ieee80211_rate rtl_ratetable_2g[] = { {.bitrate = 10, .hw_value = 0x00,}, {.bitrate = 20, .hw_value = 0x01,}, {.bitrate = 55, .hw_value = 0x02,}, @@ -91,18 +119,57 @@ static struct ieee80211_rate rtl_ratetable[] = { {.bitrate = 540, .hw_value = 0x0b,}, }; +static struct ieee80211_rate rtl_ratetable_5g[] = { + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + static const struct ieee80211_supported_band rtl_band_2ghz = { .band = IEEE80211_BAND_2GHZ, - .channels = rtl_channeltable, - .n_channels = ARRAY_SIZE(rtl_channeltable), + .channels = rtl_channeltable_2g, + .n_channels = ARRAY_SIZE(rtl_channeltable_2g), + + .bitrates = rtl_ratetable_2g, + .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), + + .ht_cap = {0}, +}; + +static struct ieee80211_supported_band rtl_band_5ghz = { + .band = IEEE80211_BAND_5GHZ, + + .channels = rtl_channeltable_5g, + .n_channels = ARRAY_SIZE(rtl_channeltable_5g), - .bitrates = rtl_ratetable, - .n_bitrates = ARRAY_SIZE(rtl_ratetable), + .bitrates = rtl_ratetable_5g, + .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), .ht_cap = {0}, }; +static const u8 tid_to_ac[] = { + 2, /* IEEE80211_AC_BE */ + 3, /* IEEE80211_AC_BK */ + 3, /* IEEE80211_AC_BK */ + 2, /* IEEE80211_AC_BE */ + 1, /* IEEE80211_AC_VI */ + 1, /* IEEE80211_AC_VI */ + 0, /* IEEE80211_AC_VO */ + 0, /* IEEE80211_AC_VO */ +}; + +u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid) +{ + return tid_to_ac[tid]; +} + static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, struct ieee80211_sta_ht_cap *ht_cap) { @@ -115,6 +182,9 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; + if (rtlpriv->rtlhal.disable_amsdu_8k) + ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; + /* *Maximum length of AMPDU that the STA can receive. *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) @@ -159,37 +229,99 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, static void _rtl_init_mac80211(struct ieee80211_hw *hw) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - /* - * <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] - * to default value(1T1R) - */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, - sizeof(struct ieee80211_supported_band)); + if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == + BAND_ON_BOTH) { + /* 1: 2.4 G bands */ + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + + /* 2: 5 G bands */ + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } else { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), + &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), + &rtl_band_5ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + ("Err BAND %d\n", + rtlhal->current_bandtype)); + } + } /* <5> set hw caps */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/ - /*IEEE80211_HW_SUPPORTS_PS | */ - /*IEEE80211_HW_PS_NULLFUNC_STACK | */ - /*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ + IEEE80211_HW_BEACON_FILTER | + IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; + /* swlps or hwlps has been set in diff chip in init_sw_vars */ + if (rtlpriv->psc.swctrl_lps) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + /* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ + 0; + hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; @@ -199,9 +331,10 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) /* TODO: Correct this value for our hw */ /* TODO: define these hard code value */ hw->channel_change_time = 100; - hw->max_listen_interval = 5; + hw->max_listen_interval = 10; hw->max_rate_tries = 4; /* hw->max_rates = 1; */ + hw->sta_data_size = sizeof(struct rtl_sta_info); /* <6> mac address */ if (is_valid_ether_addr(rtlefuse->dev_addr)) { @@ -230,6 +363,10 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, (void *)rtl_ips_nic_off_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ps_work, + (void *)rtl_swlps_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, + (void *)rtl_swlps_rfon_wq_callback); } @@ -241,6 +378,8 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) cancel_delayed_work(&rtlpriv->works.watchdog_wq); cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); + cancel_delayed_work(&rtlpriv->works.ps_work); + cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); } void rtl_init_rfkill(struct ieee80211_hw *hw) @@ -310,6 +449,8 @@ int rtl_init_core(struct ieee80211_hw *hw) spin_lock_init(&rtlpriv->locks.rf_ps_lock); spin_lock_init(&rtlpriv->locks.rf_lock); spin_lock_init(&rtlpriv->locks.lps_lock); + spin_lock_init(&rtlpriv->locks.waitq_lock); + spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); rtlmac->link_state = MAC80211_NOLINK; @@ -329,12 +470,6 @@ void rtl_init_rx_config(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MGT_FILTER, - (u8 *) (&mac->rx_mgt_filter)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CTRL_FILTER, - (u8 *) (&mac->rx_ctrl_filter)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_DATA_FILTER, - (u8 *) (&mac->rx_data_filter)); } /********************************************************* @@ -361,28 +496,40 @@ static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, } static void _rtl_query_shortgi(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc, struct ieee80211_tx_info *info) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u8 rate_flag = info->control.rates[0].flags; - + u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; tcb_desc->use_shortgi = false; - if (!mac->ht_enable) + if (sta == NULL) return; - if (!mac->sgi_40 && !mac->sgi_20) + sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + + if (!(sta->ht_cap.ht_supported)) + return; + + if (!sgi_40 && !sgi_20) return; - if ((mac->bw_40 == true) && mac->sgi_40) + if (mac->opmode == NL80211_IFTYPE_STATION) + bw_40 = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + if ((bw_40 == true) && sgi_40) tcb_desc->use_shortgi = true; - else if ((mac->bw_40 == false) && mac->sgi_20) + else if ((bw_40 == false) && sgi_20) tcb_desc->use_shortgi = true; if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) tcb_desc->use_shortgi = false; - } static void _rtl_query_protection_mode(struct ieee80211_hw *hw, @@ -410,19 +557,25 @@ static void _rtl_query_protection_mode(struct ieee80211_hw *hw, tcb_desc->rts_enable = true; tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; } - } static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u8 ratr_index = 7; + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + ratr_index = sta_entry->ratr_index; + } if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { - if (mac->opmode == NL80211_IFTYPE_STATION) + if (mac->opmode == NL80211_IFTYPE_STATION) { tcb_desc->ratr_index = 0; - else if (mac->opmode == NL80211_IFTYPE_ADHOC) { + } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { if (tcb_desc->multicast || tcb_desc->broadcast) { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; @@ -430,36 +583,61 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, } else { /* TODO */ } + tcb_desc->ratr_index = ratr_index; + } else if (mac->opmode == NL80211_IFTYPE_AP) { + tcb_desc->ratr_index = ratr_index; } } if (rtlpriv->dm.useramask) { - /* TODO adhoc and station handled differently in the future */ - tcb_desc->mac_id = 0; - - if ((mac->mode == WIRELESS_MODE_N_24G) || - (mac->mode == WIRELESS_MODE_N_5G)) { - tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; - } else if (mac->mode & WIRELESS_MODE_G) { - tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; - } else if (mac->mode & WIRELESS_MODE_B) { - tcb_desc->ratr_index = RATR_INX_WIRELESS_B; + /* TODO we will differentiate adhoc and station futrue */ + if (mac->opmode == NL80211_IFTYPE_STATION) { + tcb_desc->mac_id = 0; + + if (mac->mode == WIRELESS_MODE_N_24G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; + else if (mac->mode == WIRELESS_MODE_N_5G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_NG; + else if (mac->mode & WIRELESS_MODE_G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; + else if (mac->mode & WIRELESS_MODE_B) + tcb_desc->ratr_index = RATR_INX_WIRELESS_B; + else if (mac->mode & WIRELESS_MODE_A) + tcb_desc->ratr_index = RATR_INX_WIRELESS_G; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (NULL != sta) { + if (sta->aid > 0) + tcb_desc->mac_id = sta->aid + 1; + else + tcb_desc->mac_id = 1; + } else { + tcb_desc->mac_id = 0; + } } } } static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); tcb_desc->packet_bw = false; - - if (!mac->bw_40 || !mac->ht_enable) + if (!sta) return; - + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (!(sta->ht_cap.ht_supported) || + !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + return; + } else if (mac->opmode == NL80211_IFTYPE_STATION) { + if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) + return; + } if (tcb_desc->multicast || tcb_desc->broadcast) return; @@ -486,22 +664,21 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw) void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct ieee80211_rate *txrate; __le16 fc = hdr->frame_control; - memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + txrate = ieee80211_get_tx_rate(hw, info); + tcb_desc->hw_rate = txrate->hw_value; if (ieee80211_is_data(fc)) { - txrate = ieee80211_get_tx_rate(hw, info); - tcb_desc->hw_rate = txrate->hw_value; - /* - *we set data rate RTL_RC_CCK_RATE1M + *we set data rate INX 0 *in rtl_rc.c if skb is special data or *mgt which need low data rate. */ @@ -510,12 +687,11 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *So tcb_desc->hw_rate is just used for *special data and mgt frames */ - if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) { + if (info->control.rates[0].idx == 0 && + ieee80211_is_nullfunc(fc)) { tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = 7; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - tcb_desc->hw_rate = - rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; tcb_desc->disable_ratefallback = 1; } else { /* @@ -525,7 +701,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *and N rate will all be controlled by FW *when tcb_desc->use_driver_rate = false */ - if (rtlmac->ht_enable) { + if (sta && (sta->ht_cap.ht_supported)) { tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); } else { if (rtlmac->mode == WIRELESS_MODE_B) { @@ -543,43 +719,25 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->broadcast = 1; - _rtl_txrate_selectmode(hw, tcb_desc); - _rtl_query_bandwidth_mode(hw, tcb_desc); + _rtl_txrate_selectmode(hw, sta, tcb_desc); + _rtl_query_bandwidth_mode(hw, sta, tcb_desc); _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); - _rtl_query_shortgi(hw, tcb_desc, info); + _rtl_query_shortgi(hw, sta, tcb_desc, info); _rtl_query_protection_mode(hw, tcb_desc, info); } else { tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = 7; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; tcb_desc->disable_ratefallback = 1; tcb_desc->mac_id = 0; - - tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + tcb_desc->packet_bw = false; } } EXPORT_SYMBOL(rtl_get_tcb_desc); -bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - if (ieee80211_is_auth(fc)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); - rtl_ips_nic_on(hw); - - mac->link_state = MAC80211_LINKING; - } - - return true; -} - bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct rtl_priv *rtlpriv = rtl_priv(hw); __le16 fc = hdr->frame_control; u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN)); @@ -624,9 +782,8 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - __le16 fc = hdr->frame_control; + __le16 fc = rtl_get_fc(skb); u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; @@ -634,12 +791,11 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) if (!ieee80211_is_data(fc)) return false; - if (ieee80211_is_nullfunc(fc)) - return true; ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); + /* ether_type = ntohs(ether_type); */ if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { @@ -696,61 +852,92 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) * functions called by core.c * *********************************************************/ -int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn) +int rtl_tx_agg_start(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_tid_data *tid_data; struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("on ra = %pM tid = %d\n", ra, tid)); + if (sta == NULL) + return -EINVAL; if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - if (mac->tids[tid].agg.agg_state != RTL_AGG_OFF) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Start AGG when state is not RTL_AGG_OFF !\n")); + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + if (!sta_entry) return -ENXIO; - } - - tid_data = &mac->tids[tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); + tid_data = &sta_entry->tids[tid]; RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("HW queue is empty tid:%d\n", tid)); - tid_data->agg.agg_state = RTL_AGG_ON; + ("on ra = %pM tid = %d seq:%d\n", sta->addr, tid, + tid_data->seq_number)); + + *ssn = tid_data->seq_number; + tid_data->agg.agg_state = RTL_AGG_START; - ieee80211_start_tx_ba_cb_irqsafe(mac->vif, ra, tid); + ieee80211_start_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); return 0; } -int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 * ra, u16 tid) +int rtl_tx_agg_stop(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) { - int ssn = -1; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; - if (!ra) { + if (sta == NULL) + return -EINVAL; + + if (!sta->addr) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); return -EINVAL; } + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("on ra = %pM tid = %d\n", sta->addr, tid)); + if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - if (mac->tids[tid].agg.agg_state != RTL_AGG_ON) - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Stopping AGG while state not ON or starting\n")); + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + tid_data = &sta_entry->tids[tid]; + sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; + + ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); + + return 0; +} + +int rtl_tx_agg_oper(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; + + if (!sta->addr) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); + return -EINVAL; + } - tid_data = &mac->tids[tid]; - ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("on ra = %pM tid = %d\n", sta->addr, tid)); - mac->tids[tid].agg.agg_state = RTL_AGG_OFF; + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; - ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, ra, tid); + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + tid_data = &sta_entry->tids[tid]; + sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; return 0; } @@ -769,18 +956,16 @@ void rtl_watchdog_wq_callback(void *data) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - bool busytraffic = false; bool higher_busytraffic = false; bool higher_busyrxtraffic = false; - bool higher_busytxtraffic = false; - - u8 idx = 0; + u8 idx, tid; u32 rx_cnt_inp4eriod = 0; u32 tx_cnt_inp4eriod = 0; u32 aver_rx_cnt_inperiod = 0; u32 aver_tx_cnt_inperiod = 0; - + u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; + u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; bool enter_ps = false; if (is_hal_stop(rtlhal)) @@ -794,9 +979,6 @@ void rtl_watchdog_wq_callback(void *data) mac->cnt_after_linked = 0; } - /* <2> DM */ - rtlpriv->cfg->ops->dm_watchdog(hw); - /* *<3> to check if traffic busy, if * busytraffic we don't change channel @@ -835,8 +1017,27 @@ void rtl_watchdog_wq_callback(void *data) /* Extremely high Rx data. */ if (aver_rx_cnt_inperiod > 5000) higher_busyrxtraffic = true; + } + + /* check every tid's tx traffic */ + for (tid = 0; tid <= 7; tid++) { + for (idx = 0; idx <= 2; idx++) + rtlpriv->link_info.tidtx_in4period[tid][idx] = + rtlpriv->link_info.tidtx_in4period[tid] + [idx + 1]; + rtlpriv->link_info.tidtx_in4period[tid][3] = + rtlpriv->link_info.tidtx_inperiod[tid]; + + for (idx = 0; idx <= 3; idx++) + tidtx_inp4eriod[tid] += + rtlpriv->link_info.tidtx_in4period[tid][idx]; + aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; + if (aver_tidtx_inperiod[tid] > 5000) + rtlpriv->link_info.higher_busytxtraffic[tid] = + true; else - higher_busytxtraffic = false; + rtlpriv->link_info.higher_busytxtraffic[tid] = + false; } if (((rtlpriv->link_info.num_rx_inperiod + @@ -855,11 +1056,15 @@ void rtl_watchdog_wq_callback(void *data) rtlpriv->link_info.num_rx_inperiod = 0; rtlpriv->link_info.num_tx_inperiod = 0; + for (tid = 0; tid <= 7; tid++) + rtlpriv->link_info.tidtx_inperiod[tid] = 0; rtlpriv->link_info.busytraffic = busytraffic; rtlpriv->link_info.higher_busytraffic = higher_busytraffic; rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; + /* <3> DM */ + rtlpriv->cfg->ops->dm_watchdog(hw); } void rtl_watch_dog_timer_callback(unsigned long data) @@ -876,6 +1081,268 @@ void rtl_watch_dog_timer_callback(unsigned long data) /********************************************************* * + * frame process functions + * + *********************************************************/ +u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos + 2 + pos[1] > end) + return NULL; + + if (pos[0] == ie) + return pos; + + pos += 2 + pos[1]; + } + return NULL; +} + +/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ +/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ +static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, + enum ieee80211_smps_mode smps, u8 *da, u8 *bssid) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct sk_buff *skb; + struct ieee80211_mgmt *action_frame; + + /* 27 = header + category + action + smps mode */ + skb = dev_alloc_skb(27 + hw->extra_tx_headroom); + if (!skb) + return NULL; + + skb_reserve(skb, hw->extra_tx_headroom); + action_frame = (void *)skb_put(skb, 27); + memset(action_frame, 0, 27); + memcpy(action_frame->da, da, ETH_ALEN); + memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); + memcpy(action_frame->bssid, bssid, ETH_ALEN); + action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + action_frame->u.action.category = WLAN_CATEGORY_HT; + action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; + switch (smps) { + case IEEE80211_SMPS_AUTOMATIC:/* 0 */ + case IEEE80211_SMPS_NUM_MODES:/* 4 */ + WARN_ON(1); + case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ + break; + case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ + break; + case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ + break; + } + + return skb; +} + +int rtl_send_smps_action(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 *da, u8 *bssid, + enum ieee80211_smps_mode smps) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + if (rtlpriv->mac80211.act_scanning) + goto err_free; + + if (!sta) + goto err_free; + + if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) + goto err_free; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + goto err_free; + + /* this is a type = mgmt * stype = action frame */ + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl_sta_info *sta_entry = + (struct rtl_sta_info *) sta->drv_priv; + sta_entry->mimo_ps = smps; + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); + + info->control.rates[0].idx = 0; + info->control.sta = sta; + info->band = hw->conf.channel->band; + rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); + } +err_free: + return 0; +} + +/********************************************************* + * + * IOT functions + * + *********************************************************/ +static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, + struct octet_string vendor_ie) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool matched = false; + static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; + static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; + static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; + static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; + static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; + static u8 racap[] = { 0x00, 0x0c, 0x43 }; + static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; + static u8 marvcap[] = { 0x00, 0x50, 0x43 }; + + if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || + memcmp(vendor_ie.octet, athcap_2, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_ATH; + matched = true; + } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || + memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || + memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_BROAD; + matched = true; + } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_RAL; + matched = true; + } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_CISCO; + matched = true; + } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_MARV; + matched = true; + } + + return matched; +} + +static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, + unsigned int len) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + struct octet_string vendor_ie; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos[0] == 221) { + vendor_ie.length = pos[1]; + vendor_ie.octet = &pos[2]; + if (rtl_chk_vendor_ouisub(hw, vendor_ie)) + return true; + } + + if (pos + 2 + pos[1] > end) + return false; + + pos += 2 + pos[1]; + } + return false; +} + +void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (void *)data; + u32 vendor = PEER_UNKNOWN; + + static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; + static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; + static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; + static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; + static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; + static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; + static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; + static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; + static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; + static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; + static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; + static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; + static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; + static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; + static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; + static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (mac->link_state == MAC80211_NOLINK) { + mac->vendor = PEER_UNKNOWN; + return; + } + + if (mac->cnt_after_linked > 2) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + if (rtl_find_221_ie(hw, data, len)) + vendor = mac->vendor; + + if ((memcmp(mac->bssid, ap5_1, 3) == 0) || + (memcmp(mac->bssid, ap5_2, 3) == 0) || + (memcmp(mac->bssid, ap5_3, 3) == 0) || + (memcmp(mac->bssid, ap5_4, 3) == 0) || + (memcmp(mac->bssid, ap5_5, 3) == 0) || + (memcmp(mac->bssid, ap5_6, 3) == 0) || + vendor == PEER_ATH) { + vendor = PEER_ATH; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ath find\n")); + } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || + (memcmp(mac->bssid, ap4_5, 3) == 0) || + (memcmp(mac->bssid, ap4_1, 3) == 0) || + (memcmp(mac->bssid, ap4_2, 3) == 0) || + (memcmp(mac->bssid, ap4_3, 3) == 0) || + vendor == PEER_RAL) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ral findn\n")); + vendor = PEER_RAL; + } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || + vendor == PEER_CISCO) { + vendor = PEER_CISCO; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>cisco find\n")); + } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || + (memcmp(mac->bssid, ap3_2, 3) == 0) || + (memcmp(mac->bssid, ap3_3, 3) == 0) || + vendor == PEER_BROAD) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>broad find\n")); + vendor = PEER_BROAD; + } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || + vendor == PEER_MARV) { + vendor = PEER_MARV; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>marv find\n")); + } + + mac->vendor = vendor; +} + +/********************************************************* + * * sysfs functions * *********************************************************/ @@ -941,12 +1408,13 @@ static int __init rtl_core_module_init(void) if (rtl_rate_control_register()) printk(KERN_ERR "rtlwifi: Unable to register rtl_rc," "use default RC !!\n"); + return 0; } static void __exit rtl_core_module_exit(void) { - /*RC*/ + /*RC*/ rtl_rate_control_unregister(); } diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 043045342bc..a91f3eee59c 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h @@ -24,13 +24,26 @@ * Hsinchu 300, Taiwan. * * Larry Finger <Larry.Finger@lwfinger.net> + * *****************************************************************************/ #ifndef __RTL_BASE_H__ #define __RTL_BASE_H__ +enum ap_peer { + PEER_UNKNOWN = 0, + PEER_RTL = 1, + PEER_RTL_92SE = 2, + PEER_BROAD = 3, + PEER_RAL = 4, + PEER_ATH = 5, + PEER_CISCO = 6, + PEER_MARV = 7, + PEER_AIRGO = 9, + PEER_MAX = 10, +} ; + #define RTL_DUMMY_OFFSET 0 -#define RTL_RX_DESC_SIZE 24 #define RTL_DUMMY_UNIT 8 #define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) #define RTL_TX_DESC_SIZE 32 @@ -53,6 +66,14 @@ #define FRAME_OFFSET_SEQUENCE 22 #define FRAME_OFFSET_ADDRESS4 24 +#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ + WRITEEF2BYTE(_hdr, _val) +#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ + WRITEEF1BYTE(_hdr, _val) +#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) +#define SET_80211_HDR_TO_DS(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) #define SET_80211_PS_POLL_AID(_hdr, _val) \ (*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val)) @@ -64,11 +85,27 @@ #define SET_80211_HDR_DURATION(_hdr, _val) \ (*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val)) #define SET_80211_HDR_ADDRESS1(_hdr, _val) \ - memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val), ETH_ALEN) + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8 *)(_val)) #define SET_80211_HDR_ADDRESS2(_hdr, _val) \ - memcpy((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val), ETH_ALEN) + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) #define SET_80211_HDR_ADDRESS3(_hdr, _val) \ - memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val), ETH_ALEN) + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) +#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ + WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) + +#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) +#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) +#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) +#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ + READEF2BYTE(((u8 *)(__phdr)) + 34) +#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) +#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ + (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) int rtl_init_core(struct ieee80211_hw *hw); void rtl_deinit_core(struct ieee80211_hw *hw); @@ -80,18 +117,27 @@ void rtl_watch_dog_timer_callback(unsigned long data); void rtl_deinit_deferred_work(struct ieee80211_hw *hw); bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); -bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); void rtl_watch_dog_timer_callback(unsigned long data); -int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, +int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tid, u16 *ssn); -int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid); +int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + u16 tid); +int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + u16 tid); void rtl_watchdog_wq_callback(void *data); void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); +int rtl_send_smps_action(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 *da, u8 *bssid, + enum ieee80211_smps_mode smps); +u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); +void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); +u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid); extern struct attribute_group rtl_attribute_group; #endif diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c index 52c9c1367ca..7295af0536b 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/rtlwifi/cam.c @@ -23,6 +23,8 @@ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * + * Larry Finger <Larry.Finger@lwfinger.net> + * *****************************************************************************/ #include "wifi.h" @@ -49,7 +51,7 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, u32 target_content = 0; u8 entry_i; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("key_cont_128:\n %x:%x:%x:%x:%x:%x\n", key_cont_128[0], key_cont_128[1], key_cont_128[2], key_cont_128[3], @@ -68,15 +70,13 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], target_command); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): " - "WRITE %x: %x\n", + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE %x: %x\n", rtlpriv->cfg->maps[WCAMI], target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("The Key ID is %d\n", entry_no)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): " - "WRITE %x: %x\n", + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE %x: %x\n", rtlpriv->cfg->maps[RWCAM], target_command)); } else if (entry_i == 1) { @@ -91,12 +91,10 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], target_command); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A4: %x\n", - target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A0: %x\n", - target_command)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A4: %x\n", target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A0: %x\n", target_command)); } else { @@ -113,16 +111,14 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, target_command); udelay(100); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A4: %x\n", - target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("rtl_cam_program_entry(): WRITE A0: %x\n", - target_command)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A4: %x\n", target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + ("WRITE A0: %x\n", target_command)); } } - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("after set key, usconfig:%x\n", us_config)); } @@ -289,3 +285,71 @@ void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) } EXPORT_SYMBOL(rtl_cam_empty_entry); + +u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; + u8 entry_idx = 0; + u8 i, *addr; + + if (NULL == sta_addr) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("sta_addr is NULL.\n")); + return TOTAL_CAM_ENTRY; + } + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; + if (memcmp(addr, sta_addr, ETH_ALEN) == 0) + return i; + } + /* Get a free CAM entry. */ + for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { + if ((bitmap & BIT(0)) == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", + rtlpriv->sec.hwsec_cam_bitmap, entry_idx)); + rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; + memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], + sta_addr, ETH_ALEN); + return entry_idx; + } + bitmap = bitmap >> 1; + } + return TOTAL_CAM_ENTRY; +} +EXPORT_SYMBOL(rtl_cam_get_free_entry); + +void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bitmap; + u8 i, *addr; + + if (NULL == sta_addr) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("sta_addr is NULL.\n")); + } + + if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\ + sta_addr[4]|sta_addr[5]) == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + ("sta_addr is 00:00:00:00:00:00.\n")); + return; + } + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; + bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; + if (((bitmap & BIT(0)) == BIT(0)) && + (memcmp(addr, sta_addr, ETH_ALEN) == 0)) { + /* Remove from HW Security CAM */ + memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); + rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); + printk(KERN_INFO "&&&&&&&&&del entry %d\n", i); + } + } + return; +} +EXPORT_SYMBOL(rtl_cam_del_entry); diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/rtlwifi/cam.h index dd82f057d53..c62da4eefc7 100644 --- a/drivers/net/wireless/rtlwifi/cam.h +++ b/drivers/net/wireless/rtlwifi/cam.h @@ -23,12 +23,13 @@ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * + * Larry Finger <Larry.Finger@lwfinger.net> + * *****************************************************************************/ #ifndef __RTL_CAM_H_ #define __RTL_CAM_H_ -#define TOTAL_CAM_ENTRY 32 #define CAM_CONTENT_COUNT 8 #define CFG_DEFAULT_KEY BIT(5) @@ -49,5 +50,7 @@ int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); +u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr); +void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr); #endif diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 8fed3c68761..fc89cd8c832 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -24,6 +24,7 @@ * Hsinchu 300, Taiwan. * * Larry Finger <Larry.Finger@lwfinger.net> + * *****************************************************************************/ #include "wifi.h" @@ -70,6 +71,7 @@ static void rtl_op_stop(struct ieee80211_hw *hw) mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); + mac->vendor = PEER_UNKNOWN; /*reset sec info */ rtl_cam_reset_sec_info(hw); @@ -85,6 +87,8 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) goto err_free; @@ -92,8 +96,8 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) goto err_free; - - rtlpriv->intf_ops->adapter_tx(hw, skb); + if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) + rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); return; @@ -134,10 +138,26 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, 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; case NL80211_IFTYPE_AP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("NL80211_IFTYPE_AP\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: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -184,13 +204,12 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, mac->vif = NULL; mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); + mac->vendor = PEER_UNKNOWN; mac->opmode = NL80211_IFTYPE_UNSPECIFIED; rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - mutex_unlock(&rtlpriv->locks.conf_mutex); } - static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -222,10 +241,25 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /*For LPS */ if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) - rtl_lps_enter(hw); - else - rtl_lps_leave(hw); + cancel_delayed_work(&rtlpriv->works.ps_work); + cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); + if (conf->flags & IEEE80211_CONF_PS) { + rtlpriv->psc.sw_ps_enabled = true; + /* sleep here is must, or we may recv the beacon and + * cause mac80211 into wrong ps state, this will cause + * power save nullfunc send fail, and further cause + * pkt loss, So sleep must quickly but not immediatly + * because that will cause nullfunc send by mac80211 + * fail, and cause pkt loss, we have tested that 5mA + * is worked very well */ + if (!rtlpriv->psc.multi_buffered) + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ps_work, + MSECS(5)); + } else { + rtl_swlps_rf_awake(hw); + rtlpriv->psc.sw_ps_enabled = false; + } } if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { @@ -257,7 +291,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) case NL80211_CHAN_NO_HT: /* SC */ mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_DONT_CARE; + PRIME_CHNL_OFFSET_DONT_CARE; rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; mac->bw_40 = false; break; @@ -265,7 +299,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; + HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ @@ -276,7 +310,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; + HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ @@ -286,16 +320,29 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) default: mac->bw_40 = false; RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("switch case not processed\n")); + ("switch case not processed\n")); break; } if (wide_chan <= 0) 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 + */ + if (rtlpriv->mac80211.offchan_deley) { + rtlpriv->mac80211.offchan_deley = false; + mdelay(50); + } rtlphy->current_channel = wide_chan; - rtlpriv->cfg->ops->set_channel_access(hw); rtlpriv->cfg->ops->switch_channel(hw); + rtlpriv->cfg->ops->set_channel_access(hw); rtlpriv->cfg->ops->set_bw_mode(hw, hw->conf.channel_type); } @@ -343,27 +390,28 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, } } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - /* - *TODO: BIT(5) is probe response BIT(8) is beacon - *TODO: Use define for BIT(5) and BIT(8) - */ - if (*new_flags & FIF_BCN_PRBRESP_PROMISC) - mac->rx_mgt_filter |= (BIT(5) | BIT(8)); - else - mac->rx_mgt_filter &= ~(BIT(5) | BIT(8)); + /* if ssid not set to hw don't check bssid + * here just used for linked scanning, & linked + * and nolink check bssid is set in set network_type */ + if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && + (mac->link_state >= MAC80211_LINKED)) { + if (mac->opmode != NL80211_IFTYPE_AP) { + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { + rtlpriv->cfg->ops->set_chk_bssid(hw, false); + } else { + rtlpriv->cfg->ops->set_chk_bssid(hw, true); + } + } } if (changed_flags & FIF_CONTROL) { if (*new_flags & FIF_CONTROL) { mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; - mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("Enable receive control frame.\n")); } else { mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; - mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("Disable receive control frame.\n")); } @@ -380,14 +428,54 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, ("Disable receive other BSS's frame.\n")); } } - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, - (u8 *) (&mac->rx_mgt_filter)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, - (u8 *) (&mac->rx_ctrl_filter)); } +static int rtl_op_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry; + + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + sta_entry->wireless_mode = WIRELESS_MODE_G; + if (sta->supp_rates[0] <= 0xf) + sta_entry->wireless_mode = WIRELESS_MODE_B; + if (sta->ht_cap.ht_supported == true) + sta_entry->wireless_mode = WIRELESS_MODE_N_24G; + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + sta_entry->wireless_mode = WIRELESS_MODE_A; + if (sta->ht_cap.ht_supported == true) + sta_entry->wireless_mode = WIRELESS_MODE_N_24G; + } + + /* 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; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); + } + return 0; +} +static int rtl_op_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry; + if (sta) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + sta_entry->wireless_mode = 0; + sta_entry->ratr_index = 0; + } + return 0; +} static int _rtl_get_hal_qnum(u16 queue) { int qnum; @@ -444,19 +532,18 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct ieee80211_sta *sta = NULL; mutex_lock(&rtlpriv->locks.conf_mutex); - if ((vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((changed & BSS_CHANGED_BEACON) || (changed & BSS_CHANGED_BEACON_ENABLED && bss_conf->enable_beacon)) { - if (mac->beacon_enabled == 0) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_BEACON_ENABLED\n")); @@ -468,8 +555,13 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS], 0); + + if (rtlpriv->cfg->ops->linked_set_reg) + rtlpriv->cfg->ops->linked_set_reg(hw); } - } else { + } + if ((changed & BSS_CHANGED_BEACON_ENABLED && + !bss_conf->enable_beacon)) { if (mac->beacon_enabled == 1) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("ADHOC DISABLE BEACON\n")); @@ -480,7 +572,6 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, [RTL_IBSS_INT_MASKS]); } } - if (changed & BSS_CHANGED_BEACON_INT) { RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, ("BSS_CHANGED_BEACON_INT\n")); @@ -492,11 +583,25 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, /*TODO: reference to enum ieee80211_bss_change */ if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { + /* we should reset all sec info & cam + * before set cam after linked, we should not + * reset in disassoc, that will cause tkip->wep + * fail because some flag will be wrong */ + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + /* reset cam to fix wep fail issue + * when change from wpa to wep */ + rtl_cam_reset_all_entry(hw); + mac->link_state = MAC80211_LINKED; mac->cnt_after_linked = 0; mac->assoc_id = bss_conf->aid; memcpy(mac->bssid, bss_conf->bssid, 6); + if (rtlpriv->cfg->ops->linked_set_reg) + rtlpriv->cfg->ops->linked_set_reg(hw); + if (mac->opmode == NL80211_IFTYPE_STATION && sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_ASSOC\n")); } else { @@ -505,9 +610,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); - - /* reset sec info */ - rtl_cam_reset_sec_info(hw); + mac->vendor = PEER_UNKNOWN; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_UN_ASSOC\n")); @@ -544,14 +647,10 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { - struct ieee80211_sta *sta = NULL; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("BSS_CHANGED_HT\n")); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); - + sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); if (sta) { if (sta->ht_cap.ampdu_density > mac->current_ampdu_density) @@ -573,9 +672,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BSSID) { - struct ieee80211_sta *sta = NULL; u32 basic_rates; - u8 i; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, (u8 *) bss_conf->bssid); @@ -583,96 +680,65 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); + mac->vendor = PEER_UNKNOWN; memcpy(mac->bssid, bss_conf->bssid, 6); - if (is_valid_ether_addr(bss_conf->bssid)) { - switch (vif->type) { - case NL80211_IFTYPE_UNSPECIFIED: - break; - case NL80211_IFTYPE_ADHOC: - break; - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_AP: - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("switch case not process\n")); - break; - } - rtlpriv->cfg->ops->set_network_type(hw, vif->type); - } else - rtlpriv->cfg->ops->set_network_type(hw, - NL80211_IFTYPE_UNSPECIFIED); - - memset(mac->mcs, 0, 16); - mac->ht_enable = false; - mac->sgi_40 = false; - mac->sgi_20 = false; - - if (!bss_conf->use_short_slot) - mac->mode = WIRELESS_MODE_B; - else - mac->mode = WIRELESS_MODE_G; + rtlpriv->cfg->ops->set_network_type(hw, vif->type); rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); + sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); + if (!sta) { + rcu_read_unlock(); + goto out; + } - if (sta) { - if (sta->ht_cap.ht_supported) { + if (rtlhal->current_bandtype == BAND_ON_5G) { + mac->mode = WIRELESS_MODE_A; + } else { + if (sta->supp_rates[0] <= 0xf) + mac->mode = WIRELESS_MODE_B; + else + mac->mode = WIRELESS_MODE_G; + } + + if (sta->ht_cap.ht_supported) { + if (rtlhal->current_bandtype == BAND_ON_2_4G) mac->mode = WIRELESS_MODE_N_24G; - mac->ht_enable = true; - } + else + mac->mode = WIRELESS_MODE_N_5G; + } - if (mac->ht_enable) { - u16 ht_cap = sta->ht_cap.cap; - memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16); - - for (i = 0; i < 16; i++) - RT_TRACE(rtlpriv, COMP_MAC80211, - DBG_LOUD, ("%x ", - mac->mcs[i])); - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - ("\n")); - - if (ht_cap & IEEE80211_HT_CAP_SGI_40) - mac->sgi_40 = true; - - if (ht_cap & IEEE80211_HT_CAP_SGI_20) - mac->sgi_20 = true; - - /* - * for cisco 1252 bw20 it's wrong - * if (ht_cap & - * IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - * mac->bw_40 = true; - * } - */ - } + /* just station need it, because ibss & ap mode will + * set in sta_add, and will be NULL here */ + if (mac->opmode == NL80211_IFTYPE_STATION) { + struct rtl_sta_info *sta_entry; + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + sta_entry->wireless_mode = mac->mode; + } + + if (sta->ht_cap.ht_supported) { + mac->ht_enable = true; + + /* + * for cisco 1252 bw20 it's wrong + * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + * mac->bw_40 = true; + * } + * */ } - rcu_read_unlock(); - /*mac80211 just give us CCK rates any time - *So we add G rate in basic rates when - not in B mode*/ if (changed & BSS_CHANGED_BASIC_RATES) { - if (mac->mode == WIRELESS_MODE_B) - basic_rates = bss_conf->basic_rates | 0x00f; + /* for 5G must << RATE_6M_INDEX=4, + * because 5G have no cck rate*/ + if (rtlhal->current_bandtype == BAND_ON_5G) + basic_rates = sta->supp_rates[1] << 4; else - basic_rates = bss_conf->basic_rates | 0xff0; - - if (!vif) - goto out; + basic_rates = sta->supp_rates[0]; mac->basic_rates = basic_rates; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *) (&basic_rates)); - - if (rtlpriv->dm.useramask) - rtlpriv->cfg->ops->update_rate_mask(hw, 0); - else - rtlpriv->cfg->ops->update_rate_table(hw); - } + rcu_read_unlock(); } /* @@ -758,16 +824,17 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_START: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid)); - return rtl_tx_agg_start(hw, sta->addr, tid, ssn); + return rtl_tx_agg_start(hw, sta, tid, ssn); break; case IEEE80211_AMPDU_TX_STOP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid)); - return rtl_tx_agg_stop(hw, sta->addr, tid); + return rtl_tx_agg_stop(hw, sta, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid)); + rtl_tx_agg_oper(hw, sta, tid); break; case IEEE80211_AMPDU_RX_START: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, @@ -797,8 +864,12 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) if (mac->link_state == MAC80211_LINKED) { rtl_lps_leave(hw); mac->link_state = MAC80211_LINKED_SCANNING; - } else + } else { rtl_ips_nic_on(hw); + } + + /* Dual mac */ + rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); @@ -810,22 +881,19 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); - - rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); mac->act_scanning = false; + /* Dual mac */ + rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; + if (mac->link_state == MAC80211_LINKED_SCANNING) { mac->link_state = MAC80211_LINKED; - - /* fix fwlps issue */ - rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - - if (rtlpriv->dm.useramask) - rtlpriv->cfg->ops->update_rate_mask(hw, 0); - else - rtlpriv->cfg->ops->update_rate_table(hw); - + if (mac->opmode == NL80211_IFTYPE_STATION) { + /* fix fwlps issue */ + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + } } + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); } static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -856,49 +924,73 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, rtl_ips_nic_on(hw); mutex_lock(&rtlpriv->locks.conf_mutex); /* <1> get encryption alg */ + switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: key_type = WEP40_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n")); - rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_WEP104: RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP104\n")); key_type = WEP104_ENCRYPTION; - rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_TKIP: key_type = TKIP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n")); - if (mac->opmode == NL80211_IFTYPE_ADHOC) - rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_CCMP: key_type = AESCCMP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n")); - if (mac->opmode == NL80211_IFTYPE_ADHOC) - rtlpriv->sec.use_defaultkey = true; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("alg_err:%x!!!!:\n", key->cipher)); goto out_unlock; } + if (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION || + mac->opmode == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; + /* <2> get key_idx */ key_idx = (u8) (key->keyidx); if (key_idx > 3) goto out_unlock; /* <3> if pairwise key enable_hw_sec */ group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); - if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || - rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { - if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && - (key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION)) - wep_only = true; - rtlpriv->sec.pairwise_enc_algorithm = key_type; - rtlpriv->cfg->ops->enable_hw_sec(hw); + + /* wep always be group key, but there are two conditions: + * 1) wep only: is just for wep enc, in this condition + * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION + * will be true & enable_hw_sec will be set when wep + * ke setting. + * 2) wep(group) + AES(pairwise): some AP like cisco + * may use it, in this condition enable_hw_sec will not + * be set when wep key setting */ + /* we must reset sec_info after lingked before set key, + * or some flag will be wrong*/ + if (mac->opmode == NL80211_IFTYPE_AP) { + if (!group_key || key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION) { + if (group_key) + wep_only = true; + rtlpriv->cfg->ops->enable_hw_sec(hw); + } + } else { + if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || + rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { + if (rtlpriv->sec.pairwise_enc_algorithm == + NO_ENCRYPTION && + (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION)) + wep_only = true; + rtlpriv->sec.pairwise_enc_algorithm = key_type; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1" + " TKIP:2 AES:4 WEP104:5)\n", key_type)); + rtlpriv->cfg->ops->enable_hw_sec(hw); + } } /* <4> set key based on cmd */ switch (cmd) { @@ -930,6 +1022,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!sta) { RT_ASSERT(false, ("pairwise key withnot" "mac_addr\n")); + err = -EOPNOTSUPP; goto out_unlock; } @@ -957,6 +1050,10 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("disable key delete one entry\n")); /*set local buf about wep key. */ + if (mac->opmode == NL80211_IFTYPE_AP) { + if (sta) + rtl_cam_del_entry(hw, sta->addr); + } memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); rtlpriv->sec.key_len[key_idx] = 0; memcpy(mac_addr, zero_addr, ETH_ALEN); @@ -1009,6 +1106,18 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) mutex_unlock(&rtlpriv->locks.conf_mutex); } +/* this function is called by mac80211 to flush tx buffer + * before switch channle or power save, or tx buffer packet + * maybe send after offchannel or rf sleep, this may cause + * dis-association by AP */ +static void rtl_op_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->intf_ops->flush) + rtlpriv->intf_ops->flush(hw, drop); +} + const struct ieee80211_ops rtl_ops = { .start = rtl_op_start, .stop = rtl_op_stop, @@ -1017,6 +1126,8 @@ const struct ieee80211_ops rtl_ops = { .remove_interface = rtl_op_remove_interface, .config = rtl_op_config, .configure_filter = rtl_op_configure_filter, + .sta_add = rtl_op_sta_add, + .sta_remove = rtl_op_sta_remove, .set_key = rtl_op_set_key, .conf_tx = rtl_op_conf_tx, .bss_info_changed = rtl_op_bss_info_changed, @@ -1028,4 +1139,5 @@ const struct ieee80211_ops rtl_ops = { .sw_scan_start = rtl_op_sw_scan_start, .sw_scan_complete = rtl_op_sw_scan_complete, .rfkill_poll = rtl_op_rfkill_poll, + .flush = rtl_op_flush, }; diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h index 0ef31c3c619..4b247db2861 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/rtlwifi/core.h @@ -24,6 +24,7 @@ * Hsinchu 300, Taiwan. * * Larry Finger <Larry.Finger@lwfinger.net> + * *****************************************************************************/ #ifndef __RTL_CORE_H__ diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 5d73c0f7012..510d42edb8c 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -52,8 +52,6 @@ static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { {11, 0, 0, 28} }; -static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, - u8 *pbuf); static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, u8 *value); static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, @@ -79,7 +77,7 @@ static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, u8 *targetdata); static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, u16 efuse_addr, u8 word_en, u8 *data); -static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, +static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate); static u16 efuse_get_current_size(struct ieee80211_hw *hw); static u8 efuse_calculate_word_cnts(u8 word_en); @@ -115,8 +113,10 @@ u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address) u8 bytetemp; u8 temp; u32 k = 0; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - if (address < EFUSE_REAL_CONTENT_LEN) { + if (address < efuse_len) { temp = address & 0xFF; rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, temp); @@ -158,11 +158,13 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) u8 bytetemp; u8 temp; u32 k = 0; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("Addr=%x Data =%x\n", address, value)); - if (address < EFUSE_REAL_CONTENT_LEN) { + if (address < efuse_len) { rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); temp = address & 0xFF; @@ -198,7 +200,7 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) } -static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) +void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 value32; @@ -233,24 +235,28 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 efuse_tbl[EFUSE_MAP_LEN]; + u8 efuse_tbl[HWSET_MAX_SIZE]; u8 rtemp8[1]; u16 efuse_addr = 0; u8 offset, wren; u16 i; u16 j; + const u16 efuse_max_section = + rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; u16 efuse_utilized = 0; u8 efuse_usage; - if ((_offset + _size_byte) > EFUSE_MAP_LEN) { + if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("read_efuse(): Invalid offset(%#x) with read " "bytes(%#x)!!\n", _offset, _size_byte)); return; } - for (i = 0; i < EFUSE_MAX_SECTION; i++) + for (i = 0; i < efuse_max_section; i++) for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) efuse_word[i][j] = 0xFFFF; @@ -262,10 +268,10 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_addr++; } - while ((*rtemp8 != 0xFF) && (efuse_addr < EFUSE_REAL_CONTENT_LEN)) { + while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { offset = ((*rtemp8 >> 4) & 0x0f); - if (offset < EFUSE_MAX_SECTION) { + if (offset < efuse_max_section) { wren = (*rtemp8 & 0x0f); RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, ("offset-%d Worden=%x\n", offset, wren)); @@ -281,7 +287,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_utilized++; efuse_word[offset][i] = (*rtemp8 & 0xff); - if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) + if (efuse_addr >= efuse_len) break; RTPRINT(rtlpriv, FEEPROM, @@ -294,7 +300,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_word[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); - if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) + if (efuse_addr >= efuse_len) break; } @@ -305,13 +311,13 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, ("Addr=%d\n", efuse_addr)); read_efuse_byte(hw, efuse_addr, rtemp8); - if (*rtemp8 != 0xFF && (efuse_addr < 512)) { + if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { efuse_utilized++; efuse_addr++; } } - for (i = 0; i < EFUSE_MAX_SECTION; i++) { + for (i = 0; i < efuse_max_section; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { efuse_tbl[(i * 8) + (j * 2)] = (efuse_word[i][j] & 0xff); @@ -324,7 +330,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) pbuf[i] = efuse_tbl[_offset + i]; rtlefuse->efuse_usedbytes = efuse_utilized; - efuse_usage = (u8)((efuse_utilized * 100) / EFUSE_REAL_CONTENT_LEN); + efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len); rtlefuse->efuse_usedpercentage = efuse_usage; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_utilized); @@ -478,9 +484,10 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - if (rtlefuse->autoload_failflag == true) { - memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, 128); - } else + if (rtlefuse->autoload_failflag == true) + memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + else efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], @@ -632,8 +639,9 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) static void efuse_read_all_map(struct ieee80211_hw *hw, u8 * efuse) { + struct rtl_priv *rtlpriv = rtl_priv(hw); efuse_power_switch(hw, false, true); - read_efuse(hw, 0, 128, efuse); + read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); efuse_power_switch(hw, false, false); } @@ -641,7 +649,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, u8 efuse_data, u8 offset, u8 *tmpdata, u8 *readstate) { - bool bdataempty = true; + bool dataempty = true; u8 hoffset; u8 tmpidx; u8 hworden; @@ -657,13 +665,13 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, &efuse_data)) { tmpdata[tmpidx] = efuse_data; if (efuse_data != 0xff) - bdataempty = true; + dataempty = true; } } - if (bdataempty == true) + if (dataempty == true) { *readstate = PG_STATE_DATA; - else { + } else { *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; *readstate = PG_STATE_HEADER; } @@ -677,9 +685,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) { u8 readstate = PG_STATE_HEADER; - bool continual = true; - u8 efuse_data, word_cnts = 0; u16 efuse_addr = 0; u8 tmpdata[8]; @@ -795,19 +801,20 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, tmp_word_en &= (~BIT(1)); if ((target_pkt->word_en & BIT(2)) ^ - (match_word_en & BIT(2))) + (match_word_en & BIT(2))) tmp_word_en &= (~BIT(2)); if ((target_pkt->word_en & BIT(3)) ^ - (match_word_en & BIT(3))) + (match_word_en & BIT(3))) tmp_word_en &= (~BIT(3)); if ((tmp_word_en & 0x0F) != 0x0F) { *efuse_addr = efuse_get_current_size(hw); target_pkt->offset = offset; target_pkt->word_en = tmp_word_en; - } else + } else { *continual = false; + } *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { @@ -842,9 +849,9 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, efuse_one_byte_write(hw, *efuse_addr, pg_header); efuse_one_byte_read(hw, *efuse_addr, &tmp_header); - if (tmp_header == pg_header) + if (tmp_header == pg_header) { *write_state = PG_STATE_DATA; - else if (tmp_header == 0xFF) { + } else if (tmp_header == 0xFF) { *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { @@ -871,11 +878,13 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, reorg_worden, originaldata); *efuse_addr = efuse_get_current_size(hw); - } else + } else { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - } else + } + } else { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + } *write_state = PG_STATE_HEADER; *repeat_times += 1; @@ -1069,10 +1078,12 @@ static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 tempval; u16 tmpV16; - if (pwrstate) { + if (pwrstate && (rtlhal->hw_type != + HARDWARE_TYPE_RTL8192SE)) { tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL]); if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { @@ -1105,13 +1116,22 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) { + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + } + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, (tempval | 0x80)); } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], + 0x03); + } + } else { if (write) { tempval = rtl_read_byte(rtlpriv, @@ -1122,6 +1142,11 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) (tempval & 0x7F)); } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], + 0x02); + } + } } diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h index 47774dd4c2a..164dabaa761 100644 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ b/drivers/net/wireless/rtlwifi/efuse.h @@ -30,9 +30,10 @@ #ifndef __RTL_EFUSE_H_ #define __RTL_EFUSE_H_ +#define EFUSE_IC_ID_OFFSET 506 + #define EFUSE_REAL_CONTENT_LEN 512 #define EFUSE_MAP_LEN 128 -#define EFUSE_MAX_SECTION 16 #define EFUSE_MAX_WORD_UNIT 4 #define EFUSE_INIT_MAP 0 @@ -52,6 +53,7 @@ #define _PRE_EXECUTE_READ_CMD_ #define EFUSE_REPEAT_THRESHOLD_ 3 +#define EFUSE_ERROE_HANDLE 1 struct efuse_map { u8 offset; @@ -103,6 +105,7 @@ struct efuse_priv { u8 tx_power_g[14]; }; +extern void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); extern void efuse_initialize(struct ieee80211_hw *hw); extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index c3dd4cc678b..3550c9fb96e 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -32,6 +32,7 @@ #include "pci.h" #include "base.h" #include "ps.h" +#include "efuse.h" static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { INTEL_VENDOR_ID, @@ -40,6 +41,31 @@ static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { SIS_VENDOR_ID }; +static const u8 ac_to_hwq[] = { + VO_QUEUE, + VI_QUEUE, + BE_QUEUE, + BK_QUEUE +}; + +static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + __le16 fc = rtl_get_fc(skb); + u8 queue_index = skb_get_queue_mapping(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return BEACON_QUEUE; + if (ieee80211_is_mgmt(fc)) + return MGNT_QUEUE; + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) + if (ieee80211_is_nullfunc(fc)) + return HIGH_QUEUE; + + return ac_to_hwq[queue_index]; +} + /* Update PCI dependent default settings*/ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) { @@ -48,6 +74,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u8 init_aspm; ppsc->reg_rfps_level = 0; ppsc->support_aspm = 0; @@ -113,25 +140,45 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) /*Set HW definition to determine if it supports ASPM. */ switch (rtlpci->const_support_pciaspm) { - case 0: - /*Not support ASPM. */ - ppsc->support_aspm = false; - break; - case 1: - /*Support ASPM. */ - ppsc->support_aspm = true; - ppsc->support_backdoor = true; - break; + case 0:{ + /*Not support ASPM. */ + bool support_aspm = false; + ppsc->support_aspm = support_aspm; + break; + } + case 1:{ + /*Support ASPM. */ + bool support_aspm = true; + bool support_backdoor = true; + ppsc->support_aspm = support_aspm; + + /*if (priv->oem_id == RT_CID_TOSHIBA && + !priv->ndis_adapter.amd_l1_patch) + support_backdoor = false; */ + + ppsc->support_backdoor = support_backdoor; + + break; + } case 2: /*ASPM value set by chipset. */ - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) - ppsc->support_aspm = true; + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { + bool support_aspm = true; + ppsc->support_aspm = support_aspm; + } break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case not process\n")); break; } + + /* toshiba aspm issue, toshiba will set aspm selfly + * so we should not set aspm in driver */ + pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && + init_aspm == 0x43) + ppsc->support_aspm = false; } static bool _rtl_pci_platform_switch_device_pci_aspm( @@ -139,8 +186,11 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) + value |= 0x40; - value |= 0x40; pci_write_config_byte(rtlpci->pdev, 0x80, value); return false; @@ -150,11 +200,13 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 buffer; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - buffer = value; pci_write_config_byte(rtlpci->pdev, 0x81, value); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) + udelay(100); + return true; } @@ -175,6 +227,9 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) u16 aspmlevel = 0; u8 tmp_u1b = 0; + if (!ppsc->support_aspm) + return; + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, ("PCI(Bridge) UNKNOWN.\n")); @@ -228,6 +283,9 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) u8 u_pcibridge_aspmsetting; u8 u_device_aspmsetting; + if (!ppsc->support_aspm) + return; + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, ("PCI(Bridge) UNKNOWN.\n")); @@ -272,7 +330,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); } - udelay(200); + udelay(100); } static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) @@ -309,13 +367,13 @@ static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; u8 linkctrl_reg; - u8 num4bBytes; + u8 num4bbytes; - num4bBytes = (capabilityoffset + 0x10) / 4; + num4bbytes = (capabilityoffset + 0x10) / 4; /*Read Link Control Register */ rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, - pcicfg_addrport + (num4bBytes << 2)); + pcicfg_addrport + (num4bbytes << 2)); rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg); pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; @@ -348,7 +406,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x70f, tmp); } -static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) +static void rtl_pci_init_aspm(struct ieee80211_hw *hw) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -362,52 +420,6 @@ static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) } -static void rtl_pci_init_aspm(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Always Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - * */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; - - _rtl_pci_initialize_adapter_common(hw); -} - static void _rtl_pci_io_handler_init(struct device *dev, struct ieee80211_hw *hw) { @@ -429,6 +441,90 @@ static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) { } +static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 additionlen = FCS_LEN; + struct sk_buff *next_skb; + + /* here open is 4, wep/tkip is 8, aes is 12*/ + if (info->control.hw_key) + additionlen += info->control.hw_key->icv_len; + + /* The most skb num is 6 */ + tcb_desc->empkt_num = 0; + spin_lock_bh(&rtlpriv->locks.waitq_lock); + skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { + struct ieee80211_tx_info *next_info; + + next_info = IEEE80211_SKB_CB(next_skb); + if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { + tcb_desc->empkt_len[tcb_desc->empkt_num] = + next_skb->len + additionlen; + tcb_desc->empkt_num++; + } else { + break; + } + + if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], + next_skb)) + break; + + if (tcb_desc->empkt_num >= 5) + break; + } + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + return true; +} + +/* just for early mode now */ +static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct sk_buff *skb = NULL; + struct ieee80211_tx_info *info = NULL; + int tid; /* should be int */ + + if (!rtlpriv->rtlhal.earlymode_enable) + return; + + /* we juse use em for BE/BK/VI/VO */ + for (tid = 7; tid >= 0; tid--) { + u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)]; + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + while (!mac->act_scanning && + rtlpriv->psc.rfpwr_state == ERFON) { + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + spin_lock_bh(&rtlpriv->locks.waitq_lock); + if (!skb_queue_empty(&mac->skb_waitq[tid]) && + (ring->entries - skb_queue_len(&ring->queue) > 5)) { + skb = skb_dequeue(&mac->skb_waitq[tid]); + } else { + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + break; + } + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + /* Some macaddr can't do early mode. like + * multicast/broadcast/no_qos data */ + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + _rtl_update_earlymode_info(hw, skb, + &tcb_desc, tid); + + rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); + } + } +} + + static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -440,6 +536,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) struct rtl_tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb; struct ieee80211_tx_info *info; + __le16 fc; + u8 tid; u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, HW_DESC_OWN); @@ -460,6 +558,10 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) HW_DESC_TXBUFF_ADDR), skb->len, PCI_DMA_TODEVICE); + /* remove early mode header */ + if (rtlpriv->rtlhal.earlymode_enable) + skb_pull(skb, EM_HDR_LEN); + RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, ("new ring->idx:%d, " "free: skb_queue_len:%d, free: seq:%x\n", @@ -467,6 +569,30 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb_queue_len(&ring->queue), *(u16 *) (skb->data + 22))); + if (prio == TXCMD_QUEUE) { + dev_kfree_skb(skb); + goto tx_status_ok; + + } + + /* for sw LPS, just after NULL skb send out, we can + * sure AP kown we are sleeped, our we should not let + * rf to sleep*/ + fc = rtl_get_fc(skb); + if (ieee80211_is_nullfunc(fc)) { + if (ieee80211_has_pm(fc)) { + rtlpriv->mac80211.offchan_deley = true; + rtlpriv->psc.state_inap = 1; + } else { + rtlpriv->psc.state_inap = 0; + } + } + + /* update tid tx pkt num */ + tid = rtl_get_tid(skb); + if (tid <= 7) + rtlpriv->link_info.tidtx_inperiod[tid]++; + info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); @@ -489,7 +615,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb_get_queue_mapping (skb)); } - +tx_status_ok: skb = NULL; } @@ -561,23 +687,21 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) *skb_trim(skb, skb->len - 4); */ - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; + hdr = rtl_get_hdr(skb); + fc = rtl_get_fc(skb); - if (!stats.crc) { + if (!stats.crc || !stats.hwerror) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - if (is_broadcast_ether_addr(hdr->addr1)) + if (is_broadcast_ether_addr(hdr->addr1)) { ;/*TODO*/ - else { - if (is_multicast_ether_addr(hdr->addr1)) - ;/*TODO*/ - else { - unicast = true; - rtlpriv->stats.rxbytesunicast += - skb->len; - } + } else if (is_multicast_ether_addr(hdr->addr1)) { + ;/*TODO*/ + } else { + unicast = true; + rtlpriv->stats.rxbytesunicast += + skb->len; } rtl_is_special_data(hw, skb, false); @@ -591,28 +715,38 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) num_rx_inperiod++; } - if (unlikely(!rtl_action_proc(hw, skb, - false))) { + /* for sw lps */ + rtl_swlps_beacon(hw, (void *)skb->data, + skb->len); + rtl_recognize_peer(hw, (void *)skb->data, + skb->len); + if ((rtlpriv->mac80211.opmode == + NL80211_IFTYPE_AP) && + (rtlpriv->rtlhal.current_bandtype == + BAND_ON_2_4G) && + (ieee80211_is_beacon(fc) || + ieee80211_is_probe_resp(fc))) { dev_kfree_skb_any(skb); } else { - struct sk_buff *uskb = NULL; - u8 *pdata; - uskb = dev_alloc_skb(skb->len + 128); - if (!uskb) { - RT_TRACE(rtlpriv, - (COMP_INTR | COMP_RECV), - DBG_EMERG, - ("can't alloc rx skb\n")); - goto done; + if (unlikely(!rtl_action_proc(hw, skb, + false))) { + dev_kfree_skb_any(skb); + } else { + struct sk_buff *uskb = NULL; + u8 *pdata; + uskb = dev_alloc_skb(skb->len + + 128); + memcpy(IEEE80211_SKB_RXCB(uskb), + &rx_status, + sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, + skb->len); + memcpy(pdata, skb->data, + skb->len); + dev_kfree_skb_any(skb); + + ieee80211_rx_irqsafe(hw, uskb); } - memcpy(IEEE80211_SKB_RXCB(uskb), - &rx_status, - sizeof(rx_status)); - pdata = (u8 *)skb_put(uskb, skb->len); - memcpy(pdata, skb->data, skb->len); - dev_kfree_skb_any(skb); - - ieee80211_rx_irqsafe(hw, uskb); } } else { dev_kfree_skb_any(skb); @@ -627,7 +761,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) new_skb = dev_alloc_skb(rtlpci->rxbuffersize); if (unlikely(!new_skb)) { RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_EMERG, + DBG_DMESG, ("can't alloc skb for rx\n")); goto done; } @@ -645,7 +779,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) } done: - bufferaddress = (u32)(*((dma_addr_t *) skb->cb)); + bufferaddress = (*((dma_addr_t *)skb->cb)); tmp_one = 1; rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, HW_DESC_RXBUFF_ADDR, @@ -674,6 +808,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) struct ieee80211_hw *hw = dev_id; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); unsigned long flags; u32 inta = 0; u32 intb = 0; @@ -760,23 +895,36 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) _rtl_pci_tx_isr(hw, VO_QUEUE); } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + ("CMD TX OK interrupt!\n")); + _rtl_pci_tx_isr(hw, TXCMD_QUEUE); + } + } + /*<2> Rx related */ if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n")); - tasklet_schedule(&rtlpriv->works.irq_tasklet); + _rtl_pci_rx_interrupt(hw); } if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx descriptor unavailable!\n")); - tasklet_schedule(&rtlpriv->works.irq_tasklet); + _rtl_pci_rx_interrupt(hw); } if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n")); - tasklet_schedule(&rtlpriv->works.irq_tasklet); + _rtl_pci_rx_interrupt(hw); } + if (rtlpriv->rtlhal.earlymode_enable) + tasklet_schedule(&rtlpriv->works.irq_tasklet); + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); return IRQ_HANDLED; @@ -787,7 +935,7 @@ done: static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) { - _rtl_pci_rx_interrupt(hw); + _rtl_pci_tx_chk_waitq(hw); } static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) @@ -795,14 +943,15 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; + struct rtl8192_tx_ring *ring = NULL; struct ieee80211_hdr *hdr = NULL; struct ieee80211_tx_info *info = NULL; struct sk_buff *pskb = NULL; struct rtl_tx_desc *pdesc = NULL; - unsigned int queue_index; + struct rtl_tcb_desc tcb_desc; u8 temp_one = 1; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); ring = &rtlpci->tx_ring[BEACON_QUEUE]; pskb = __skb_dequeue(&ring->queue); if (pskb) @@ -812,14 +961,11 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) pskb = ieee80211_beacon_get(hw, mac->vif); if (pskb == NULL) return; - hdr = (struct ieee80211_hdr *)(pskb->data); + hdr = rtl_get_hdr(pskb); info = IEEE80211_SKB_CB(pskb); - - queue_index = BEACON_QUEUE; - pdesc = &ring->desc[0]; rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, - info, pskb, queue_index); + info, pskb, BEACON_QUEUE, &tcb_desc); __skb_queue_tail(&ring->queue, pskb); @@ -861,7 +1007,6 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); rtlpci->up_first_time = true; rtlpci->being_init_adapter = false; @@ -869,31 +1014,20 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, rtlhal->hw = hw; rtlpci->pdev = pdev; - ppsc->inactiveps = false; - ppsc->leisure_ps = true; - ppsc->fwctrl_lps = true; - ppsc->reg_fwctrl_lps = 3; - ppsc->reg_max_lps_awakeintvl = 5; - - if (ppsc->reg_fwctrl_lps == 1) - ppsc->fwctrl_psmode = FW_PS_MIN_MODE; - else if (ppsc->reg_fwctrl_lps == 2) - ppsc->fwctrl_psmode = FW_PS_MAX_MODE; - else if (ppsc->reg_fwctrl_lps == 3) - ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; - /*Tx/Rx related var */ _rtl_pci_init_trx_var(hw); - /*IBSS*/ mac->beacon_interval = 100; + /*IBSS*/ mac->beacon_interval = 100; - /*AMPDU*/ mac->min_space_cfg = 0; + /*AMPDU*/ + mac->min_space_cfg = 0; mac->max_mss_density = 0; /*set sane AMPDU defaults */ mac->current_ampdu_density = 7; mac->current_ampdu_factor = 3; - /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; + /*QOS*/ + rtlpci->acm_method = eAcmWay2_SW; /*task */ tasklet_init(&rtlpriv->works.irq_tasklet, @@ -934,7 +1068,8 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, ("queue:%d, ring_addr:%p\n", prio, ring)); for (i = 0; i < entries; i++) { - nextdescaddress = (u32) dma + ((i + 1) % entries) * + nextdescaddress = (u32) dma + + ((i + 1) % entries) * sizeof(*ring); rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), @@ -999,7 +1134,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - bufferaddress = (u32)(*((dma_addr_t *)skb->cb)); + bufferaddress = (*((dma_addr_t *)skb->cb)); rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXBUFF_ADDR, (u8 *)&bufferaddress); @@ -1182,72 +1317,73 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) return 0; } -static unsigned int _rtl_mac_to_hwqueue(__le16 fc, - unsigned int mac80211_queue_index) +static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, + struct sk_buff *skb) { - unsigned int hw_queue_index; - - if (unlikely(ieee80211_is_beacon(fc))) { - hw_queue_index = BEACON_QUEUE; - goto out; - } - - if (ieee80211_is_mgmt(fc)) { - hw_queue_index = MGNT_QUEUE; - goto out; - } - - switch (mac80211_queue_index) { - case 0: - hw_queue_index = VO_QUEUE; - break; - case 1: - hw_queue_index = VI_QUEUE; - break; - case 2: - hw_queue_index = BE_QUEUE;; - break; - case 3: - hw_queue_index = BK_QUEUE; - break; - default: - hw_queue_index = BE_QUEUE; - RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", - mac80211_queue_index)); - break; - } + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; + struct rtl_sta_info *sta_entry = NULL; + u8 tid = rtl_get_tid(skb); + + if (!sta) + return false; + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + + if (!rtlpriv->rtlhal.earlymode_enable) + return false; + if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) + return false; + if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) + return false; + if (tid > 7) + return false; + + /* maybe every tid should be checked */ + if (!rtlpriv->link_info.higher_busytxtraffic[tid]) + return false; + + spin_lock_bh(&rtlpriv->locks.waitq_lock); + skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); + spin_unlock_bh(&rtlpriv->locks.waitq_lock); -out: - return hw_queue_index; + return true; } -static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; struct rtl8192_tx_ring *ring; struct rtl_tx_desc *pdesc; u8 idx; - unsigned int queue_index, hw_queue; + u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb); unsigned long flags; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + __le16 fc = rtl_get_fc(skb); u8 *pda_addr = hdr->addr1; struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); /*ssn */ - u8 *qc = NULL; u8 tid = 0; u16 seq_number = 0; u8 own; u8 temp_one = 1; - if (ieee80211_is_mgmt(fc)) - rtl_tx_mgmt_proc(hw, skb); - rtl_action_proc(hw, skb, true); + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); + rtl_ips_nic_on(hw); + } + + if (rtlpriv->psc.sw_ps_enabled) { + if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && + !ieee80211_has_pm(fc)) + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } - queue_index = skb_get_queue_mapping(skb); - hw_queue = _rtl_mac_to_hwqueue(fc, queue_index); + rtl_action_proc(hw, skb, true); if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; @@ -1257,7 +1393,6 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) rtlpriv->stats.txbytesunicast += skb->len; spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - ring = &rtlpci->tx_ring[hw_queue]; if (hw_queue != BEACON_QUEUE) idx = (ring->idx + skb_queue_len(&ring->queue)) % @@ -1280,43 +1415,30 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return skb->len; } - /* - *if(ieee80211_is_nullfunc(fc)) { - * spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - * return 1; - *} - */ - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - - seq_number = mac->tids[tid].seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - /* - *hdr->seq_ctrl = hdr->seq_ctrl & - *cpu_to_le16(IEEE80211_SCTL_FRAG); - *hdr->seq_ctrl |= cpu_to_le16(seq_number); - */ - - seq_number += 1; + tid = rtl_get_tid(skb); + if (sta) { + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + seq_number = (le16_to_cpu(hdr->seq_ctrl) & + IEEE80211_SCTL_SEQ) >> 4; + seq_number += 1; + + if (!ieee80211_has_morefrags(hdr->frame_control)) + sta_entry->tids[tid].seq_number = seq_number; + } } if (ieee80211_is_data(fc)) rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, - info, skb, hw_queue); + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, + info, skb, hw_queue, ptcb_desc); __skb_queue_tail(&ring->queue, skb); - rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, + rtlpriv->cfg->ops->set_desc((u8 *)pdesc, true, HW_DESC_OWN, (u8 *)&temp_one); - if (!ieee80211_has_morefrags(hdr->frame_control)) { - if (qc) - mac->tids[tid].seq_number = seq_number; - } if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && hw_queue != BEACON_QUEUE) { @@ -1338,6 +1460,35 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return 0; } +static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i = 0; + int queue_id; + struct rtl8192_tx_ring *ring; + + for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { + u32 queue_len; + ring = &pcipriv->dev.tx_ring[queue_id]; + queue_len = skb_queue_len(&ring->queue); + if (queue_len == 0 || queue_id == BEACON_QUEUE || + queue_id == TXCMD_QUEUE) { + queue_id--; + continue; + } else { + msleep(20); + i++; + } + + /* we just wait 1s for all queues */ + if (rtlpriv->psc.rfpwr_state == ERFOFF || + is_hal_stop(rtlhal) || i >= 200) + return; + } +} + static void rtl_pci_deinit(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1456,11 +1607,13 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, struct pci_dev *bridge_pdev = pdev->bus->self; u16 venderid; u16 deviceid; + u8 revisionid; u16 irqline; u8 tmp; venderid = pdev->vendor; deviceid = pdev->device; + pci_read_config_byte(pdev, 0x8, &revisionid); pci_read_config_word(pdev, 0x3C, &irqline); if (deviceid == RTL_PCI_8192_DID || @@ -1471,7 +1624,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, deviceid == RTL_PCI_8173_DID || deviceid == RTL_PCI_8172_DID || deviceid == RTL_PCI_8171_DID) { - switch (pdev->revision) { + switch (revisionid) { case RTL_PCI_REVISION_ID_8192PCIE: RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("8192 PCI-E is found - " @@ -1500,6 +1653,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("8192C PCI-E is found - " "vid/did=%x/%x\n", venderid, deviceid)); + } else if (deviceid == RTL_PCI_8192DE_DID || + deviceid == RTL_PCI_8192DE_DID2) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("8192D PCI-E is found - " + "vid/did=%x/%x\n", venderid, deviceid)); } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Err: Unknown device -" @@ -1508,6 +1667,25 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { + if (revisionid == 0 || revisionid == 1) { + if (revisionid == 0) { + RT_TRACE(rtlpriv, COMP_INIT, + DBG_LOUD, ("Find 92DE MAC0.\n")); + rtlhal->interfaceindex = 0; + } else if (revisionid == 1) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Find 92DE MAC1.\n")); + rtlhal->interfaceindex = 1; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + ("Unknown device - " + "VendorID/DeviceID=%x/%x, Revision=%x\n", + venderid, deviceid, revisionid)); + rtlhal->interfaceindex = 0; + } + } /*find bus info */ pcipriv->ndis_adapter.busnumber = pdev->bus->number; pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); @@ -1533,12 +1711,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, PCI_SLOT(bridge_pdev->devfn); pcipriv->ndis_adapter.pcibridge_funcnum = PCI_FUNC(bridge_pdev->devfn); - pcipriv->ndis_adapter.pcibridge_pciehdr_offset = - pci_pcie_cap(bridge_pdev); pcipriv->ndis_adapter.pcicfg_addrport = (pcipriv->ndis_adapter.pcibridge_busnum << 16) | (pcipriv->ndis_adapter.pcibridge_devnum << 11) | (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31); + pcipriv->ndis_adapter.pcibridge_pciehdr_offset = + pci_pcie_cap(bridge_pdev); pcipriv->ndis_adapter.num4bytes = (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; @@ -1621,6 +1799,11 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pcipriv = (void *)rtlpriv->priv; pcipriv->dev.pdev = pdev; + /* init cfg & intf_ops */ + rtlpriv->rtlhal.interface = INTF_PCI; + rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); + rtlpriv->intf_ops = &rtl_pci_ops; + /* *init dbgp flags before all *other functions, because we will @@ -1638,13 +1821,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, return err; } - pmem_start = pci_resource_start(pdev, 2); - pmem_len = pci_resource_len(pdev, 2); - pmem_flags = pci_resource_flags(pdev, 2); + pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); + pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); + pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id); /*shared mem start */ rtlpriv->io.pci_mem_start = - (unsigned long)pci_iomap(pdev, 2, pmem_len); + (unsigned long)pci_iomap(pdev, + rtlpriv->cfg->bar_id, pmem_len); if (rtlpriv->io.pci_mem_start == 0) { RT_ASSERT(false, ("Can't map PCI mem\n")); goto fail2; @@ -1663,11 +1847,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x04, 0x06); pci_write_config_byte(pdev, 0x04, 0x07); - /* init cfg & intf_ops */ - rtlpriv->rtlhal.interface = INTF_PCI; - rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); - rtlpriv->intf_ops = &rtl_pci_ops; - /* find adapter */ _rtl_pci_find_adapter(pdev, hw); @@ -1785,8 +1964,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) rtl_pci_deinit(hw); rtl_deinit_core(hw); - if (rtlpriv->cfg->ops->deinit_sw_leds) - rtlpriv->cfg->ops->deinit_sw_leds(hw); _rtl_pci_io_handler_release(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); @@ -1801,6 +1978,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev) } pci_disable_device(pdev); + + rtl_pci_disable_aspm(hw); + pci_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); @@ -1824,10 +2004,15 @@ no need to call hw_disable here. ****************************************/ int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state) { + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->cfg->ops->hw_suspend(hw); + rtl_deinit_rfkill(hw); + pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); - return 0; } EXPORT_SYMBOL(rtl_pci_suspend); @@ -1835,6 +2020,8 @@ EXPORT_SYMBOL(rtl_pci_suspend); int rtl_pci_resume(struct pci_dev *pdev) { int ret; + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_priv *rtlpriv = rtl_priv(hw); pci_set_power_state(pdev, PCI_D0); ret = pci_enable_device(pdev); @@ -1845,15 +2032,20 @@ int rtl_pci_resume(struct pci_dev *pdev) pci_restore_state(pdev); + rtlpriv->cfg->ops->hw_resume(hw); + rtl_init_rfkill(hw); return 0; } EXPORT_SYMBOL(rtl_pci_resume); struct rtl_intf_ops rtl_pci_ops = { + .read_efuse_byte = read_efuse_byte, .adapter_start = rtl_pci_start, .adapter_stop = rtl_pci_stop, .adapter_tx = rtl_pci_tx, + .flush = rtl_pci_flush, .reset_trx_ring = rtl_pci_reset_trx_ring, + .waitq_insert = rtl_pci_tx_chk_waitq_insert, .disable_aspm = rtl_pci_disable_aspm, .enable_aspm = rtl_pci_enable_aspm, diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 12747b9c71e..671b1f5aa0c 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -102,8 +102,8 @@ #define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ #define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ -#define RTL_PCI_8192DE_DID 0x092D /*8192ce */ -#define RTL_PCI_8192DU_DID 0x092D /*8192ce */ +#define RTL_PCI_8192DE_DID 0x8193 /*8192de */ +#define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ /*8192 support 16 pages of IO registers*/ #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 @@ -129,6 +129,11 @@ enum pci_bridge_vendor { PCI_BRIDGE_VENDOR_MAX, }; +struct rtl_pci_capabilities_header { + u8 capability_id; + u8 next; +}; + struct rtl_rx_desc { u32 dword[8]; } __packed; @@ -161,7 +166,9 @@ struct rtl_pci { bool driver_is_goingto_unload; bool up_first_time; + bool first_init; bool being_init_adapter; + bool init_ready; bool irq_enabled; /*Tx */ @@ -197,6 +204,9 @@ struct rtl_pci { /*QOS & EDCA */ enum acm_method acm_method; + + u16 shortretry_limit; + u16 longretry_limit; }; struct mp_adapter { @@ -227,6 +237,7 @@ struct rtl_pci_priv { struct rtl_pci dev; struct mp_adapter ndis_adapter; struct rtl_led_ctl ledctl; + struct bt_coexist_info bt_coexist; }; #define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index c8395fb0c05..2bb71195e97 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -36,7 +36,6 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool init_status = true; /*<1> reset trx ring */ if (rtlhal->interface == INTF_PCI) @@ -49,7 +48,6 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<2> Enable Adapter */ rtlpriv->cfg->ops->hw_init(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - /*init_status = false; */ /*<3> Enable Interrupt */ rtlpriv->cfg->ops->enable_interrupt(hw); @@ -57,7 +55,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<enable timer> */ rtl_watch_dog_timer_callback((unsigned long)hw); - return init_status; + return true; } EXPORT_SYMBOL(rtl_ps_enable_nic); @@ -192,12 +190,13 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) ppsc->swrf_processing = true; - if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { + if (ppsc->inactive_pwrstate == ERFOFF && + rtlhal->interface == INTF_PCI) { if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } } @@ -206,9 +205,10 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) if (ppsc->inactive_pwrstate == ERFOFF && rtlhal->interface == INTF_PCI) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } } @@ -232,6 +232,9 @@ void rtl_ips_nic_off_wq_callback(void *data) return; } + if (mac->link_state > MAC80211_NOLINK) + return; + if (is_hal_stop(rtlhal)) return; @@ -283,10 +286,14 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) void rtl_ips_nic_on(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate; unsigned long flags; + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); if (ppsc->inactiveps) { @@ -369,8 +376,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) * mode and set RPWM to turn RF on. */ - if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) && - ppsc->report_linked) { + if ((ppsc->fwctrl_lps) && ppsc->report_linked) { bool fw_current_inps; if (ppsc->dot11_psmode == EACTIVE) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, @@ -424,7 +430,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned long flag; - if (!(ppsc->fwctrl_lps && ppsc->leisure_ps)) + if (!ppsc->fwctrl_lps) return; if (rtlpriv->sec.being_setkey) @@ -445,17 +451,16 @@ void rtl_lps_enter(struct ieee80211_hw *hw) spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - if (ppsc->leisure_ps) { - /* Idle for a while if we connect to AP a while ago. */ - if (mac->cnt_after_linked >= 2) { - if (ppsc->dot11_psmode == EACTIVE) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Enter 802.11 power save mode...\n")); - rtl_lps_set_psmode(hw, EAUTOPS); - } + rtl_lps_set_psmode(hw, EAUTOPS); } } + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } @@ -469,17 +474,17 @@ void rtl_lps_leave(struct ieee80211_hw *hw) spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - if (ppsc->fwctrl_lps && ppsc->leisure_ps) { + if (ppsc->fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) { /*FIX ME */ rtlpriv->cfg->ops->enable_interrupt(hw); if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && - RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, @@ -490,3 +495,214 @@ void rtl_lps_leave(struct ieee80211_hw *hw) } spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } + +/* For sw LPS*/ +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (void *) data; + struct ieee80211_tim_ie *tim_ie; + u8 *tim; + u8 tim_len; + bool u_buffed; + bool m_buffed; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (!rtlpriv->psc.swctrl_lps) + return; + + if (rtlpriv->mac80211.link_state != MAC80211_LINKED) + return; + + if (!rtlpriv->psc.sw_ps_enabled) + return; + + if (rtlpriv->psc.fwctrl_lps) + return; + + if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + rtlpriv->psc.last_beacon = jiffies; + + tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); + if (!tim) + return; + + if (tim[1] < sizeof(*tim_ie)) + return; + + tim_len = tim[1]; + tim_ie = (struct ieee80211_tim_ie *) &tim[2]; + + if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period)) + rtlpriv->psc.dtim_counter = tim_ie->dtim_count; + + /* Check whenever the PHY can be turned off again. */ + + /* 1. What about buffered unicast traffic for our AID? */ + u_buffed = ieee80211_check_tim(tim_ie, tim_len, + rtlpriv->mac80211.assoc_id); + + /* 2. Maybe the AP wants to send multicast/broadcast data? */ + m_buffed = tim_ie->bitmap_ctrl & 0x01; + rtlpriv->psc.multi_buffered = m_buffed; + + /* unicast will process by mac80211 through + * set ~IEEE80211_CONF_PS, So we just check + * multicast frames here */ + if (!m_buffed) { + /* back to low-power land. and delay is + * prevent null power save frame tx fail */ + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ps_work, MSECS(5)); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("u_bufferd: %x, " + "m_buffered: %x\n", u_buffed, m_buffed)); + } +} + +void rtl_swlps_rf_awake(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + unsigned long flag; + + if (!rtlpriv->psc.swctrl_lps) + return; + if (mac->link_state != MAC80211_LINKED) + return; + + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} + +void rtl_swlps_rfon_wq_callback(void *data) +{ + struct rtl_works *rtlworks = + container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq); + struct ieee80211_hw *hw = rtlworks->hw; + + rtl_swlps_rf_awake(hw); +} + +void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + unsigned long flag; + u8 sleep_intv; + + if (!rtlpriv->psc.sw_ps_enabled) + return; + + if ((rtlpriv->sec.being_setkey) || + (mac->opmode == NL80211_IFTYPE_ADHOC)) + return; + + /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ + if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) + return; + + if (rtlpriv->link_info.busytraffic) + return; + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (rtlpriv->psc.rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return; + } + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + /* here is power save alg, when this beacon is DTIM + * we will set sleep time to dtim_period * n; + * when this beacon is not DTIM, we will set sleep + * time to sleep_intv = rtlpriv->psc.dtim_counter or + * MAX_SW_LPS_SLEEP_INTV(default set to 5) */ + + if (rtlpriv->psc.dtim_counter == 0) { + if (hw->conf.ps_dtim_period == 1) + sleep_intv = hw->conf.ps_dtim_period * 2; + else + sleep_intv = hw->conf.ps_dtim_period; + } else { + sleep_intv = rtlpriv->psc.dtim_counter; + } + + if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) + sleep_intv = MAX_SW_LPS_SLEEP_INTV; + + /* this print should always be dtim_conter = 0 & + * sleep = dtim_period, that meaons, we should + * awake before every dtim */ + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + ("dtim_counter:%x will sleep :%d" + " beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv)); + + /* we tested that 40ms is enough for sw & hw sw delay */ + queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, + MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); +} + + +void rtl_swlps_wq_callback(void *data) +{ + struct rtl_works *rtlworks = container_of_dwork_rtl(data, + struct rtl_works, + ps_work); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool ps = false; + + ps = (hw->conf.flags & IEEE80211_CONF_PS); + + /* we can sleep after ps null send ok */ + if (rtlpriv->psc.state_inap) { + rtl_swlps_rf_sleep(hw); + + if (rtlpriv->psc.state && !ps) { + rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies - + rtlpriv->psc.last_action); + } + + if (ps) + rtlpriv->psc.last_slept = jiffies; + + rtlpriv->psc.last_action = jiffies; + rtlpriv->psc.state = ps; + } +} diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index ae56da801a2..e3bf8984037 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h @@ -30,6 +30,8 @@ #ifndef __REALTEK_RTL_PCI_PS_H__ #define __REALTEK_RTL_PCI_PS_H__ +#define MAX_SW_LPS_SLEEP_INTV 5 + bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, enum rf_pwrstate state_toset, u32 changesource, bool protect_or_not); @@ -40,4 +42,11 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw); void rtl_ips_nic_off_wq_callback(void *data); void rtl_lps_enter(struct ieee80211_hw *hw); void rtl_lps_leave(struct ieee80211_hw *hw); + +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len); +void rtl_swlps_wq_callback(void *data); +void rtl_swlps_rfon_wq_callback(void *data); +void rtl_swlps_rf_awake(struct ieee80211_hw *hw); +void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); + #endif diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index 91634107434..30da68a7778 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c @@ -38,17 +38,14 @@ *CCK11M or OFDM_54M based on wireless mode. */ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, + struct ieee80211_sta *sta, struct sk_buff *skb, bool not_data) { struct rtl_mac *rtlmac = rtl_mac(rtlpriv); - - /* - *mgt use 1M, although we have check it - *before this function use rate_control_send_low, - *we still check it here - */ - if (not_data) - return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_sta_info *sta_entry = NULL; + u8 wireless_mode = 0; /* *this rate is no use for true rate, firmware @@ -57,35 +54,78 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, *2.in rtl_get_tcb_desc when we check rate is * 1M we will not use FW rate but user rate. */ - if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true)) { - return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; + if (rtlmac->opmode == NL80211_IFTYPE_AP || + rtlmac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wireless_mode = sta_entry->wireless_mode; + } else { + return 0; + } + } else { + wireless_mode = rtlmac->mode; + } + + if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true) || + not_data) { + return 0; } else { - if (rtlmac->mode == WIRELESS_MODE_B) - return rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; - else - return rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + if (wireless_mode == WIRELESS_MODE_B) { + return B_MODE_MAX_RIX; + } else if (wireless_mode == WIRELESS_MODE_G) { + return G_MODE_MAX_RIX; + } else { + if (get_rf_type(rtlphy) != RF_2T2R) + return N_MODE_MCS7_RIX; + else + return N_MODE_MCS15_RIX; + } + } else { + if (wireless_mode == WIRELESS_MODE_A) { + return A_MODE_MAX_RIX; + } else { + if (get_rf_type(rtlphy) != RF_2T2R) + return N_MODE_MCS7_RIX; + else + return N_MODE_MCS15_RIX; + } + } } } static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, + struct ieee80211_sta *sta, struct ieee80211_tx_rate *rate, struct ieee80211_tx_rate_control *txrc, - u8 tries, u8 rix, int rtsctsenable, + u8 tries, char rix, int rtsctsenable, bool not_data) { struct rtl_mac *mac = rtl_mac(rtlpriv); + u8 sgi_20 = 0, sgi_40 = 0; + if (sta) { + sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + } rate->count = tries; - rate->idx = (rix > 0x2) ? rix : 0x2; + rate->idx = rix >= 0x00 ? rix : 0x00; if (!not_data) { if (txrc->short_preamble) rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (mac->bw_40) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (mac->sgi_20 || mac->sgi_40) + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta && (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + } else { + if (mac->bw_40) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + } + if (sgi_20 || sgi_40) rate->flags |= IEEE80211_TX_RC_SHORT_GI; - if (mac->ht_enable) + if (sta && sta->ht_cap.ht_supported) rate->flags |= IEEE80211_TX_RC_MCS; } } @@ -97,39 +137,39 @@ static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc = hdr->frame_control; + __le16 fc = rtl_get_fc(skb); u8 try_per_rate, i, rix; bool not_data = !ieee80211_is_data(fc); if (rate_control_send_low(sta, priv_sta, txrc)) return; - rix = _rtl_rc_get_highest_rix(rtlpriv, skb, not_data); - + rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); try_per_rate = 1; - _rtl_rc_rate_set_series(rtlpriv, &rates[0], txrc, + _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, try_per_rate, rix, 1, not_data); if (!not_data) { for (i = 1; i < 4; i++) - _rtl_rc_rate_set_series(rtlpriv, &rates[i], + _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], txrc, i, (rix - i), 1, not_data); } } -static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, u16 tid) +static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, + struct rtl_sta_info *sta_entry, u16 tid) { struct rtl_mac *mac = rtl_mac(rtlpriv); if (mac->act_scanning) return false; - if (mac->cnt_after_linked < 3) + if (mac->opmode == NL80211_IFTYPE_STATION && + mac->cnt_after_linked < 3) return false; - if (mac->tids[tid].agg.agg_state == RTL_AGG_OFF) + if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) return true; return false; @@ -143,11 +183,9 @@ static void rtl_tx_status(void *ppriv, { struct rtl_priv *rtlpriv = ppriv; struct rtl_mac *mac = rtl_mac(rtlpriv); - struct ieee80211_hdr *hdr; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + __le16 fc = rtl_get_fc(skb); + struct rtl_sta_info *sta_entry; if (!priv_sta || !ieee80211_is_data(fc)) return; @@ -159,17 +197,21 @@ static void rtl_tx_status(void *ppriv, || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) return; - /* Check if aggregation has to be enabled for this tid */ - if (conf_is_ht(&mac->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - - if (_rtl_tx_aggr_check(rtlpriv, tid)) - ieee80211_start_tx_ba_session(sta, tid, 5000); + if (sta) { + /* Check if aggregation has to be enabled for this tid */ + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + if ((sta->ht_cap.ht_supported == true) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 tid = rtl_get_tid(skb); + if (_rtl_tx_aggr_check(rtlpriv, sta_entry, + tid)) { + sta_entry->tids[tid].agg.agg_state = + RTL_AGG_PROGRESS; + ieee80211_start_tx_ba_session(sta, + tid, 5000); + } + } } } } @@ -178,43 +220,6 @@ static void rtl_rate_init(void *ppriv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { - struct rtl_priv *rtlpriv = ppriv; - struct rtl_mac *mac = rtl_mac(rtlpriv); - u8 is_ht = conf_is_ht(&mac->hw->conf); - - if ((mac->opmode == NL80211_IFTYPE_STATION) || - (mac->opmode == NL80211_IFTYPE_MESH_POINT) || - (mac->opmode == NL80211_IFTYPE_ADHOC)) { - - switch (sband->band) { - case IEEE80211_BAND_2GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_G; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - case IEEE80211_BAND_5GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_A; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Invalid band\n")); - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - } - - RT_TRACE(rtlpriv, COMP_RATE, DBG_DMESG, - ("Choosing rate table index: %d\n", - rtlpriv->rate_priv->cur_ratetab_idx)); - - } - } static void rtl_rate_update(void *ppriv, @@ -223,49 +228,6 @@ static void rtl_rate_update(void *ppriv, u32 changed, enum nl80211_channel_type oper_chan_type) { - struct rtl_priv *rtlpriv = ppriv; - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - bool oper_cw40 = false, oper_sgi40; - bool local_cw40 = mac->bw_40; - bool local_sgi40 = mac->sgi_40; - u8 is_ht = conf_is_ht(&mac->hw->conf); - - if (changed & IEEE80211_RC_HT_CHANGED) { - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - - if (rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || - rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) - oper_cw40 = true; - - oper_sgi40 = mac->sgi_40; - - if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { - switch (sband->band) { - case IEEE80211_BAND_2GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_G; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - case IEEE80211_BAND_5GHZ: - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_A; - if (is_ht) - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Invalid band\n")); - rtlpriv->rate_priv->cur_ratetab_idx = - RATR_INX_WIRELESS_NGB; - break; - } - } - } } static void *rtl_rate_alloc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rc.h b/drivers/net/wireless/rtlwifi/rc.h index b4667c035f0..4afa2c20adc 100644 --- a/drivers/net/wireless/rtlwifi/rc.h +++ b/drivers/net/wireless/rtlwifi/rc.h @@ -30,8 +30,15 @@ #ifndef __RTL_RC_H__ #define __RTL_RC_H__ +#define B_MODE_MAX_RIX 3 +#define G_MODE_MAX_RIX 11 +#define A_MODE_MAX_RIX 7 + +/* in mac80211 mcs0-mcs15 is idx0-idx15*/ +#define N_MODE_MCS7_RIX 7 +#define N_MODE_MCS15_RIX 15 + struct rtl_rate_priv { - u8 cur_ratetab_idx; u8 ht_cap; }; diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index d26f957981a..8f6718f163e 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -66,31 +66,83 @@ static struct country_code_to_enum_rd allCountries[] = { NL80211_RRF_PASSIVE_SCAN | \ NL80211_RRF_NO_OFDM) +/* 5G chan 36 - chan 64*/ +#define RTL819x_5GHZ_5150_5350 \ + REG_RULE(5150-10, 5350+10, 40, 0, 30, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +/* 5G chan 100 - chan 165*/ +#define RTL819x_5GHZ_5470_5850 \ + REG_RULE(5470-10, 5850+10, 40, 0, 30, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +/* 5G chan 149 - chan 165*/ +#define RTL819x_5GHZ_5725_5850 \ + REG_RULE(5725-10, 5850+10, 40, 0, 30, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_IBSS) + +#define RTL819x_5GHZ_ALL \ + (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) + static const struct ieee80211_regdomain rtl_regdom_11 = { .n_reg_rules = 1, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - } + } +}; + +static const struct ieee80211_regdomain rtl_regdom_12_13 = { + .n_reg_rules = 2, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + } }; -static const struct ieee80211_regdomain rtl_regdom_global = { +static const struct ieee80211_regdomain rtl_regdom_no_midband = { .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_2GHZ_CH14, - } + RTL819x_5GHZ_5150_5350, + RTL819x_5GHZ_5725_5850, + } }; -static const struct ieee80211_regdomain rtl_regdom_world = { - .n_reg_rules = 2, +static const struct ieee80211_regdomain rtl_regdom_60_64 = { + .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - } + RTL819x_2GHZ_CH12_13, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_14_60_64 = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_14 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + } }; static bool _rtl_is_radar_freq(u16 center_freq) @@ -162,6 +214,8 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, u32 bandwidth = 0; int r; + if (!wiphy->bands[IEEE80211_BAND_2GHZ]) + return; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; /* @@ -292,25 +346,26 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( { switch (reg->country_code) { case COUNTRY_CODE_FCC: + return &rtl_regdom_no_midband; case COUNTRY_CODE_IC: return &rtl_regdom_11; case COUNTRY_CODE_ETSI: + case COUNTRY_CODE_TELEC_NETGEAR: + return &rtl_regdom_60_64; case COUNTRY_CODE_SPAIN: case COUNTRY_CODE_FRANCE: case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_TELEC_NETGEAR: - return &rtl_regdom_world; + case COUNTRY_CODE_WORLD_WIDE_13: + return &rtl_regdom_12_13; case COUNTRY_CODE_MKK: case COUNTRY_CODE_MKK1: case COUNTRY_CODE_TELEC: case COUNTRY_CODE_MIC: - return &rtl_regdom_global; + return &rtl_regdom_14_60_64; case COUNTRY_CODE_GLOBAL_DOMAIN: - return &rtl_regdom_global; - case COUNTRY_CODE_WORLD_WIDE_13: - return &rtl_regdom_world; + return &rtl_regdom_14; default: - return &rtl_regdom_world; + return &rtl_regdom_no_midband; } } @@ -323,9 +378,11 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, const struct ieee80211_regdomain *regd; wiphy->reg_notifier = reg_notifier; + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; + regd = _rtl_regdomain_select(reg); wiphy_apply_custom_regulatory(wiphy, regd); _rtl_reg_apply_radar_flags(wiphy); @@ -355,8 +412,8 @@ int rtl_regd_init(struct ieee80211_hw *hw, if (wiphy == NULL || &rtlpriv->regd == NULL) return -EINVAL; - /* force the channel plan to world wide 13 */ - rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; + /* init country_code from efuse channel plan */ + rtlpriv->regd.country_code = rtlpriv->efuse.channel_plan; RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, (KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", @@ -373,8 +430,8 @@ int rtl_regd_init(struct ieee80211_hw *hw, country = _rtl_regd_find_country(rtlpriv->regd.country_code); if (country) { - rtlpriv->regd.alpha2[0] = country->isoName[0]; - rtlpriv->regd.alpha2[1] = country->isoName[1]; + rtlpriv->regd.alpha2[0] = country->iso_name[0]; + rtlpriv->regd.alpha2[1] = country->iso_name[1]; } else { rtlpriv->regd.alpha2[0] = '0'; rtlpriv->regd.alpha2[1] = '0'; diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/rtlwifi/regd.h index 4cdbc4ae76d..d23118938fa 100644 --- a/drivers/net/wireless/rtlwifi/regd.h +++ b/drivers/net/wireless/rtlwifi/regd.h @@ -32,7 +32,7 @@ struct country_code_to_enum_rd { u16 countrycode; - const char *isoName; + const char *iso_name; }; enum country_code_type_t { diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index c228b9ee371..97183829b9b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -28,10 +28,26 @@ *****************************************************************************/ #include "dm_common.h" +#include "phy_common.h" +#include "../pci.h" +#include "../base.h" struct dig_t dm_digtable; static struct ps_t dm_pstable; +#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) +#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) +#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) +#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) +#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) + +#define RTLPRIV (struct rtl_priv *) +#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ + ((RTLPRIV(_priv))->mac80211.opmode == \ + NL80211_IFTYPE_ADHOC) ? \ + ((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \ + ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb) + static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { 0x7f8001fe, 0x788001e2, @@ -304,7 +320,7 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) { - static u8 binitialized; /* initialized to false */ + static u8 initialized; /* initialized to false */ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; @@ -315,11 +331,11 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) if ((multi_sta == false) || (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT)) { - binitialized = false; + initialized = false; dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; return; - } else if (binitialized == false) { - binitialized = true; + } else if (initialized == false) { + initialized = true; dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; dm_digtable.cur_igvalue = 0x20; rtl92c_dm_write_dig(hw); @@ -461,10 +477,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) if (mac->act_scanning == true) return; - if ((mac->link_state > MAC80211_NOLINK) && - (mac->link_state < MAC80211_LINKED)) - dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT; - else if (mac->link_state >= MAC80211_LINKED) + if (mac->link_state >= MAC80211_LINKED) dm_digtable.cursta_connectctate = DIG_STA_CONNECT; else dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT; @@ -562,23 +575,42 @@ EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo); static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + static u64 last_txok_cnt; static u64 last_rxok_cnt; - u64 cur_txok_cnt; - u64 cur_rxok_cnt; + static u32 last_bt_edca_ul; + static u32 last_bt_edca_dl; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; u32 edca_be_ul = 0x5ea42b; u32 edca_be_dl = 0x5ea42b; + bool bt_change_edca = false; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - goto dm_checkedcaturbo_exit; + if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || + (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { + rtlpriv->dm.current_turbo_edca = false; + last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; + last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; + } + + if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { + edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; + bt_change_edca = true; + } + + if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { + edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; + bt_change_edca = true; + } if (mac->link_state != MAC80211_LINKED) { rtlpriv->dm.current_turbo_edca = false; return; } - if (!mac->ht_enable) { /*FIX MERGE */ + if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { if (!(edca_be_ul & 0xffff0000)) edca_be_ul |= 0x005e0000; @@ -586,10 +618,12 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) edca_be_dl |= 0x005e0000; } - if ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) { + if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting))) { + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + if (cur_rxok_cnt > 4 * cur_txok_cnt) { if (!rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { @@ -618,7 +652,6 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) } } -dm_checkedcaturbo_exit: rtlpriv->dm.is_any_nonbepkts = false; last_txok_cnt = rtlpriv->stats.txbytesunicast; last_rxok_cnt = rtlpriv->stats.rxbytesunicast; @@ -633,14 +666,14 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 thermalvalue, delta, delta_lck, delta_iqk; long ele_a, ele_d, temp_cck, val_x, value32; - long val_y, ele_c; + long val_y, ele_c = 0; u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0; int i; bool is2t = IS_92C_SERIAL(rtlhal->version); u8 txpwr_level[2] = {0, 0}; u8 ofdm_min_index = 6, rf; - rtlpriv->dm.txpower_trackingInit = true; + rtlpriv->dm.txpower_trackinginit = true; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n")); @@ -683,7 +716,6 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw for (i = 0; i < OFDM_TABLE_LENGTH; i++) { if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { - ofdm_index_old[1] = (u8) i; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -1062,7 +1094,7 @@ static void rtl92c_dm_initialize_txpower_tracking_thermalmeter( struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackingInit = false; + rtlpriv->dm.txpower_trackinginit = false; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("pMgntInfo->txpower_tracking = %d\n", @@ -1132,6 +1164,7 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rate_adaptive *p_ra = &(rtlpriv->ra); u32 low_rssithresh_for_ra, high_rssithresh_for_ra; + struct ieee80211_sta *sta = NULL; if (is_hal_stop(rtlhal)) { RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, @@ -1145,8 +1178,8 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) return; } - if (mac->link_state == MAC80211_LINKED) { - + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { switch (p_ra->pre_ratr_state) { case DM_RATR_STA_HIGH: high_rssithresh_for_ra = 50; @@ -1185,10 +1218,13 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) ("PreState = %d, CurState = %d\n", p_ra->pre_ratr_state, p_ra->ratr_state)); - rtlpriv->cfg->ops->update_rate_mask(hw, + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, p_ra->ratr_state); p_ra->pre_ratr_state = p_ra->ratr_state; + rcu_read_unlock(); } } } @@ -1202,51 +1238,6 @@ static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) dm_pstable.rssi_val_min = 0; } -static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (dm_pstable.rssi_val_min != 0) { - if (dm_pstable.pre_ccastate == CCA_2R) { - if (dm_pstable.rssi_val_min >= 35) - dm_pstable.cur_ccasate = CCA_1R; - else - dm_pstable.cur_ccasate = CCA_2R; - } else { - if (dm_pstable.rssi_val_min <= 30) - dm_pstable.cur_ccasate = CCA_2R; - else - dm_pstable.cur_ccasate = CCA_1R; - } - } else { - dm_pstable.cur_ccasate = CCA_MAX; - } - - if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) { - if (dm_pstable.cur_ccasate == CCA_1R) { - if (get_rf_type(rtlphy) == RF_2T2R) { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE0, 0x13); - rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20); - } else { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE0, 0x23); - rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c); - } - } else { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, - 0x33); - rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63); - } - dm_pstable.pre_ccastate = dm_pstable.cur_ccasate; - } - - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n", - (dm_pstable.cur_ccasate == - 0) ? "1RCCA" : "2RCCA")); -} - void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) { static u8 initialize; @@ -1352,7 +1343,9 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) } if (IS_92C_SERIAL(rtlhal->version)) - rtl92c_dm_1r_cca(hw); + ;/* rtl92c_dm_1r_cca(hw); */ + else + rtl92c_dm_rf_saving(hw, false); } void rtl92c_dm_init(struct ieee80211_hw *hw) @@ -1369,6 +1362,84 @@ void rtl92c_dm_init(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_dm_init); +void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undecorated_smoothed_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Not connected to any\n")); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Client PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.undecorated_smoothed_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("STA Default Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + } else { + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("AP Ext Port PWDB = 0x%lx\n", + undecorated_smoothed_pwdb)); + } + + if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n")); + } else if ((undecorated_smoothed_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undecorated_smoothed_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n")); + } else if (undecorated_smoothed_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("TXHIGHPWRLEVEL_NORMAL\n")); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel)); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + void rtl92c_dm_watchdog(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1388,11 +1459,321 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) rtl92c_dm_dig(hw); rtl92c_dm_false_alarm_counter_statistics(hw); rtl92c_dm_dynamic_bb_powersaving(hw); - rtlpriv->cfg->ops->dm_dynamic_txpower(hw); + rtl92c_dm_dynamic_txpower(hw); rtl92c_dm_check_txpower_tracking(hw); rtl92c_dm_refresh_rate_adaptive_mask(hw); + rtl92c_dm_bt_coexist(hw); rtl92c_dm_check_edca_turbo(hw); - } } EXPORT_SYMBOL(rtl92c_dm_watchdog); + +u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + long undecorated_smoothed_pwdb; + u8 curr_bt_rssi_state = 0x00; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + undecorated_smoothed_pwdb = + GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); + } else { + if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0) + undecorated_smoothed_pwdb = 100; + else + undecorated_smoothed_pwdb = + rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; + } + + /* Check RSSI to determine HighPower/NormalPower state for + * BT coexistence. */ + if (undecorated_smoothed_pwdb >= 67) + curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); + else if (undecorated_smoothed_pwdb < 62) + curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; + + /* Check RSSI to determine AMPDU setting for BT coexistence. */ + if (undecorated_smoothed_pwdb >= 40) + curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); + else if (undecorated_smoothed_pwdb <= 32) + curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; + + /* Marked RSSI state. It will be used to determine BT coexistence + * setting later. */ + if (undecorated_smoothed_pwdb < 35) + curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; + else + curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); + + /* Set Tx Power according to BT status. */ + if (undecorated_smoothed_pwdb >= 30) + curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; + else if (undecorated_smoothed_pwdb < 25) + curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); + + /* Check BT state related to BT_Idle in B/G mode. */ + if (undecorated_smoothed_pwdb < 15) + curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; + else + curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); + + if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) { + rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state; + return true; + } else { + return false; + } +} +EXPORT_SYMBOL(rtl92c_bt_rssi_state_change); + +static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + u32 polling, ratio_tx, ratio_pri; + u32 bt_tx, bt_pri; + u8 bt_state; + u8 cur_service_type; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) + return false; + + bt_state = rtl_read_byte(rtlpriv, 0x4fd); + bt_tx = rtl_read_dword(rtlpriv, 0x488); + bt_tx = bt_tx & 0x00ffffff; + bt_pri = rtl_read_dword(rtlpriv, 0x48c); + bt_pri = bt_pri & 0x00ffffff; + polling = rtl_read_dword(rtlpriv, 0x490); + + if (bt_tx == 0xffffffff && bt_pri == 0xffffffff && + polling == 0xffffffff && bt_state == 0xff) + return false; + + bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1); + if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) { + rtlpcipriv->bt_coexist.bt_cur_state = bt_state; + + if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) { + rtlpcipriv->bt_coexist.bt_service = BT_IDLE; + + bt_state = bt_state | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + BIT_OFFSET_LEN_MASK_32(2, 1); + rtl_write_byte(rtlpriv, 0x4fd, bt_state); + } + return true; + } + + ratio_tx = bt_tx * 1000 / polling; + ratio_pri = bt_pri * 1000 / polling; + rtlpcipriv->bt_coexist.ratio_tx = ratio_tx; + rtlpcipriv->bt_coexist.ratio_pri = ratio_pri; + + if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) { + + if ((ratio_tx < 30) && (ratio_pri < 30)) + cur_service_type = BT_IDLE; + else if ((ratio_pri > 110) && (ratio_pri < 250)) + cur_service_type = BT_SCO; + else if ((ratio_tx >= 200) && (ratio_pri >= 200)) + cur_service_type = BT_BUSY; + else if ((ratio_tx >= 350) && (ratio_tx < 500)) + cur_service_type = BT_OTHERBUSY; + else if (ratio_tx >= 500) + cur_service_type = BT_PAN; + else + cur_service_type = BT_OTHER_ACTION; + + if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) { + rtlpcipriv->bt_coexist.bt_service = cur_service_type; + bt_state = bt_state | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + + /* Add interrupt migration when bt is not ini + * idle state (no traffic). */ + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + rtl_write_word(rtlpriv, 0x504, 0x0ccc); + rtl_write_byte(rtlpriv, 0x506, 0x54); + rtl_write_byte(rtlpriv, 0x507, 0x54); + } else { + rtl_write_byte(rtlpriv, 0x506, 0x00); + rtl_write_byte(rtlpriv, 0x507, 0x00); + } + + rtl_write_byte(rtlpriv, 0x4fd, bt_state); + return true; + } + } + + return false; + +} + +static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + static bool media_connect; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { + media_connect = false; + } else { + if (!media_connect) { + media_connect = true; + return true; + } + media_connect = true; + } + + return false; +} + +static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + + if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b; + } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f; + } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) { + if (rtlpcipriv->bt_coexist.ratio_tx > 160) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f; + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b; + } + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } + + if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) && + (rtlpriv->mac80211.mode == WIRELESS_MODE_G || + (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_BG_EDCA_LOW)) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b; + } +} + +static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + + /* Only enable HW BT coexist when BT in "Busy" state. */ + if (rtlpriv->mac80211.vendor == PEER_CISCO && + rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else { + if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_NORMAL_POWER)) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else if ((rtlpcipriv->bt_coexist.bt_service == + BT_OTHER_ACTION) && (rtlpriv->mac80211.mode < + WIRELESS_MODE_N_24G) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_SPECIAL_LOW)) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); + } else { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); + } + } + + if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100); + else + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0); + + if (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_NORMAL_POWER) { + rtl92c_bt_set_normal(hw); + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } + + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + rtlpriv->cfg->ops->set_rfreg(hw, + RF90_PATH_A, + 0x1e, + 0xf0, 0xf); + } else { + rtlpriv->cfg->ops->set_rfreg(hw, + RF90_PATH_A, 0x1e, 0xf0, + rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); + } + + if (!rtlpriv->dm.dynamic_txpower_enable) { + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + if (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_TXPOWER_LOW) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_BT2; + } else { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_BT1; + } + } else { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_NORMAL; + } + rtl92c_phy_set_txpower_level(hw, + rtlpriv->phy.current_channel); + } +} + +static void rtl92c_check_bt_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + if (rtlpcipriv->bt_coexist.bt_cur_state) { + if (rtlpcipriv->bt_coexist.bt_ant_isolation) + rtl92c_bt_ant_isolation(hw); + } else { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); + rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, + rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); + + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } +} + +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + bool wifi_connect_change; + bool bt_state_change; + bool rssi_state_change; + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { + + wifi_connect_change = rtl92c_bt_wifi_connect_change(hw); + bt_state_change = rtl92c_bt_state_change(hw); + rssi_state_change = rtl92c_bt_rssi_state_change(hw); + + if (wifi_connect_change || bt_state_change || rssi_state_change) + rtl92c_check_bt_change(hw); + } +} +EXPORT_SYMBOL(rtl92c_dm_bt_coexist); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h index b9cbb0a3c03..b9736d3e9a3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h @@ -200,5 +200,7 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); +void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index bc9d24134ac..50303e1adff 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -223,29 +223,15 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) u8 *pfwdata; u32 fwsize; enum version_8192c version = rtlhal->version; - const struct firmware *firmware; printk(KERN_INFO "rtl8192c: Loading firmware file %s\n", rtlpriv->cfg->fw_name); - if (request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev)) { - printk(KERN_ERR "rtl8192c: Firmware loading failed\n"); + if (!rtlhal->pfirmware) return 1; - } - - if (firmware->size > 0x4000) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - - memcpy(rtlhal->pfirmware, firmware->data, firmware->size); - fwsize = firmware->size; - release_firmware(firmware); pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware; + fwsize = rtlhal->fwsize; if (IS_FW_HEADER_EXIST(pfwheader)) { RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, @@ -553,6 +539,39 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) } EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd); +static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + u8 own; + unsigned long flags; + struct sk_buff *pskb = NULL; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + pdesc = &ring->desc[0]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); + + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); + + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + + return true; +} + #define BEACON_PG 0 /*->1*/ #define PSPOLL_PG 2 #define NULL_PG 3 @@ -670,7 +689,7 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -679,12 +698,12 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u32 totalpacketlen; bool rtstatus; u8 u1RsvdPageLoc[3] = {0}; - bool b_dlok = false; + bool dlok = false; u8 *beacon; - u8 *p_pspoll; + u8 *pspoll; u8 *nullfunc; - u8 *p_probersp; + u8 *probersp; /*--------------------------------------------------------- (1) beacon ---------------------------------------------------------*/ @@ -695,10 +714,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) /*------------------------------------------------------- (2) ps-poll --------------------------------------------------------*/ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); + SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); @@ -715,10 +734,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) /*--------------------------------------------------------- (4) probe response ----------------------------------------------------------*/ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(probersp, mac->bssid); SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); @@ -736,12 +755,12 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, totalpacketlen); - rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb); + rtstatus = _rtl92c_cmd_send_packet(hw, skb); if (rtstatus) - b_dlok = true; + dlok = true; - if (b_dlok) { + if (dlok) { RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Set RSVD page location to Fw.\n")); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h index 3db33bd1466..3d5823c1262 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h @@ -27,8 +27,8 @@ * *****************************************************************************/ -#ifndef __RTL92C__FW__H__ -#define __RTL92C__FW__H__ +#ifndef __RTL92C__FW__COMMON__H__ +#define __RTL92C__FW__COMMON__H__ #define FW_8192C_SIZE 0x3000 #define FW_8192C_START_ADDRESS 0x1000 diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index a7022827839..c5424cad43c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -78,27 +78,29 @@ void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," " data(%#x)\n", regaddr, bitmask, data)); + } EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) + enum radio_path rfpath, u32 offset) { RT_ASSERT(false, ("deprecated!\n")); return 0; + } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) + enum radio_path rfpath, u32 offset, + u32 data) { RT_ASSERT(false, ("deprecated!\n")); } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) + enum radio_path rfpath, u32 offset) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -149,8 +151,8 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) + enum radio_path rfpath, u32 offset, + u32 data) { u32 data_and_addr; u32 newoffset; @@ -197,6 +199,7 @@ static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw) rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); } + bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -241,13 +244,14 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); + return true; } EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) + u32 regaddr, u32 bitmask, + u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -317,61 +321,48 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, } if (regaddr == RTXAGC_B_RATE54_24) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9])); } - if (regaddr == RTXAGC_B_CCK1_55_MCS32) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14])); } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15])); } - if (regaddr == RTXAGC_B_MCS03_MCS00) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10])); } - if (regaddr == RTXAGC_B_MCS07_MCS04) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11])); } - if (regaddr == RTXAGC_B_MCS11_MCS08) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12])); } - if (regaddr == RTXAGC_B_MCS15_MCS12) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", rtlphy->pwrgroup_cnt, @@ -583,6 +574,7 @@ static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw, rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; + } void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) @@ -611,7 +603,6 @@ bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 idx; u8 rf_path; - u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_B, power_indbm); @@ -639,11 +630,6 @@ bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) } EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm); -void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval) -{ -} -EXPORT_SYMBOL(rtl92c_phy_set_beacon_hw_reg); - u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, enum wireless_mode wirelessmode, long power_indbm) @@ -741,9 +727,9 @@ void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, if (rtlphy->set_bwmode_inprogress) return; rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) - rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); - else { + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtlphy->set_bwmode_inprogress = false; + } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("FALSE driver sleep or unload\n")); rtlphy->set_bwmode_inprogress = false; @@ -773,8 +759,9 @@ void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw) mdelay(delay); else continue; - } else + } else { rtlphy->sw_chnl_inprogress = false; + } break; } while (true); RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); @@ -811,9 +798,32 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_phy_sw_chnl); -static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -917,29 +927,6 @@ static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, return false; } -static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) { return true; @@ -1002,13 +989,13 @@ static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw) reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + if (!(reg_eac & BIT(31)) && (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) result |= 0x01; else return result; - if (!(reg_eac & BIT(30)) && (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) @@ -1023,9 +1010,9 @@ static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, u32 oldval_0, x, tx0_a, reg; long y, tx0_c; - if (final_candidate == 0xFF) + if (final_candidate == 0xFF) { return; - else if (iqk_ok) { + } else if (iqk_ok) { oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; x = result[final_candidate][0]; @@ -1063,9 +1050,9 @@ static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, u32 oldval_1, x, tx1_a, reg; long y, tx1_c; - if (final_candidate == 0xFF) + if (final_candidate == 0xFF) { return; - else if (iqk_ok) { + } else if (iqk_ok) { oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; x = result[final_candidate][4]; @@ -1282,6 +1269,7 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, RFPGA0_XA_HSSIPARAMETER1, BIT(8)); } + if (!rtlphy->rfpi_enable) _rtl92c_phy_pi_mode_switch(hw, true); if (t == 0) { @@ -1317,9 +1305,10 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, 0x3FF0000) >> 16; break; } else if (i == (retrycount - 1) && patha_ok == 0x01) + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & 0x3FF0000) >> - 16; + 16; result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; @@ -1375,8 +1364,7 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta, bool is2t) { - /* This routine is deliberately dummied out for later fixes */ -#if 0 +#if 0 /* This routine is deliberately dummied out for later fixes */ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); @@ -1434,7 +1422,7 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x04db25a4, 0x0b1b25a4 }; - u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; + const u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 }; @@ -1463,13 +1451,15 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x00050006 }; - const u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; + u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; long bb_offset, delta_v, delta_offset; if (!is2t) pathbound = 1; + return; + for (index = 0; index < PATH_NUM; index++) { apk_offset[index] = apk_normal_offset[index]; apk_value[index] = apk_normal_value[index]; @@ -1730,8 +1720,7 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x08)); } - - rtlphy->apk_done = true; + rtlphy->b_apk_done = true; #endif } @@ -1758,6 +1747,7 @@ static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); } + } #undef IQK_ADDA_REG_NUM diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h index 53ffb098158..9a264c0d612 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h @@ -27,8 +27,8 @@ * *****************************************************************************/ -#ifndef __RTL92C_PHY_H__ -#define __RTL92C_PHY_H__ +#ifndef __RTL92C_PHY_COMMON_H__ +#define __RTL92C_PHY_COMMON_H__ #define MAX_PRECMD_CNT 16 #define MAX_RFDEPENDCMD_CNT 16 @@ -39,6 +39,7 @@ #define RT_CANNOT_IO(hw) false #define HIGHPOWER_RADIOA_ARRAYLEN 22 +#define IQK_ADDA_REG_NUM 16 #define MAX_TOLERANCE 5 #define IQK_DELAY_TIME 1 @@ -56,6 +57,7 @@ #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 +#define IQK_DELAY_TIME 1 #define RF90_PATH_MAX 2 #define CT_OFFSET_MAC_ADDR 0X16 @@ -77,6 +79,7 @@ #define RTL92C_MAX_PATH_NUM 2 #define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 + enum swchnlcmd_id { CMDID_END, CMDID_SET_TXPOWEROWER_LEVEL, @@ -184,45 +187,41 @@ struct tx_power_struct { u32 mcs_original_offset[4][16]; }; -extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); -extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); -extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm); -extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, +void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); -extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); -extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state); void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); void rtl92c_phy_set_io(struct ieee80211_hw *hw); @@ -235,12 +234,25 @@ u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, enum wireless_mode wirelessmode, long power_indbm); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); -static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, u32 para1, - u32 para2, u32 msdelay); -static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay); +void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); +bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); +u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw); +u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); +void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data); +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 2f577c8828f..35ff7df41a1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -121,19 +121,6 @@ #define CHIP_92C 0x01 #define CHIP_88C 0x00 -/* Add vendor information into chip version definition. - * Add UMC B-Cut and RTL8723 chip info definition. - * - * BIT 7 Reserved - * BIT 6 UMC BCut - * BIT 5 Manufacturer(TSMC/UMC) - * BIT 4 TEST/NORMAL - * BIT 3 8723 Version - * BIT 2 8723? - * BIT 1 1T2R? - * BIT 0 88C/92C -*/ - enum version_8192c { VERSION_A_CHIP_92C = 0x01, VERSION_A_CHIP_88C = 0x00, @@ -280,20 +267,6 @@ struct h2c_cmd_8192c { u8 *p_cmdbuffer; }; -static inline u8 _rtl92c_get_chnl_group(u8 chnl) -{ - u8 group = 0; - - if (chnl < 3) - group = 0; - else if (chnl < 9) - group = 1; - else - group = 2; - - return group; -} - /* NOTE: reference to rtl8192c_rates struct */ static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, u8 desc_rate, bool first_ampdu) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c index 7d76504df4d..2df33e53e15 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c @@ -29,10 +29,12 @@ #include "../wifi.h" #include "../base.h" +#include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" #include "dm.h" +#include "../rtl8192c/fw_common.h" void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h index 36302ebae4a..07dd9552e82 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h @@ -192,6 +192,7 @@ void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 05477f465a7..4a56138eb33 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -30,12 +30,14 @@ #include "../wifi.h" #include "../efuse.h" #include "../base.h" +#include "../regd.h" #include "../cam.h" #include "../ps.h" #include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" +#include "../rtl8192c/fw_common.h" #include "dm.h" #include "led.h" #include "hw.h" @@ -137,15 +139,6 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } - case HW_VAR_MGT_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); - break; - case HW_VAR_CTRL_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); - break; - case HW_VAR_DATA_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); - break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case not process\n")); @@ -156,6 +149,7 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -178,7 +172,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rate_cfg |= 0x01; rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); rtl_write_byte(rtlpriv, REG_RRSR + 1, - (rate_cfg >> 8)&0xff); + (rate_cfg >> 8) & 0xff); while (rate_cfg > 0x1) { rate_cfg = (rate_cfg >> 1); rate_index++; @@ -276,13 +270,19 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; + u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; u8 factor_toset; u8 *p_regtoset = NULL; u8 index = 0; - p_regtoset = regtoset_normal; + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == + BT_CSR_BC4)) + p_regtoset = regtoset_bt; + else + p_regtoset = regtoset_normal; factor_toset = *((u8 *) val); if (factor_toset <= 3) { @@ -317,45 +317,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } case HW_VAR_AC_PARAM:{ u8 e_aci = *((u8 *) val); - u32 u4b_ac_param; - u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); - u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); - u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); - - u4b_ac_param = (u32) mac->ac[e_aci].aifs; - u4b_ac_param |= ((u32)cw_min - & 0xF) << AC_PARAM_ECW_MIN_OFFSET; - u4b_ac_param |= ((u32)cw_max & - 0xF) << AC_PARAM_ECW_MAX_OFFSET; - u4b_ac_param |= (u32)tx_op << AC_PARAM_TXOP_OFFSET; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - ("queue:%x, ac_param:%x\n", e_aci, - u4b_ac_param)); - - switch (e_aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, - u4b_ac_param); - break; - case AC0_BE: - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, - u4b_ac_param); - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, - u4b_ac_param); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, - u4b_ac_param); - break; - default: - RT_ASSERT(false, - ("SetHwReg8185(): invalid aci: %d !\n", - e_aci)); - break; - } + rtl92c_dm_init_edca_turbo(hw); if (rtlpci->acm_method != eAcmWay2_SW) rtlpriv->cfg->ops->set_hw_reg(hw, @@ -526,9 +488,6 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_CORRECT_TSF:{ u8 btype_ibss = ((u8 *) (val))[0]; - /*btype_ibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? - 1 : 0;*/ - if (btype_ibss == true) _rtl92ce_stop_tx_beacon(hw); @@ -537,7 +496,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_dword(rtlpriv, REG_TSFTR, (u32) (mac->tsf & 0xffffffff)); rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32) ((mac->tsf >> 32)&0xffffffff)); + (u32) ((mac->tsf >> 32) & 0xffffffff)); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); @@ -547,15 +506,6 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } - case HW_VAR_MGT_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *) val); - break; - case HW_VAR_CTRL_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *) val); - break; - case HW_VAR_DATA_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *) val); - break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " "not process\n")); @@ -679,12 +629,12 @@ static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) rtl92ce_sw_led_on(hw, pLed0); else rtl92ce_sw_led_off(hw, pLed0); - } static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -693,9 +643,22 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) u16 retry; rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u32 value32; + value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); + value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); + rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); + } rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); + + u4b_tmp &= (~0x00024800); + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); + } + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); udelay(2); @@ -726,6 +689,11 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); udelay(2); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd; + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp); + } + rtl_write_word(rtlpriv, REG_CR, 0x2ff); if (_rtl92ce_llt_table_init(hw) == false) @@ -793,6 +761,7 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); u8 reg_bw_opmode; u32 reg_ratr, reg_prsr; @@ -824,7 +793,11 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); + else + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); @@ -840,11 +813,20 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); + } else { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + } - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + else + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); @@ -948,8 +930,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) } rtlhal->last_hmeboxnum = 0; - rtl92ce_phy_mac_config(hw); - rtl92ce_phy_bb_config(hw); + rtl92c_phy_mac_config(hw); + rtl92c_phy_bb_config(hw); rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; rtl92c_phy_rf_config(hw); rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, @@ -962,15 +944,20 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) _rtl92ce_hw_configure(hw); rtl_cam_reset_all_entry(hw); rtl92ce_enable_hw_security_config(hw); + ppsc->rfpwr_state = ERFON; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); _rtl92ce_enable_aspm_back_door(hw); rtlpriv->intf_ops->enable_aspm(hw); + + rtl8192ce_bt_hw_init(hw); + if (ppsc->rfpwr_state == ERFON) { rtl92c_phy_set_rfpath_switch(hw, 1); - if (iqk_initialized) + if (iqk_initialized) { rtl92c_phy_iq_calibrate(hw, true); - else { + } else { rtl92c_phy_iq_calibrate(hw, false); iqk_initialized = true; } @@ -1128,75 +1115,62 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, return 0; } -static void _rtl92ce_set_check_bssid(struct ieee80211_hw *hw, - enum nl80211_iftype type) +void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); - u8 filterout_non_associated_bssid = false; - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - filterout_non_associated_bssid = true; - break; - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_AP: - default: - break; - } + if (rtlpriv->psc.rfpwr_state != ERFON) + return; - if (filterout_non_associated_bssid == true) { + if (check_bssid == true) { reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (®_rcr)); _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (filterout_non_associated_bssid == false) { + } else if (check_bssid == false) { reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (®_rcr)); } + } int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (_rtl92ce_set_media_status(hw, type)) return -EOPNOTSUPP; - _rtl92ce_set_check_bssid(hw, type); + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92ce_set_check_bssid(hw, true); + } else { + rtl92ce_set_check_bssid(hw, false); + } + return 0; } +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u32 u4b_ac_param; - u16 cw_min = le16_to_cpu(mac->ac[aci].cw_min); - u16 cw_max = le16_to_cpu(mac->ac[aci].cw_max); - u16 tx_op = le16_to_cpu(mac->ac[aci].tx_op); - rtl92c_dm_init_edca_turbo(hw); - u4b_ac_param = (u32) mac->ac[aci].aifs; - u4b_ac_param |= (u32) ((cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET); - u4b_ac_param |= (u32) ((cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET); - u4b_ac_param |= (u32) (tx_op << AC_PARAM_TXOP_OFFSET); - RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG, - ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n", - aci, u4b_ac_param, mac->ac[aci].aifs, cw_min, - cw_max, tx_op)); switch (aci) { case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param); + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); break; case AC0_BE: - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); + /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ break; case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param); + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); break; case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param); + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); break; default: RT_ASSERT(false, ("invalid aci: %d !\n", aci)); @@ -1227,8 +1201,10 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 u1b_tmp; + u32 u4b_tmp; rtlpriv->intf_ops->enable_aspm(hw); rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); @@ -1243,13 +1219,27 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | - (u1b_tmp << 8)); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) { + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 | + (u1b_tmp << 8)); + } else { + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | + (u1b_tmp << 8)); + } rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); + u4b_tmp |= 0x03824800; + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); + } else { + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + } + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); } @@ -1327,6 +1317,7 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); + if (add_msr) rtlpci->irq_mask[0] |= add_msr; if (rm_msr) @@ -1582,7 +1573,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) ("RTL819X Not boot from eeprom, check it !!")); } - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"), + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), hwinfo, HWSET_MAX_SIZE); eeprom_id = *((u16 *)&hwinfo[0]); @@ -1610,6 +1601,10 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) rtlefuse->autoload_failflag, hwinfo); + rtl8192ce_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; rtlefuse->txpwr_fromeprom = true; @@ -1618,6 +1613,9 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid)); + /* set channel paln to world wide 13 */ + rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; + if (rtlhal->oem_id == RT_CID_DEFAULT) { switch (rtlefuse->eeprom_oemid) { case EEPROM_CID_DEFAULT: @@ -1701,30 +1699,36 @@ void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw) } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); } - _rtl92ce_hal_customized_behavior(hw); } -void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) +static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - u32 ratr_value = (u32) mac->basic_rates; - u8 *mcsrate = mac->mcs; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; u8 ratr_index = 0; u8 nmode = mac->ht_enable; - u8 mimo_ps = 1; + u8 mimo_ps = IEEE80211_SMPS_OFF; u16 shortgi_rate; u32 tmp_ratr_value; u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = mac->sgi_40; - u8 curshortgi_20mhz = mac->sgi_20; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; enum wireless_mode wirelessmode = mac->mode; - ratr_value |= ((*(u16 *) (mcsrate))) << 12; - + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); switch (wirelessmode) { case WIRELESS_MODE_B: if (ratr_value & 0x0000000c) @@ -1738,7 +1742,7 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) case WIRELESS_MODE_N_24G: case WIRELESS_MODE_N_5G: nmode = 1; - if (mimo_ps == 0) { + if (mimo_ps == IEEE80211_SMPS_STATIC) { ratr_value &= 0x0007F005; } else { u32 ratr_mask; @@ -1761,10 +1765,19 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) break; } - ratr_value &= 0x0FFFFFFF; + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && + (rtlpcipriv->bt_coexist.bt_cur_state) && + (rtlpcipriv->bt_coexist.bt_ant_isolation) && + ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) || + (rtlpcipriv->bt_coexist.bt_service == BT_BUSY))) + ratr_value &= 0x0fffcfc0; + else + ratr_value &= 0x0FFFFFFF; - if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz && - curshortgi_20mhz))) { + if (nmode && ((curtxbw_40mhz && + curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { ratr_value |= 0x10000000; tmp_ratr_value = (ratr_value >> 12); @@ -1784,24 +1797,42 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0))); } -void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) +static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u32 ratr_bitmap = (u32) mac->basic_rates; - u8 *p_mcsrate = mac->mcs; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; u8 ratr_index; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = mac->sgi_40; - u8 curshortgi_20mhz = mac->sgi_20; - enum wireless_mode wirelessmode = mac->mode; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; bool shortgi = false; u8 rate_mask[5]; u8 macid = 0; - u8 mimops = 1; - - ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12); + u8 mimo_ps = IEEE80211_SMPS_OFF; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); switch (wirelessmode) { case WIRELESS_MODE_B: ratr_index = RATR_INX_WIRELESS_B; @@ -1828,7 +1859,7 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) case WIRELESS_MODE_N_5G: ratr_index = RATR_INX_WIRELESS_NGB; - if (mimops == 0) { + if (mimo_ps == IEEE80211_SMPS_STATIC) { if (rssi_level == 1) ratr_bitmap &= 0x00070000; else if (rssi_level == 2) @@ -1892,8 +1923,8 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) } RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("ratr_bitmap :%x\n", ratr_bitmap)); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); + *(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | + (ratr_index << 28)); rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, " "ratr_val:%x, %x:%x:%x:%x:%x\n", @@ -1902,6 +1933,20 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) rate_mask[2], rate_mask[3], rate_mask[4])); rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); + + if (macid != 0) + sta_entry->ratr_index = ratr_index; +} + +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92ce_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92ce_update_hal_rate_table(hw, sta); } void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) @@ -1919,7 +1964,7 @@ void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); } -bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -1929,7 +1974,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) bool actuallyset = false; unsigned long flag; - if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) + if (rtlpci->being_init_adapter) return false; if (ppsc->swrf_processing) @@ -1946,12 +1991,6 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) cur_rfstate = ppsc->rfpwr_state; - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG)&~(BIT(3))); @@ -1976,38 +2015,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) } if (actuallyset) { - if (e_rfpowerstate_toset == ERFON) { - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - } - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - - if (e_rfpowerstate_toset == ERFOFF) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - } - - } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { + } else { if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - } - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } else { spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); @@ -2086,15 +2100,31 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, macaddr = cam_const_broad; entry_id = key_index; } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + ("Can not find free hw" + " security cam entry\n")); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + key_index = PAIRWISE_KEYIDX; - entry_id = CAM_PAIRWISE_KEY_POSITION; is_pairwise = true; } } if (rtlpriv->sec.key_len[key_index] == 0) { RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("delete one entry\n")); + ("delete one entry, entry_id is %d\n", + entry_id)); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); } else { RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, @@ -2146,3 +2176,132 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, } } } + +static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + rtlpcipriv->bt_coexist.bt_coexistence = + rtlpcipriv->bt_coexist.eeprom_bt_coexist; + rtlpcipriv->bt_coexist.bt_ant_num = + rtlpcipriv->bt_coexist.eeprom_bt_ant_num; + rtlpcipriv->bt_coexist.bt_coexist_type = + rtlpcipriv->bt_coexist.eeprom_bt_type; + + if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) + rtlpcipriv->bt_coexist.bt_ant_isolation = + rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation; + else + rtlpcipriv->bt_coexist.bt_ant_isolation = + rtlpcipriv->bt_coexist.reg_bt_iso; + + rtlpcipriv->bt_coexist.bt_radio_shared_type = + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared; + + if (rtlpcipriv->bt_coexist.bt_coexistence) { + + if (rtlpcipriv->bt_coexist.reg_bt_sco == 1) + rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2) + rtlpcipriv->bt_coexist.bt_service = BT_SCO; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4) + rtlpcipriv->bt_coexist.bt_service = BT_BUSY; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5) + rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY; + else + rtlpcipriv->bt_coexist.bt_service = BT_IDLE; + + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + rtlpcipriv->bt_coexist.bt_rssi_state = 0xff; + } +} + +void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + u8 value; + + if (!auto_load_fail) { + rtlpcipriv->bt_coexist.eeprom_bt_coexist = + ((hwinfo[RF_OPTION1] & 0xe0) >> 5); + value = hwinfo[RF_OPTION4]; + rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1); + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1); + rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = + ((value & 0x10) >> 4); + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = + ((value & 0x20) >> 5); + } else { + rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; + rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; + rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0; + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; + } + + rtl8192ce_bt_var_init(hw); +} + +void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpcipriv->bt_coexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpcipriv->bt_coexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpcipriv->bt_coexist.reg_bt_sco = 0; +} + + +void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + u8 u1_tmp; + + if (rtlpcipriv->bt_coexist.bt_coexistence && + ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || + rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) { + + if (rtlpcipriv->bt_coexist.bt_ant_isolation) + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + + u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & + BIT_OFFSET_LEN_MASK_32(0, 1); + u1_tmp = u1_tmp | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); + + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); + + /* Config to 1T1R. */ + if (rtlphy->rf_type == RF_1T1R) { + u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); + + u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); + } + } +} + +void rtl92ce_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl92ce_resume(struct ieee80211_hw *hw) +{ +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h index a3dfdb63516..07dbe3e340a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h @@ -30,7 +30,18 @@ #ifndef __RTL92CE_HW_H__ #define __RTL92CE_HW_H__ -#define H2C_RA_MASK 6 +static inline u8 _rtl92c_get_chnl_group(u8 chnl) +{ + u8 group; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + return group; +} void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); @@ -41,28 +52,27 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw); void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw); -void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); -bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); -int rtl92c_download_fw(struct ieee80211_hw *hw); -void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); -void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); -bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw); + +void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); +void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); +void rtl92ce_suspend(struct ieee80211_hw *hw); +void rtl92ce_resume(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c index d21b934b5c3..9dd1ed7b642 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -106,12 +106,11 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); } -void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, +static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); @@ -146,7 +145,7 @@ void rtl92ce_led_control(struct ieee80211_hw *hw, ledaction == LED_CTL_POWER_ON)) { return; } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d.\n", ledaction)); _rtl92ce_sw_led_control(hw, ledaction); } diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h index 94332b3af5b..7dfccea2095 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h @@ -34,7 +34,5 @@ void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); -void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index d0541e8c601..73ae8a43184 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -38,7 +38,9 @@ #include "dm.h" #include "table.h" -u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); + +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -73,9 +75,47 @@ u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, return readback_value; } +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is92c = IS_92C_SERIAL(rtlhal->version); + bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); + + if (is92c) + rtl_write_byte(rtlpriv, 0x14, 0x71); + return rtstatus; +} + +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regvaldw; + u8 reg_hwparafile = 1; + + _rtl92c_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTn | FEN_BBRSTB); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); + rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); + if (reg_hwparafile == 1) + rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -121,45 +161,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, bitmask, data, rfpath)); } -bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool is92c = IS_92C_SERIAL(rtlhal->version); - bool rtstatus = _rtl92ce_phy_config_mac_with_headerfile(hw); - - if (is92c) - rtl_write_byte(rtlpriv, 0x14, 0x71); - return rtstatus; -} - -bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u32 regvaldw; - u8 reg_hwparafile = 1; - - _rtl92c_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTn | FEN_BBRSTB); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); - rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); - if (reg_hwparafile == 1) - rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); - return rtstatus; -} - -bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 i; @@ -177,7 +179,7 @@ bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) } bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { int i; u32 *phy_regarray_table; @@ -236,7 +238,7 @@ bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, } bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { struct rtl_priv *rtlpriv = rtl_priv(hw); int i; @@ -274,7 +276,7 @@ bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, return true; } -bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath) { @@ -364,74 +366,6 @@ bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } -void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - ("Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz")) - - if (is_hal_stop(rtlhal)) - return; - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - - reg_prsr_rsc = - (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); - break; - } - rtl92c_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); -} - void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; @@ -477,6 +411,36 @@ void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } } +static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + u32 u4b_tmp; + u8 delay = 5; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4b_tmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + ("Switch RF timeout !!!.\n")); + return; + } + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { @@ -523,33 +487,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, break; } case ERFOFF:{ - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0 || - queue_id == BEACON_QUEUE) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("eRf Off/Sleep: %d times " - "TcbBusyQueue[%d] " - "=%d before doze!\n", (i + 1), - queue_id, - skb_queue_len(&ring->queue))); - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("\nERFOFF: %d times " - "TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue))); - break; - } - } if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, ("IPS Set eRf nic disable\n")); @@ -581,6 +518,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, "TcbBusyQueue[%d] =%d before " "doze!\n", (i + 1), queue_id, skb_queue_len(&ring->queue))); + udelay(10); i++; } @@ -599,7 +537,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies))); ppsc->last_sleep_jiffies = jiffies; - _rtl92c_phy_set_rf_sleep(hw); + _rtl92ce_phy_set_rf_sleep(hw); break; } default: @@ -614,10 +552,11 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, return bresult; } -bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = false; if (rfpwr_state == ppsc->rfpwr_state) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index a37267e3fc2..ad580852cc7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -39,6 +39,7 @@ #define RT_CANNOT_IO(hw) false #define HIGHPOWER_RADIOA_ARRAYLEN 22 +#define IQK_ADDA_REG_NUM 16 #define MAX_TOLERANCE 5 #define IQK_DELAY_TIME 1 @@ -56,6 +57,8 @@ #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 +#define IQK_DELAY_TIME 1 + #define RF90_PATH_MAX 2 #define CT_OFFSET_MAC_ADDR 0X16 @@ -76,7 +79,7 @@ #define CT_OFFSET_CUSTOMER_ID 0x7F #define RTL92C_MAX_PATH_NUM 2 -#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 + enum swchnlcmd_id { CMDID_END, CMDID_SET_TXPOWEROWER_LEVEL, @@ -184,43 +187,44 @@ struct tx_power_struct { u32 mcs_original_offset[4][16]; }; -extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); -extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm); -extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, +void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); -extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); +void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, @@ -237,9 +241,6 @@ u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data); void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); @@ -250,5 +251,11 @@ bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index b0868a61384..598cecc63f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h @@ -72,6 +72,7 @@ #define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ #define REG_MULTI_FUNC_CTRL 0x0068 + #define REG_MCUFWDL 0x0080 #define REG_HMEBOX_EXT_0 0x0088 @@ -542,7 +543,7 @@ #define IMR_OCPINT BIT(1) #define IMR_WLANOFF BIT(0) -#define HWSET_MAX_SIZE 128 +#define EFUSE_REAL_CONTENT_LEN 512 #define EEPROM_DEFAULT_TSSI 0x0 #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 @@ -656,6 +657,7 @@ #define STOPBE BIT(1) #define STOPBK BIT(0) +#define RCR_APPFCS BIT(31) #define RCR_APP_FCS BIT(31) #define RCR_APP_MIC BIT(30) #define RCR_APP_ICV BIT(29) @@ -688,6 +690,7 @@ #define REG_USB_INFO 0xFE17 #define REG_USB_SPECIAL_OPTION 0xFE55 + #define REG_USB_DMA_AGG_TO 0xFE5B #define REG_USB_AGG_TO 0xFE5C #define REG_USB_AGG_TH 0xFE5D @@ -775,7 +778,6 @@ #define BOOT_FROM_EEPROM BIT(4) #define EEPROM_EN BIT(5) -#define EEPROMSEL BOOT_FROM_EEPROM #define AFE_BGEN BIT(0) #define AFE_MBEN BIT(1) @@ -901,28 +903,7 @@ #define BD_PKG_SEL BIT(25) #define BD_HCI_SEL BIT(26) #define TYPE_ID BIT(27) - -/* REG_GPIO_OUTSTS (For RTL8723 only) */ -#define EFS_HCI_SEL (BIT(0)|BIT(1)) -#define PAD_HCI_SEL (BIT(2)|BIT(3)) -#define HCI_SEL (BIT(4)|BIT(5)) -#define PKG_SEL_HCI BIT(6) -#define FEN_GPS BIT(7) -#define FEN_BT BIT(8) -#define FEN_WL BIT(9) -#define FEN_PCI BIT(10) -#define FEN_USB BIT(11) -#define BTRF_HWPDN_N BIT(12) -#define WLRF_HWPDN_N BIT(13) -#define PDN_BT_N BIT(14) -#define PDN_GPS_N BIT(15) -#define BT_CTL_HWPDN BIT(16) -#define GPS_CTL_HWPDN BIT(17) -#define PPHY_SUSB BIT(20) -#define UPHY_SUSB BIT(21) -#define PCI_SUSEN BIT(22) -#define USB_SUSEN BIT(23) -#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) +#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) #define CHIP_VER_RTL_MASK 0xF000 #define CHIP_VER_RTL_SHIFT 12 @@ -1077,6 +1058,7 @@ #define _RARF_RC8(x) (((x) & 0x1F) << 24) #define AC_PARAM_TXOP_OFFSET 16 +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 #define AC_PARAM_ECW_MAX_OFFSET 12 #define AC_PARAM_ECW_MIN_OFFSET 8 #define AC_PARAM_AIFS_OFFSET 0 @@ -1221,33 +1203,11 @@ #define EPROM_CMD_CONFIG 0x3 #define EPROM_CMD_LOAD 1 -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -/* REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ -/* Enable GPIO[9] as WiFi HW PDn source */ #define WL_HWPDN_EN BIT(0) -/* WiFi HW PDn polarity control */ -#define WL_HWPDN_SL BIT(1) -/* WiFi function enable */ -#define WL_FUNC_EN BIT(2) -/* Enable GPIO[9] as WiFi RF HW PDn source */ -#define WL_HWROF_EN BIT(3) -/* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_EN BIT(16) -/* BT HW PDn polarity control */ -#define BT_HWPDN_SL BIT(17) -/* BT function enable */ -#define BT_FUNC_EN BIT(18) -/* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define BT_HWROF_EN BIT(19) -/* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_EN BIT(20) -/* GPS HW PDn polarity control */ -#define GPS_HWPDN_SL BIT(21) -/* GPS function enable */ -#define GPS_FUNC_EN BIT(22) + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) #define RPMAC_RESET 0x100 #define RPMAC_TXSTART 0x104 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c index e301b12e281..90d0f2cf3b2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -34,9 +34,9 @@ #include "rf.h" #include "dm.h" -static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); +static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); -void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -62,7 +62,7 @@ void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) } void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) + u8 *ppowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -128,8 +128,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tmpval = tx_agc[RF90_PATH_A] >> 8; - if (mac->mode == WIRELESS_MODE_B) - tmpval = tmpval & 0xff00ffff; + tmpval = tmpval & 0xff00ffff; rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); @@ -440,16 +439,17 @@ bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw) else rtlphy->num_total_rfpath = 2; - return _rtl92c_phy_rf6052_config_parafile(hw); + return _rtl92ce_phy_rf6052_config_parafile(hw); + } -static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); u32 u4_regvalue = 0; u8 rfpath; - bool rtstatus; + bool rtstatus = true; struct bb_reg_def *pphyreg; for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { @@ -484,12 +484,12 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) switch (rfpath) { case RF90_PATH_A: - rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, - (enum radio_path) rfpath); + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); break; case RF90_PATH_B: - rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, - (enum radio_path) rfpath); + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); break; case RF90_PATH_C: break; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h index 3aa520c1c17..39ff0368598 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h @@ -34,14 +34,11 @@ #define RF6052_MAX_REG 0x3F #define RF6052_MAX_PATH 2 -extern void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); -bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); - +extern void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +extern void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +extern void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +extern bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index f4e2f3dccca..390bbb5ee11 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -42,10 +42,58 @@ #include "trx.h" #include "led.h" +static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + int rtl92c_init_sw_vars(struct ieee80211_hw *hw) { + int err; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + const struct firmware *firmware; + + rtl8192ce_bt_reg_init(hw); rtlpriv->dm.dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; @@ -53,7 +101,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->dm.thermalvalue = 0; rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - rtlpci->receive_config = (RCR_APP_FCS | + /* compatible 5G band 88ce just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | RCR_AMF | RCR_ADF | RCR_APP_MIC | @@ -76,13 +129,49 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0); - rtlpriv->rtlhal.pfirmware = (u8 *) vmalloc(0x4000); + /* for LPS & IPS */ + rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; + rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 */ + rtl92c_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); if (!rtlpriv->rtlhal.pfirmware) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Can't alloc buffer for fw.\n")); return 1; } + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to request firmware!\n")); + return 1; + } + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return 1; + } + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); + return 0; } @@ -103,17 +192,19 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .interrupt_recognized = rtl92ce_interrupt_recognized, .hw_init = rtl92ce_hw_init, .hw_disable = rtl92ce_card_disable, + .hw_suspend = rtl92ce_suspend, + .hw_resume = rtl92ce_resume, .enable_interrupt = rtl92ce_enable_interrupt, .disable_interrupt = rtl92ce_disable_interrupt, .set_network_type = rtl92ce_set_network_type, + .set_chk_bssid = rtl92ce_set_check_bssid, .set_qos = rtl92ce_set_qos, .set_bcn_reg = rtl92ce_set_beacon_related_registers, .set_bcn_intv = rtl92ce_set_beacon_interval, .update_interrupt_mask = rtl92ce_update_interrupt_mask, .get_hw_reg = rtl92ce_get_hw_reg, .set_hw_reg = rtl92ce_set_hw_reg, - .update_rate_table = rtl92ce_update_hal_rate_table, - .update_rate_mask = rtl92ce_update_hal_rate_mask, + .update_rate_tbl = rtl92ce_update_hal_rate_tbl, .fill_tx_desc = rtl92ce_tx_fill_desc, .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, .query_rx_desc = rtl92ce_rx_query_desc, @@ -123,7 +214,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .switch_channel = rtl92c_phy_sw_chnl, .dm_watchdog = rtl92c_dm_watchdog, .scan_operation_backup = rtl92c_phy_scan_operation_backup, - .set_rf_power_state = rtl92ce_phy_set_rf_power_state, + .set_rf_power_state = rtl92c_phy_set_rf_power_state, .led_control = rtl92ce_led_control, .set_desc = rtl92ce_set_desc, .get_desc = rtl92ce_get_desc, @@ -133,24 +224,27 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .init_sw_leds = rtl92ce_init_sw_leds, .get_bbreg = rtl92c_phy_query_bb_reg, .set_bbreg = rtl92c_phy_set_bb_reg, - .get_rfreg = rtl92ce_phy_query_rf_reg, .set_rfreg = rtl92ce_phy_set_rf_reg, - .cmd_send_packet = _rtl92c_cmd_send_packet, + .get_rfreg = rtl92c_phy_query_rf_reg, .phy_rf6052_config = rtl92ce_phy_rf6052_config, .phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower, .phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower, .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, - .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, }; static struct rtl_mod_params rtl92ce_mod_params = { - .sw_crypto = 0, + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = false, + .fwctrl_lps = true, }; static struct rtl_hal_cfg rtl92ce_hal_cfg = { + .bar_id = 2, + .write_readback = true, .name = "rtl92c_pci", .fw_name = "rtlwifi/rtl8192cfw.bin", .ops = &rtl8192ce_hal_ops, @@ -174,6 +268,8 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, .maps[EFUSE_ANA8M] = EFUSE_ANA8M, .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, .maps[RWCAM] = REG_CAMCMD, .maps[WCAMI] = REG_CAMWRITE, @@ -238,7 +334,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; -static struct pci_device_id rtl92ce_pci_ids[] __devinitdata = { +DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, @@ -256,7 +352,13 @@ MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); +module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); +module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); +module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); +MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); +MODULE_PARM_DESC(fwlps, "using linked fw control power save " + "(default 1 is open)\n"); static struct pci_driver rtl92ce_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h index 36e657668c1..b7dc3263e43 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h @@ -33,19 +33,9 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw); void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); void rtl92c_init_var_map(struct ieee80211_hw *hw); -bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb); -void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); + u8 configtype); bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask); -void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); + u8 configtype); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index aa2b5815600..54b2bd53d36 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -36,42 +36,16 @@ #include "trx.h" #include "led.h" -static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc, - unsigned int - skb_queue) +static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) { - enum rtl_desc_qsel qsel; + __le16 fc = rtl_get_fc(skb); - if (unlikely(ieee80211_is_beacon(fc))) { - qsel = QSLT_BEACON; - return qsel; - } - - if (ieee80211_is_mgmt(fc)) { - qsel = QSLT_MGNT; - return qsel; - } + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc)) + return QSLT_MGNT; - switch (skb_queue) { - case VO_QUEUE: - qsel = QSLT_VO; - break; - case VI_QUEUE: - qsel = QSLT_VI; - break; - case BE_QUEUE: - qsel = QSLT_BE; - break; - case BK_QUEUE: - qsel = QSLT_BK; - break; - default: - qsel = QSLT_BE; - RT_ASSERT(false, ("BE queue, skb_queue:%d," - " set qsel = 0x%X\n", skb_queue, QSLT_BE)); - break; - } - return qsel; + return skb->priority; } static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) @@ -255,6 +229,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, u8 evm, pwdb_all, rf_rx_num = 0; u8 i, max_spatial_stream; u32 rssi, total_rssi = 0; + bool in_powersavemode = false; bool is_cck_rate; is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); @@ -270,9 +245,13 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, u8 report, cck_highpwr; cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); + if (!in_powersavemode) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; report = cck_buf->cck_agc_rpt & 0xc0; @@ -398,6 +377,7 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) { + rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX; last_rssi = @@ -424,10 +404,6 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, if (!pstats->is_cck && pstats->packet_toself) { for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; rfpath++) { - - if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) - continue; - if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { rtlpriv->stats.rx_rssi_percentage[rfpath] = pstats->rx_mimo_signalstrength[rfpath]; @@ -723,7 +699,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index) + u8 hw_queue, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -732,16 +708,9 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, bool defaultadapter = true; struct ieee80211_sta *sta; u8 *pdesc = (u8 *) pdesc_tx; - struct rtl_tcb_desc tcb_desc; - u8 *qc = ieee80211_get_qos_ctl(hdr); - u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; __le16 fc = hdr->frame_control; - u8 rate_flag = info->control.rates[0].flags; - - enum rtl_desc_qsel fw_qsel = - _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index); - + u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); bool firstseg = ((hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); @@ -751,56 +720,68 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + u8 bw_40 = 0; + + rcu_read_lock(); + sta = get_sta(hw, mac->vif, mac->bssid); + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } if (firstseg) { SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate); + SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); - if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && - info->flags & IEEE80211_TX_CTL_AMPDU) { + if (info->flags & IEEE80211_TX_CTL_AMPDU) { SET_TX_DESC_AGG_BREAK(pdesc, 1); SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); } SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable && - !tcb_desc. + SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && + !tcb_desc-> cts_enable) ? 1 : 0)); SET_TX_DESC_HW_RTS_ENABLE(pdesc, - ((tcb_desc.rts_enable - || tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); + ((tcb_desc->rts_enable + || tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate); + SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc); + SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? - (tcb_desc.rts_use_shortpreamble ? 1 : 0) - : (tcb_desc.rts_use_shortgi ? 1 : 0))); + ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); - if (mac->bw_40) { - if (tcb_desc.packet_bw) { + if (bw_40) { + if (tcb_desc->packet_bw) { SET_TX_DESC_DATA_BW(pdesc, 1); SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); } else { SET_TX_DESC_DATA_BW(pdesc, 0); - - if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); } } else { SET_TX_DESC_DATA_BW(pdesc, 0); @@ -810,13 +791,10 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); } - rcu_read_unlock(); if (info->control.hw_key) { struct ieee80211_key_conf *keyconf = @@ -844,7 +822,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { @@ -855,24 +833,24 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, } } } + rcu_read_unlock(); SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id); + SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index); + SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); } - if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && - ppsc->fwctrl_lps) { + if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { SET_TX_DESC_HWSEQ_EN(pdesc, 1); SET_TX_DESC_PKT_ID(pdesc, 8); @@ -923,7 +901,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); SET_TX_DESC_RATE_ID(pdesc, 7); SET_TX_DESC_MACID(pdesc, 0); @@ -1021,7 +999,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) return ret; } -void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); if (hw_queue == BEACON_QUEUE) { @@ -1032,35 +1010,3 @@ void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) } } -bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - u8 own; - unsigned long flags; - struct sk_buff *pskb = NULL; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - - pskb = __skb_dequeue(&ring->queue); - if (pskb) - kfree_skb(pskb); - - pdesc = &ring->desc[0]; - own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); - - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); - - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - - return true; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index b0b0b13dd0a..0f117713750 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -724,17 +724,16 @@ struct rx_desc_92c { void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc, struct ieee80211_tx_info *info, - struct sk_buff *skb, unsigned int qsel); + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, u8 *pdesc, struct sk_buff *skb); void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); -void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue); +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool b_firstseg, bool b_lastseg, struct sk_buff *skb); -bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); - #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index e43be254782..52e2af58c1e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -39,6 +39,7 @@ #include "mac.h" #include "dm.h" #include "hw.h" +#include "../rtl8192ce/hw.h" #include "trx.h" #include "led.h" #include "table.h" @@ -605,10 +606,10 @@ void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) if (!IS_NORMAL_CHIP(rtlhal->version)) return; tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ? + rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n", - (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE")); + (tmp_u1b & BOOT_FROM_EEPROM) ? "EERROM" : "EFUSE")); rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n", (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!")); @@ -977,7 +978,7 @@ static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APP_FCS | + mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); rtl_write_dword(rtlpriv, REG_RCR, mac->rx_conf); @@ -2182,7 +2183,9 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } } -void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw) +void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h index 62af555bb61..32f85cba106 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h @@ -98,13 +98,14 @@ void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw); +void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level); void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -u8 _rtl92c_get_chnl_group(u8 chnl); int rtl92c_download_fw(struct ieee80211_hw *hw); void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 4e020e654e6..9a3d0239e27 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -38,7 +38,7 @@ #include "table.h" u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) + enum radio_path rfpath, u32 regaddr, u32 bitmask) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 original_value, readback_value, bitshift; @@ -64,8 +64,8 @@ u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, } void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -163,7 +163,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) } bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { int i; u32 *phy_regarray_table; @@ -223,7 +223,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, } bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -459,7 +459,7 @@ void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } } -bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, +static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -595,7 +595,7 @@ bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, } bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) + enum rf_pwrstate rfpwr_state) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool bresult = false; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h index 06299559ab6..ff81a61729d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h @@ -34,3 +34,17 @@ bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); void rtl92c_phy_set_io(struct ieee80211_hw *hw); bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw); +u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask); +void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); +bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); +bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 1c79c226f14..c7576ec4744 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -62,7 +62,7 @@ void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) } void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) + u8 *ppowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -389,7 +389,7 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, } void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) + u8 *ppowerlevel, u8 channel) { u32 writeVal[2], powerBase0[2], powerBase1[2]; u8 index = 0; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h index 86c2728cfa0..500a2094b6b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h @@ -43,5 +43,9 @@ extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); +void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 71244a38d49..bee7c1480f6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -94,7 +94,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { .update_interrupt_mask = rtl92cu_update_interrupt_mask, .get_hw_reg = rtl92cu_get_hw_reg, .set_hw_reg = rtl92cu_set_hw_reg, - .update_rate_table = rtl92cu_update_hal_rate_table, + .update_rate_tbl = rtl92cu_update_hal_rate_table, .update_rate_mask = rtl92cu_update_hal_rate_mask, .fill_tx_desc = rtl92cu_tx_fill_desc, .fill_fake_txdesc = rtl92cu_fill_fake_txdesc, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 3f0cb81c424..79c98f62175 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -498,14 +498,14 @@ static void _rtl_tx_desc_checksum(u8 *txdesc) void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index) + u8 queue_index, + struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta; - struct rtl_tcb_desc tcb_desc; + struct ieee80211_sta *sta = info->control.sta = info->control.sta; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; @@ -517,15 +517,15 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, u8 *txdesc; seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); memset(txdesc, 0, RTL_TX_HEADER_SIZE); SET_TX_DESC_PKT_SIZE(txdesc, pktlen); SET_TX_DESC_LINIP(txdesc, 0); SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate); - if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) + SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(txdesc, 1); if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -535,21 +535,21 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_AGG_BREAK(txdesc, 1); } SET_TX_DESC_SEQ(txdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable && - !tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable || - tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate); + SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && + !tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || + tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); + SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); SET_TX_DESC_RTS_BW(txdesc, 0); - SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc); + SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(txdesc, - ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? - (tcb_desc.rts_use_shortpreamble ? 1 : 0) - : (tcb_desc.rts_use_shortgi ? 1 : 0))); + ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); if (mac->bw_40) { - if (tcb_desc.packet_bw) { + if (tcb_desc->packet_bw) { SET_TX_DESC_DATA_BW(txdesc, 1); SET_TX_DESC_DATA_SC(txdesc, 3); } else { @@ -590,7 +590,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); SET_TX_DESC_DISABLE_FB(txdesc, 0); - SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, @@ -600,11 +600,11 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, } } if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id); + SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index); + SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); } if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && ppsc->fwctrl_lps) { @@ -656,7 +656,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; - memset(pdesc, 0, RTL_TX_HEADER_SIZE); + memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); if (firstseg) SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h index b396d46edbb..53de5f66e24 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h @@ -37,6 +37,8 @@ #define RTL92C_SIZE_MAX_RX_BUFFER 15360 /* 8192 */ #define RX_DRV_INFO_SIZE_UNIT 8 +#define RTL_AGG_ON 1 + enum usb_rx_agg_mode { USB_RX_AGG_DISABLE, USB_RX_AGG_DMA, @@ -419,7 +421,8 @@ struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *, void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index); + u8 queue_index, + struct rtl_tcb_desc *tcb_desc); void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, u32 buffer_len, bool bIsPsPoll); void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index f5d85735d64..a9367eba1ea 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -852,6 +852,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rtl_tx_desc *pdesc = NULL; + struct rtl_tcb_desc tcb_desc; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; u8 *pda_addr = hdr->addr1; @@ -860,8 +861,17 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, u8 tid = 0; u16 seq_number = 0; - if (ieee80211_is_mgmt(fc)) - rtl_tx_mgmt_proc(hw, skb); + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); + rtl_ips_nic_on(hw); + } + + if (rtlpriv->psc.sw_ps_enabled) { + if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && + !ieee80211_has_pm(fc)) + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } + rtl_action_proc(hw, skb, true); if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; @@ -878,7 +888,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, seq_number <<= 4; } rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb, - hw_queue); + hw_queue, &tcb_desc); if (!ieee80211_has_morefrags(hdr->frame_control)) { if (qc) mac->tids[tid].seq_number = seq_number; @@ -887,7 +897,8 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); } -static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb, + struct rtl_tcb_desc *dummy) { struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h index abadfe918d3..d2a63fb3e1e 100644 --- a/drivers/net/wireless/rtlwifi/usb.h +++ b/drivers/net/wireless/rtlwifi/usb.h @@ -31,6 +31,8 @@ #include <linux/usb.h> #include <linux/skbuff.h> +#define RTL_RX_DESC_SIZE 24 + #define RTL_USB_DEVICE(vend, prod, cfg) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 2713efe07ce..693395ee98f 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -68,6 +68,8 @@ #define QBSS_LOAD_SIZE 5 #define MAX_WMMELE_LENGTH 64 +#define TOTAL_CAM_ENTRY 32 + /*slot time for 11g. */ #define RTL_SLOT_TIME_9 9 #define RTL_SLOT_TIME_20 20 @@ -94,8 +96,10 @@ #define CHANNEL_GROUP_MAX_5G 9 #define CHANNEL_MAX_NUMBER_2G 14 #define AVG_THERMAL_NUM 8 +#define MAX_TID_COUNT 9 /* for early mode */ +#define FCS_LEN 4 #define EM_HDR_LEN 8 enum intf_type { INTF_PCI = 0, @@ -159,6 +163,8 @@ enum hardware_type { (IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) #define IS_HARDWARE_TYPE_8723(rtlhal) \ (IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) +#define IS_HARDWARE_TYPE_8723U(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) enum scan_operation_backup_opt { SCAN_OPT_BACKUP = 0, @@ -297,6 +303,9 @@ enum hw_variables { HW_VAR_DATA_FILTER, }; +#define HWSET_MAX_SIZE 128 +#define EFUSE_MAX_SECTION 16 + enum _RT_MEDIA_STATUS { RT_MEDIA_DISCONNECT = 0, RT_MEDIA_CONNECT = 1 @@ -843,6 +852,7 @@ struct rtl_phy { bool apk_done; u32 reg_rf3c[2]; /* pathA / pathB */ + /* bfsync */ u8 framesync; u32 framesync_c34; @@ -852,6 +862,10 @@ struct rtl_phy { }; #define MAX_TID_COUNT 9 +#define RTL_AGG_STOP 0 +#define RTL_AGG_PROGRESS 1 +#define RTL_AGG_START 2 +#define RTL_AGG_OPERATIONAL 3 #define RTL_AGG_OFF 0 #define RTL_AGG_ON 1 #define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 @@ -871,6 +885,13 @@ struct rtl_tid_data { struct rtl_ht_agg agg; }; +struct rtl_sta_info { + u8 ratr_index; + u8 wireless_mode; + u8 mimo_ps; + struct rtl_tid_data tids[MAX_TID_COUNT]; +} __packed; + struct rtl_priv; struct rtl_io { struct device *dev; @@ -894,6 +915,7 @@ struct rtl_io { u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len, u8 *pdata); + }; struct rtl_mac { @@ -916,6 +938,8 @@ struct rtl_mac { int n_channels; int n_bitrates; + bool offchan_deley; + /*filters */ u32 rx_conf; u16 rx_mgt_filter; @@ -1032,7 +1056,9 @@ struct rtl_security { enum rt_enc_alg pairwise_enc_algorithm; /*Encryption Algorithm for Brocast/Multicast */ enum rt_enc_alg group_enc_algorithm; - + /*Cam Entry Bitmap */ + u32 hwsec_cam_bitmap; + u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; /*local Key buffer, indx 0 is for pairwise key 1-4 is for agoup key. */ u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; @@ -1053,7 +1079,7 @@ struct rtl_dm { bool current_turbo_edca; bool is_any_nonbepkts; /*out dm */ bool is_cur_rdlstate; - bool txpower_trackingInit; + bool txpower_trackinginit; bool disable_framebursting; bool cck_inch14; bool txpower_tracking; @@ -1079,7 +1105,6 @@ struct rtl_dm { bool disable_tx_int; char ofdm_index[2]; char cck_index; - u8 power_index_backup[6]; }; #define EFUSE_MAX_LOGICAL_SIZE 256 @@ -1175,6 +1200,7 @@ struct rtl_ps_ctl { * otherwise Offset[560h] = 0x00. * */ bool support_aspm; + bool support_backdoor; /*for LPS */ @@ -1201,7 +1227,6 @@ struct rtl_ps_ctl { /*just for PCIE ASPM */ u8 const_amdpci_aspm; - bool pwrdown_mode; enum rf_pwrstate inactive_pwrstate; @@ -1282,6 +1307,10 @@ struct rt_link_detect { bool busytraffic; bool higher_busytraffic; bool higher_busyrxtraffic; + + u32 tidtx_in4period[MAX_TID_COUNT][4]; + u32 tidtx_inperiod[MAX_TID_COUNT]; + bool higher_busytxtraffic[MAX_TID_COUNT]; }; struct rtl_tcb_desc { @@ -1344,13 +1373,15 @@ struct rtl_hal_ops { u32 add_msr, u32 rm_msr); void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*update_rate_table) (struct ieee80211_hw *hw); + void (*update_rate_tbl) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); void (*fill_tx_desc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, - struct sk_buff *skb, unsigned int queue_index); - void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 * pDesc, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); + void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, u32 buffer_len, bool bIsPsPoll); void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, @@ -1370,10 +1401,10 @@ struct rtl_hal_ops { enum led_ctl_mode ledaction); void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name); - void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue); + void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); void (*enable_hw_sec) (struct ieee80211_hw *hw); void (*set_key) (struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, + u8 *macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); void (*init_sw_leds) (struct ieee80211_hw *hw); void (*deinit_sw_leds) (struct ieee80211_hw *hw); @@ -1384,6 +1415,7 @@ struct rtl_hal_ops { u32 regaddr, u32 bitmask); void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask, u32 data); + void (*linked_set_reg) (struct ieee80211_hw *hw); bool (*phy_rf6052_config) (struct ieee80211_hw *hw); void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, u8 *powerlevel); @@ -1404,7 +1436,9 @@ struct rtl_intf_ops { int (*adapter_start) (struct ieee80211_hw *hw); void (*adapter_stop) (struct ieee80211_hw *hw); - int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb); + int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc); + void (*flush)(struct ieee80211_hw *hw, bool drop); int (*reset_trx_ring) (struct ieee80211_hw *hw); bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1418,6 +1452,15 @@ struct rtl_intf_ops { struct rtl_mod_params { /* default: 0 = using hardware encryption */ int sw_crypto; + + /* default: 1 = using no linked power save */ + bool inactiveps; + + /* default: 1 = using linked sw power save */ + bool swctrl_lps; + + /* default: 1 = using linked fw power save */ + bool fwctrl_lps; }; struct rtl_hal_usbint_cfg { @@ -1445,6 +1488,7 @@ struct rtl_hal_usbint_cfg { struct rtl_hal_cfg { u8 bar_id; + bool write_readback; char *name; char *fw_name; struct rtl_hal_ops *ops; @@ -1469,7 +1513,6 @@ struct rtl_locks { spinlock_t rf_lock; spinlock_t lps_lock; spinlock_t waitq_lock; - spinlock_t tx_urb_lock; /*Dual mac*/ spinlock_t cck_and_rw_pagea_lock; @@ -1653,13 +1696,23 @@ struct bt_coexist_info { #define EF4BYTE(_val) \ (le32_to_cpu(_val)) +/* Read data from memory */ +#define READEF1BYTE(_ptr) \ + EF1BYTE(*((u8 *)(_ptr))) /* Read le16 data from memory and convert to host ordering */ #define READEF2BYTE(_ptr) \ EF2BYTE(*((u16 *)(_ptr))) +#define READEF4BYTE(_ptr) \ + EF4BYTE(*((u32 *)(_ptr))) +/* Write data to memory */ +#define WRITEEF1BYTE(_ptr, _val) \ + (*((u8 *)(_ptr))) = EF1BYTE(_val) /* Write le16 data to memory in host ordering */ #define WRITEEF2BYTE(_ptr, _val) \ (*((u16 *)(_ptr))) = EF2BYTE(_val) +#define WRITEEF4BYTE(_ptr, _val) \ + (*((u16 *)(_ptr))) = EF2BYTE(_val) /* Create a bit mask * Examples: @@ -1698,6 +1751,25 @@ struct bt_coexist_info { #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ (EF1BYTE(*((u8 *)(__pstart)))) +/*Description: +Translate subfield (continuous bits in little-endian) of 4-byte +value to host byte ordering.*/ +#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_32(__bitlen) \ + ) +#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_16(__bitlen) \ + ) +#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_8(__bitlen) \ + ) + /* Description: * Mask subfield (continuous bits in little-endian) of 4-byte value * and return the result in 4-byte value in host byte ordering. @@ -1721,6 +1793,18 @@ struct bt_coexist_info { /* Description: * Set subfield of little-endian 4-byte value to specified value. */ +#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u32 *)(__pstart)) = EF4BYTE \ + ( \ + LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \ + ); +#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u16 *)(__pstart)) = EF2BYTE \ + ( \ + LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ + ); #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ *((u8 *)(__pstart)) = EF1BYTE \ ( \ @@ -1728,12 +1812,16 @@ struct bt_coexist_info { ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ ); +#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ + (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) + /**************************************** mem access macro define end ****************************************/ #define byte(x, n) ((x >> (8 * n)) & 0xff) +#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) #define RTL_WATCH_DOG_TIME 2000 #define MSECS(t) msecs_to_jiffies(t) #define WLAN_FC_GET_VERS(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_VERS) @@ -1768,6 +1856,15 @@ struct bt_coexist_info { #define container_of_dwork_rtl(x, y, z) \ container_of(container_of(x, struct delayed_work, work), y, z) +#define FILL_OCTET_STRING(_os, _octet, _len) \ + (_os).octet = (u8 *)(_octet); \ + (_os).length = (_len); + +#define CP_MACADDR(des, src) \ + ((des)[0] = (src)[0], (des)[1] = (src)[1],\ + (des)[2] = (src)[2], (des)[3] = (src)[3],\ + (des)[4] = (src)[4], (des)[5] = (src)[5]) + static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) { return rtlpriv->io.read8_sync(rtlpriv, addr); @@ -1786,17 +1883,26 @@ static inline u32 rtl_read_dword(struct rtl_priv *rtlpriv, u32 addr) static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) { rtlpriv->io.write8_async(rtlpriv, addr, val8); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read8_sync(rtlpriv, addr); } static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) { rtlpriv->io.write16_async(rtlpriv, addr, val16); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read16_sync(rtlpriv, addr); } static inline void rtl_write_dword(struct rtl_priv *rtlpriv, u32 addr, u32 val32) { rtlpriv->io.write32_async(rtlpriv, addr, val32); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read32_sync(rtlpriv, addr); } static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, @@ -1855,4 +1961,31 @@ static inline u8 get_rf_type(struct rtl_phy *rtlphy) return rtlphy->rf_type; } +static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) +{ + return (struct ieee80211_hdr *)(skb->data); +} + +static inline __le16 rtl_get_fc(struct sk_buff *skb) +{ + return rtl_get_hdr(skb)->frame_control; +} + +static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) +{ + return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; +} + +static inline u16 rtl_get_tid(struct sk_buff *skb) +{ + return rtl_get_tid_h(rtl_get_hdr(skb)); +} + +static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u8 *bssid) +{ + return ieee80211_find_sta(vif, bssid); +} + #endif |