0001
0002
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
0173
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
0225
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
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
0332 if (extid != 1)
0333 return;
0334
0335 seq = tmp_buf[2] >> 4;
0336 data = &tmp_buf[3];
0337
0338
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
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);