Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2013  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include <linux/vmalloc.h>
0006 #include <linux/module.h>
0007 
0008 #include "rtl_btc.h"
0009 #include "halbt_precomp.h"
0010 
0011 static struct rtl_btc_ops rtl_btc_operation = {
0012     .btc_init_variables = rtl_btc_init_variables,
0013     .btc_init_variables_wifi_only = rtl_btc_init_variables_wifi_only,
0014     .btc_deinit_variables = rtl_btc_deinit_variables,
0015     .btc_init_hal_vars = rtl_btc_init_hal_vars,
0016     .btc_power_on_setting = rtl_btc_power_on_setting,
0017     .btc_init_hw_config = rtl_btc_init_hw_config,
0018     .btc_init_hw_config_wifi_only = rtl_btc_init_hw_config_wifi_only,
0019     .btc_ips_notify = rtl_btc_ips_notify,
0020     .btc_lps_notify = rtl_btc_lps_notify,
0021     .btc_scan_notify = rtl_btc_scan_notify,
0022     .btc_scan_notify_wifi_only = rtl_btc_scan_notify_wifi_only,
0023     .btc_connect_notify = rtl_btc_connect_notify,
0024     .btc_mediastatus_notify = rtl_btc_mediastatus_notify,
0025     .btc_periodical = rtl_btc_periodical,
0026     .btc_halt_notify = rtl_btc_halt_notify,
0027     .btc_btinfo_notify = rtl_btc_btinfo_notify,
0028     .btc_btmpinfo_notify = rtl_btc_btmpinfo_notify,
0029     .btc_is_limited_dig = rtl_btc_is_limited_dig,
0030     .btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
0031     .btc_is_bt_disabled = rtl_btc_is_bt_disabled,
0032     .btc_special_packet_notify = rtl_btc_special_packet_notify,
0033     .btc_switch_band_notify = rtl_btc_switch_band_notify,
0034     .btc_switch_band_notify_wifi_only = rtl_btc_switch_band_notify_wifionly,
0035     .btc_record_pwr_mode = rtl_btc_record_pwr_mode,
0036     .btc_get_lps_val = rtl_btc_get_lps_val,
0037     .btc_get_rpwm_val = rtl_btc_get_rpwm_val,
0038     .btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
0039     .btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
0040     .btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
0041     .btc_display_bt_coex_info = rtl_btc_display_bt_coex_info,
0042 };
0043 
0044 void rtl_btc_display_bt_coex_info(struct rtl_priv *rtlpriv, struct seq_file *m)
0045 {
0046     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0047 
0048     if (!btcoexist) {
0049         seq_puts(m, "btc_coexist context is NULL!\n");
0050         return;
0051     }
0052 
0053     exhalbtc_display_bt_coex_info(btcoexist, m);
0054 }
0055 
0056 void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
0057 {
0058     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0059     u8 safe_len;
0060 
0061     if (!btcoexist)
0062         return;
0063 
0064     safe_len = sizeof(btcoexist->pwr_mode_val);
0065 
0066     if (safe_len > len)
0067         safe_len = len;
0068 
0069     memcpy(btcoexist->pwr_mode_val, buf, safe_len);
0070 }
0071 
0072 u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
0073 {
0074     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0075 
0076     if (!btcoexist)
0077         return 0;
0078 
0079     return btcoexist->bt_info.lps_val;
0080 }
0081 
0082 u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
0083 {
0084     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0085 
0086     if (!btcoexist)
0087         return 0;
0088 
0089     return btcoexist->bt_info.rpwm_val;
0090 }
0091 
0092 bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
0093 {
0094     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0095 
0096     if (!btcoexist)
0097         return false;
0098 
0099     return btcoexist->bt_info.bt_ctrl_lps;
0100 }
0101 
0102 bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
0103 {
0104     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0105 
0106     if (!btcoexist)
0107         return false;
0108 
0109     return btcoexist->bt_info.bt_lps_on;
0110 }
0111 
0112 void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
0113                u8 *ctrl_agg_size, u8 *agg_size)
0114 {
0115     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0116 
0117     if (!btcoexist) {
0118         *reject_agg = false;
0119         *ctrl_agg_size = false;
0120         return;
0121     }
0122 
0123     if (reject_agg)
0124         *reject_agg = btcoexist->bt_info.reject_agg_pkt;
0125     if (ctrl_agg_size)
0126         *ctrl_agg_size = btcoexist->bt_info.bt_ctrl_agg_buf_size;
0127     if (agg_size)
0128         *agg_size = btcoexist->bt_info.agg_buf_size;
0129 }
0130 
0131 static void rtl_btc_alloc_variable(struct rtl_priv *rtlpriv, bool wifi_only)
0132 {
0133     if (wifi_only)
0134         rtlpriv->btcoexist.wifi_only_context =
0135             kzalloc(sizeof(struct wifi_only_cfg), GFP_KERNEL);
0136     else
0137         rtlpriv->btcoexist.btc_context =
0138             kzalloc(sizeof(struct btc_coexist), GFP_KERNEL);
0139 }
0140 
0141 static void rtl_btc_free_variable(struct rtl_priv *rtlpriv)
0142 {
0143     kfree(rtlpriv->btcoexist.btc_context);
0144     rtlpriv->btcoexist.btc_context = NULL;
0145 
0146     kfree(rtlpriv->btcoexist.wifi_only_context);
0147     rtlpriv->btcoexist.wifi_only_context = NULL;
0148 }
0149 
0150 void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
0151 {
0152     rtl_btc_alloc_variable(rtlpriv, false);
0153 
0154     exhalbtc_initlize_variables(rtlpriv);
0155     exhalbtc_bind_bt_coex_withadapter(rtlpriv);
0156 }
0157 
0158 void rtl_btc_init_variables_wifi_only(struct rtl_priv *rtlpriv)
0159 {
0160     rtl_btc_alloc_variable(rtlpriv, true);
0161 
0162     exhalbtc_initlize_variables_wifi_only(rtlpriv);
0163 }
0164 
0165 void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv)
0166 {
0167     rtl_btc_free_variable(rtlpriv);
0168 }
0169 
0170 void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
0171 {
0172     /* move ant_num, bt_type and single_ant_path to
0173      * exhalbtc_bind_bt_coex_withadapter()
0174      */
0175 }
0176 
0177 void rtl_btc_power_on_setting(struct rtl_priv *rtlpriv)
0178 {
0179     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0180 
0181     if (!btcoexist)
0182         return;
0183 
0184     exhalbtc_power_on_setting(btcoexist);
0185 }
0186 
0187 void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
0188 {
0189     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0190 
0191     u8 bt_exist;
0192 
0193     bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
0194     rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
0195         "%s, bt_exist is %d\n", __func__, bt_exist);
0196 
0197     if (!btcoexist)
0198         return;
0199 
0200     exhalbtc_init_hw_config(btcoexist, !bt_exist);
0201     exhalbtc_init_coex_dm(btcoexist);
0202 }
0203 
0204 void rtl_btc_init_hw_config_wifi_only(struct rtl_priv *rtlpriv)
0205 {
0206     struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
0207 
0208     if (!wifionly_cfg)
0209         return;
0210 
0211     exhalbtc_init_hw_config_wifi_only(wifionly_cfg);
0212 }
0213 
0214 void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
0215 {
0216     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0217 
0218     if (!btcoexist)
0219         return;
0220 
0221     exhalbtc_ips_notify(btcoexist, type);
0222 
0223     if (type == ERFON) {
0224         /* In some situation, it doesn't scan after leaving IPS, and
0225          * this will cause btcoex in wrong state.
0226          */
0227         exhalbtc_scan_notify(btcoexist, 1);
0228         exhalbtc_scan_notify(btcoexist, 0);
0229     }
0230 }
0231 
0232 void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
0233 {
0234     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0235 
0236     if (!btcoexist)
0237         return;
0238 
0239     exhalbtc_lps_notify(btcoexist, type);
0240 }
0241 
0242 void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
0243 {
0244     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0245 
0246     if (!btcoexist)
0247         return;
0248 
0249     exhalbtc_scan_notify(btcoexist, scantype);
0250 }
0251 
0252 void rtl_btc_scan_notify_wifi_only(struct rtl_priv *rtlpriv, u8 scantype)
0253 {
0254     struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
0255     struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
0256     u8 is_5g = (rtlhal->current_bandtype == BAND_ON_5G);
0257 
0258     if (!wifionly_cfg)
0259         return;
0260 
0261     exhalbtc_scan_notify_wifi_only(wifionly_cfg, is_5g);
0262 }
0263 
0264 void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action)
0265 {
0266     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0267 
0268     if (!btcoexist)
0269         return;
0270 
0271     exhalbtc_connect_notify(btcoexist, action);
0272 }
0273 
0274 void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv,
0275                 enum rt_media_status mstatus)
0276 {
0277     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0278 
0279     if (!btcoexist)
0280         return;
0281 
0282     exhalbtc_mediastatus_notify(btcoexist, mstatus);
0283 }
0284 
0285 void rtl_btc_periodical(struct rtl_priv *rtlpriv)
0286 {
0287     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0288 
0289     if (!btcoexist)
0290         return;
0291 
0292     /*rtl_bt_dm_monitor();*/
0293     exhalbtc_periodical(btcoexist);
0294 }
0295 
0296 void rtl_btc_halt_notify(struct rtl_priv *rtlpriv)
0297 {
0298     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0299 
0300     if (!btcoexist)
0301         return;
0302 
0303     exhalbtc_halt_notify(btcoexist);
0304 }
0305 
0306 void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
0307 {
0308     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0309 
0310     if (!btcoexist)
0311         return;
0312 
0313     exhalbtc_bt_info_notify(btcoexist, tmp_buf, length);
0314 }
0315 
0316 void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
0317 {
0318     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0319     u8 extid, seq;
0320     u16 bt_real_fw_ver;
0321     u8 bt_fw_ver;
0322     u8 *data;
0323 
0324     if (!btcoexist)
0325         return;
0326 
0327     if ((length < 4) || (!tmp_buf))
0328         return;
0329 
0330     extid = tmp_buf[0];
0331     /* not response from BT FW then exit*/
0332     if (extid != 1) /* C2H_TRIG_BY_BT_FW = 1 */
0333         return;
0334 
0335     seq = tmp_buf[2] >> 4;
0336     data = &tmp_buf[3];
0337 
0338     /* BT Firmware version response */
0339     switch (seq) {
0340     case BT_SEQ_GET_BT_VERSION:
0341         bt_real_fw_ver = tmp_buf[3] | (tmp_buf[4] << 8);
0342         bt_fw_ver = tmp_buf[5];
0343 
0344         btcoexist->bt_info.bt_real_fw_ver = bt_real_fw_ver;
0345         btcoexist->bt_info.bt_fw_ver = bt_fw_ver;
0346         break;
0347     case BT_SEQ_GET_AFH_MAP_L:
0348         btcoexist->bt_info.afh_map_l = le32_to_cpu(*(__le32 *)data);
0349         break;
0350     case BT_SEQ_GET_AFH_MAP_M:
0351         btcoexist->bt_info.afh_map_m = le32_to_cpu(*(__le32 *)data);
0352         break;
0353     case BT_SEQ_GET_AFH_MAP_H:
0354         btcoexist->bt_info.afh_map_h = le16_to_cpu(*(__le16 *)data);
0355         break;
0356     case BT_SEQ_GET_BT_COEX_SUPPORTED_FEATURE:
0357         btcoexist->bt_info.bt_supported_feature = tmp_buf[3] |
0358                               (tmp_buf[4] << 8);
0359         break;
0360     case BT_SEQ_GET_BT_COEX_SUPPORTED_VERSION:
0361         btcoexist->bt_info.bt_supported_version = tmp_buf[3] |
0362                               (tmp_buf[4] << 8);
0363         break;
0364     case BT_SEQ_GET_BT_ANT_DET_VAL:
0365         btcoexist->bt_info.bt_ant_det_val = tmp_buf[3];
0366         break;
0367     case BT_SEQ_GET_BT_BLE_SCAN_PARA:
0368         btcoexist->bt_info.bt_ble_scan_para = tmp_buf[3] |
0369                               (tmp_buf[4] << 8) |
0370                               (tmp_buf[5] << 16) |
0371                               (tmp_buf[6] << 24);
0372         break;
0373     case BT_SEQ_GET_BT_BLE_SCAN_TYPE:
0374         btcoexist->bt_info.bt_ble_scan_type = tmp_buf[3];
0375         break;
0376     case BT_SEQ_GET_BT_DEVICE_INFO:
0377         btcoexist->bt_info.bt_device_info =
0378                         le32_to_cpu(*(__le32 *)data);
0379         break;
0380     case BT_OP_GET_BT_FORBIDDEN_SLOT_VAL:
0381         btcoexist->bt_info.bt_forb_slot_val =
0382                         le32_to_cpu(*(__le32 *)data);
0383         break;
0384     }
0385 
0386     rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
0387         "btmpinfo complete req_num=%d\n", seq);
0388 
0389     complete(&btcoexist->bt_mp_comp);
0390 }
0391 
0392 bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv)
0393 {
0394     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0395 
0396     if (!btcoexist)
0397         return false;
0398 
0399     return btcoexist->bt_info.limited_dig;
0400 }
0401 
0402 bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv)
0403 {
0404     bool bt_change_edca = false;
0405     u32 cur_edca_val;
0406     u32 edca_bt_hs_uplink = 0x5ea42b, edca_bt_hs_downlink = 0x5ea42b;
0407     u32 edca_hs;
0408     u32 edca_addr = 0x504;
0409 
0410     cur_edca_val = rtl_read_dword(rtlpriv, edca_addr);
0411     if (halbtc_is_wifi_uplink(rtlpriv)) {
0412         if (cur_edca_val != edca_bt_hs_uplink) {
0413             edca_hs = edca_bt_hs_uplink;
0414             bt_change_edca = true;
0415         }
0416     } else {
0417         if (cur_edca_val != edca_bt_hs_downlink) {
0418             edca_hs = edca_bt_hs_downlink;
0419             bt_change_edca = true;
0420         }
0421     }
0422 
0423     if (bt_change_edca)
0424         rtl_write_dword(rtlpriv, edca_addr, edca_hs);
0425 
0426     return true;
0427 }
0428 
0429 bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv)
0430 {
0431     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0432 
0433     if (!btcoexist)
0434         return true;
0435 
0436     /* It seems 'bt_disabled' is never be initialized or set. */
0437     if (btcoexist->bt_info.bt_disabled)
0438         return true;
0439     else
0440         return false;
0441 }
0442 
0443 void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type)
0444 {
0445     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0446 
0447     if (!btcoexist)
0448         return;
0449 
0450     return exhalbtc_special_packet_notify(btcoexist, pkt_type);
0451 }
0452 
0453 void rtl_btc_switch_band_notify(struct rtl_priv *rtlpriv, u8 band_type,
0454                 bool scanning)
0455 {
0456     struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
0457     u8 type = BTC_NOT_SWITCH;
0458 
0459     if (!btcoexist)
0460         return;
0461 
0462     switch (band_type) {
0463     case BAND_ON_2_4G:
0464         if (scanning)
0465             type = BTC_SWITCH_TO_24G;
0466         else
0467             type = BTC_SWITCH_TO_24G_NOFORSCAN;
0468         break;
0469 
0470     case BAND_ON_5G:
0471         type = BTC_SWITCH_TO_5G;
0472         break;
0473     }
0474 
0475     if (type != BTC_NOT_SWITCH)
0476         exhalbtc_switch_band_notify(btcoexist, type);
0477 }
0478 
0479 void rtl_btc_switch_band_notify_wifionly(struct rtl_priv *rtlpriv, u8 band_type,
0480                      bool scanning)
0481 {
0482     struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
0483     u8 is_5g = (band_type == BAND_ON_5G);
0484 
0485     if (!wifionly_cfg)
0486         return;
0487 
0488     exhalbtc_switch_band_notify_wifi_only(wifionly_cfg, is_5g);
0489 }
0490 
0491 struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
0492 {
0493     return &rtl_btc_operation;
0494 }
0495 EXPORT_SYMBOL(rtl_btc_get_ops_pointer);
0496 
0497 
0498 enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw)
0499 {
0500     struct rtl_priv *rtlpriv = rtl_priv(hw);
0501     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0502     enum rt_media_status    m_status = RT_MEDIA_DISCONNECT;
0503 
0504     u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
0505 
0506     if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED)
0507         m_status = RT_MEDIA_CONNECT;
0508 
0509     return m_status;
0510 }
0511 
0512 u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv)
0513 {
0514     return rtlpriv->btcoexist.btc_info.btcoexist;
0515 }
0516 
0517 MODULE_AUTHOR("Page He  <page_he@realsil.com.cn>");
0518 MODULE_AUTHOR("Realtek WlanFAE  <wlanfae@realtek.com>");
0519 MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
0520 MODULE_LICENSE("GPL");
0521 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
0522 
0523 static int __init rtl_btcoexist_module_init(void)
0524 {
0525     return 0;
0526 }
0527 
0528 static void __exit rtl_btcoexist_module_exit(void)
0529 {
0530     return;
0531 }
0532 
0533 module_init(rtl_btcoexist_module_init);
0534 module_exit(rtl_btcoexist_module_exit);