root/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtl_btc_display_bt_coex_info
  2. rtl_btc_record_pwr_mode
  3. rtl_btc_get_lps_val
  4. rtl_btc_get_rpwm_val
  5. rtl_btc_is_bt_ctrl_lps
  6. rtl_btc_is_bt_lps_on
  7. rtl_btc_get_ampdu_cfg
  8. rtl_btc_alloc_variable
  9. rtl_btc_free_variable
  10. rtl_btc_init_variables
  11. rtl_btc_init_variables_wifi_only
  12. rtl_btc_deinit_variables
  13. rtl_btc_init_hal_vars
  14. rtl_btc_power_on_setting
  15. rtl_btc_init_hw_config
  16. rtl_btc_init_hw_config_wifi_only
  17. rtl_btc_ips_notify
  18. rtl_btc_lps_notify
  19. rtl_btc_scan_notify
  20. rtl_btc_scan_notify_wifi_only
  21. rtl_btc_connect_notify
  22. rtl_btc_mediastatus_notify
  23. rtl_btc_periodical
  24. rtl_btc_halt_notify
  25. rtl_btc_btinfo_notify
  26. rtl_btc_btmpinfo_notify
  27. rtl_btc_is_limited_dig
  28. rtl_btc_is_disable_edca_turbo
  29. rtl_btc_is_bt_disabled
  30. rtl_btc_special_packet_notify
  31. rtl_btc_switch_band_notify
  32. rtl_btc_switch_band_notify_wifionly
  33. rtl_btc_get_ops_pointer
  34. mgnt_link_status_query
  35. rtl_get_hwpg_bt_exist
  36. rtl_btcoexist_module_init
  37. rtl_btcoexist_module_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright(c) 2009-2013  Realtek Corporation.*/
   3 
   4 #include "../wifi.h"
   5 #include <linux/vmalloc.h>
   6 #include <linux/module.h>
   7 
   8 #include "rtl_btc.h"
   9 #include "halbt_precomp.h"
  10 
  11 static struct rtl_btc_ops rtl_btc_operation = {
  12         .btc_init_variables = rtl_btc_init_variables,
  13         .btc_init_variables_wifi_only = rtl_btc_init_variables_wifi_only,
  14         .btc_deinit_variables = rtl_btc_deinit_variables,
  15         .btc_init_hal_vars = rtl_btc_init_hal_vars,
  16         .btc_power_on_setting = rtl_btc_power_on_setting,
  17         .btc_init_hw_config = rtl_btc_init_hw_config,
  18         .btc_init_hw_config_wifi_only = rtl_btc_init_hw_config_wifi_only,
  19         .btc_ips_notify = rtl_btc_ips_notify,
  20         .btc_lps_notify = rtl_btc_lps_notify,
  21         .btc_scan_notify = rtl_btc_scan_notify,
  22         .btc_scan_notify_wifi_only = rtl_btc_scan_notify_wifi_only,
  23         .btc_connect_notify = rtl_btc_connect_notify,
  24         .btc_mediastatus_notify = rtl_btc_mediastatus_notify,
  25         .btc_periodical = rtl_btc_periodical,
  26         .btc_halt_notify = rtl_btc_halt_notify,
  27         .btc_btinfo_notify = rtl_btc_btinfo_notify,
  28         .btc_btmpinfo_notify = rtl_btc_btmpinfo_notify,
  29         .btc_is_limited_dig = rtl_btc_is_limited_dig,
  30         .btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
  31         .btc_is_bt_disabled = rtl_btc_is_bt_disabled,
  32         .btc_special_packet_notify = rtl_btc_special_packet_notify,
  33         .btc_switch_band_notify = rtl_btc_switch_band_notify,
  34         .btc_switch_band_notify_wifi_only = rtl_btc_switch_band_notify_wifionly,
  35         .btc_record_pwr_mode = rtl_btc_record_pwr_mode,
  36         .btc_get_lps_val = rtl_btc_get_lps_val,
  37         .btc_get_rpwm_val = rtl_btc_get_rpwm_val,
  38         .btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
  39         .btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
  40         .btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
  41         .btc_display_bt_coex_info = rtl_btc_display_bt_coex_info,
  42 };
  43 
  44 void rtl_btc_display_bt_coex_info(struct rtl_priv *rtlpriv, struct seq_file *m)
  45 {
  46         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
  47 
  48         if (!btcoexist) {
  49                 seq_puts(m, "btc_coexist context is NULL!\n");
  50                 return;
  51         }
  52 
  53         exhalbtc_display_bt_coex_info(btcoexist, m);
  54 }
  55 
  56 void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
  57 {
  58         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
  59         u8 safe_len;
  60 
  61         if (!btcoexist)
  62                 return;
  63 
  64         safe_len = sizeof(btcoexist->pwr_mode_val);
  65 
  66         if (safe_len > len)
  67                 safe_len = len;
  68 
  69         memcpy(btcoexist->pwr_mode_val, buf, safe_len);
  70 }
  71 
  72 u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
  73 {
  74         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
  75 
  76         if (!btcoexist)
  77                 return 0;
  78 
  79         return btcoexist->bt_info.lps_val;
  80 }
  81 
  82 u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
  83 {
  84         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
  85 
  86         if (!btcoexist)
  87                 return 0;
  88 
  89         return btcoexist->bt_info.rpwm_val;
  90 }
  91 
  92 bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
  93 {
  94         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
  95 
  96         if (!btcoexist)
  97                 return false;
  98 
  99         return btcoexist->bt_info.bt_ctrl_lps;
 100 }
 101 
 102 bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
 103 {
 104         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 105 
 106         if (!btcoexist)
 107                 return false;
 108 
 109         return btcoexist->bt_info.bt_lps_on;
 110 }
 111 
 112 void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
 113                            u8 *ctrl_agg_size, u8 *agg_size)
 114 {
 115         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 116 
 117         if (!btcoexist) {
 118                 *reject_agg = false;
 119                 *ctrl_agg_size = false;
 120                 return;
 121         }
 122 
 123         if (reject_agg)
 124                 *reject_agg = btcoexist->bt_info.reject_agg_pkt;
 125         if (ctrl_agg_size)
 126                 *ctrl_agg_size = btcoexist->bt_info.bt_ctrl_agg_buf_size;
 127         if (agg_size)
 128                 *agg_size = btcoexist->bt_info.agg_buf_size;
 129 }
 130 
 131 static void rtl_btc_alloc_variable(struct rtl_priv *rtlpriv, bool wifi_only)
 132 {
 133         if (wifi_only)
 134                 rtlpriv->btcoexist.wifi_only_context =
 135                         kzalloc(sizeof(struct wifi_only_cfg), GFP_KERNEL);
 136         else
 137                 rtlpriv->btcoexist.btc_context =
 138                         kzalloc(sizeof(struct btc_coexist), GFP_KERNEL);
 139 }
 140 
 141 static void rtl_btc_free_variable(struct rtl_priv *rtlpriv)
 142 {
 143         kfree(rtlpriv->btcoexist.btc_context);
 144         rtlpriv->btcoexist.btc_context = NULL;
 145 
 146         kfree(rtlpriv->btcoexist.wifi_only_context);
 147         rtlpriv->btcoexist.wifi_only_context = NULL;
 148 }
 149 
 150 void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
 151 {
 152         rtl_btc_alloc_variable(rtlpriv, false);
 153 
 154         exhalbtc_initlize_variables(rtlpriv);
 155         exhalbtc_bind_bt_coex_withadapter(rtlpriv);
 156 }
 157 
 158 void rtl_btc_init_variables_wifi_only(struct rtl_priv *rtlpriv)
 159 {
 160         rtl_btc_alloc_variable(rtlpriv, true);
 161 
 162         exhalbtc_initlize_variables_wifi_only(rtlpriv);
 163 }
 164 
 165 void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv)
 166 {
 167         rtl_btc_free_variable(rtlpriv);
 168 }
 169 
 170 void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
 171 {
 172         /* move ant_num, bt_type and single_ant_path to
 173          * exhalbtc_bind_bt_coex_withadapter()
 174          */
 175 }
 176 
 177 void rtl_btc_power_on_setting(struct rtl_priv *rtlpriv)
 178 {
 179         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 180 
 181         if (!btcoexist)
 182                 return;
 183 
 184         exhalbtc_power_on_setting(btcoexist);
 185 }
 186 
 187 void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
 188 {
 189         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 190 
 191         u8 bt_exist;
 192 
 193         bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
 194         RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 195                 "%s, bt_exist is %d\n", __func__, bt_exist);
 196 
 197         if (!btcoexist)
 198                 return;
 199 
 200         exhalbtc_init_hw_config(btcoexist, !bt_exist);
 201         exhalbtc_init_coex_dm(btcoexist);
 202 }
 203 
 204 void rtl_btc_init_hw_config_wifi_only(struct rtl_priv *rtlpriv)
 205 {
 206         struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
 207 
 208         if (!wifionly_cfg)
 209                 return;
 210 
 211         exhalbtc_init_hw_config_wifi_only(wifionly_cfg);
 212 }
 213 
 214 void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
 215 {
 216         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 217 
 218         if (!btcoexist)
 219                 return;
 220 
 221         exhalbtc_ips_notify(btcoexist, type);
 222 
 223         if (type == ERFON) {
 224                 /* In some situation, it doesn't scan after leaving IPS, and
 225                  * this will cause btcoex in wrong state.
 226                  */
 227                 exhalbtc_scan_notify(btcoexist, 1);
 228                 exhalbtc_scan_notify(btcoexist, 0);
 229         }
 230 }
 231 
 232 void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
 233 {
 234         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 235 
 236         if (!btcoexist)
 237                 return;
 238 
 239         exhalbtc_lps_notify(btcoexist, type);
 240 }
 241 
 242 void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
 243 {
 244         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 245 
 246         if (!btcoexist)
 247                 return;
 248 
 249         exhalbtc_scan_notify(btcoexist, scantype);
 250 }
 251 
 252 void rtl_btc_scan_notify_wifi_only(struct rtl_priv *rtlpriv, u8 scantype)
 253 {
 254         struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 255         struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
 256         u8 is_5g = (rtlhal->current_bandtype == BAND_ON_5G);
 257 
 258         if (!wifionly_cfg)
 259                 return;
 260 
 261         exhalbtc_scan_notify_wifi_only(wifionly_cfg, is_5g);
 262 }
 263 
 264 void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action)
 265 {
 266         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 267 
 268         if (!btcoexist)
 269                 return;
 270 
 271         exhalbtc_connect_notify(btcoexist, action);
 272 }
 273 
 274 void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv,
 275                                 enum rt_media_status mstatus)
 276 {
 277         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 278 
 279         if (!btcoexist)
 280                 return;
 281 
 282         exhalbtc_mediastatus_notify(btcoexist, mstatus);
 283 }
 284 
 285 void rtl_btc_periodical(struct rtl_priv *rtlpriv)
 286 {
 287         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 288 
 289         if (!btcoexist)
 290                 return;
 291 
 292         /*rtl_bt_dm_monitor();*/
 293         exhalbtc_periodical(btcoexist);
 294 }
 295 
 296 void rtl_btc_halt_notify(struct rtl_priv *rtlpriv)
 297 {
 298         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 299 
 300         if (!btcoexist)
 301                 return;
 302 
 303         exhalbtc_halt_notify(btcoexist);
 304 }
 305 
 306 void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
 307 {
 308         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 309 
 310         if (!btcoexist)
 311                 return;
 312 
 313         exhalbtc_bt_info_notify(btcoexist, tmp_buf, length);
 314 }
 315 
 316 void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
 317 {
 318         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 319         u8 extid, seq;
 320         u16 bt_real_fw_ver;
 321         u8 bt_fw_ver;
 322         u8 *data;
 323 
 324         if (!btcoexist)
 325                 return;
 326 
 327         if ((length < 4) || (!tmp_buf))
 328                 return;
 329 
 330         extid = tmp_buf[0];
 331         /* not response from BT FW then exit*/
 332         if (extid != 1) /* C2H_TRIG_BY_BT_FW = 1 */
 333                 return;
 334 
 335         seq = tmp_buf[2] >> 4;
 336         data = &tmp_buf[3];
 337 
 338         /* BT Firmware version response */
 339         switch (seq) {
 340         case BT_SEQ_GET_BT_VERSION:
 341                 bt_real_fw_ver = tmp_buf[3] | (tmp_buf[4] << 8);
 342                 bt_fw_ver = tmp_buf[5];
 343 
 344                 btcoexist->bt_info.bt_real_fw_ver = bt_real_fw_ver;
 345                 btcoexist->bt_info.bt_fw_ver = bt_fw_ver;
 346                 break;
 347         case BT_SEQ_GET_AFH_MAP_L:
 348                 btcoexist->bt_info.afh_map_l = le32_to_cpu(*(__le32 *)data);
 349                 break;
 350         case BT_SEQ_GET_AFH_MAP_M:
 351                 btcoexist->bt_info.afh_map_m = le32_to_cpu(*(__le32 *)data);
 352                 break;
 353         case BT_SEQ_GET_AFH_MAP_H:
 354                 btcoexist->bt_info.afh_map_h = le16_to_cpu(*(__le16 *)data);
 355                 break;
 356         case BT_SEQ_GET_BT_COEX_SUPPORTED_FEATURE:
 357                 btcoexist->bt_info.bt_supported_feature = tmp_buf[3] |
 358                                                           (tmp_buf[4] << 8);
 359                 break;
 360         case BT_SEQ_GET_BT_COEX_SUPPORTED_VERSION:
 361                 btcoexist->bt_info.bt_supported_version = tmp_buf[3] |
 362                                                           (tmp_buf[4] << 8);
 363                 break;
 364         case BT_SEQ_GET_BT_ANT_DET_VAL:
 365                 btcoexist->bt_info.bt_ant_det_val = tmp_buf[3];
 366                 break;
 367         case BT_SEQ_GET_BT_BLE_SCAN_PARA:
 368                 btcoexist->bt_info.bt_ble_scan_para = tmp_buf[3] |
 369                                                       (tmp_buf[4] << 8) |
 370                                                       (tmp_buf[5] << 16) |
 371                                                       (tmp_buf[6] << 24);
 372                 break;
 373         case BT_SEQ_GET_BT_BLE_SCAN_TYPE:
 374                 btcoexist->bt_info.bt_ble_scan_type = tmp_buf[3];
 375                 break;
 376         case BT_SEQ_GET_BT_DEVICE_INFO:
 377                 btcoexist->bt_info.bt_device_info =
 378                                                 le32_to_cpu(*(__le32 *)data);
 379                 break;
 380         case BT_OP_GET_BT_FORBIDDEN_SLOT_VAL:
 381                 btcoexist->bt_info.bt_forb_slot_val =
 382                                                 le32_to_cpu(*(__le32 *)data);
 383                 break;
 384         }
 385 
 386         RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
 387                  "btmpinfo complete req_num=%d\n", seq);
 388 
 389         complete(&btcoexist->bt_mp_comp);
 390 }
 391 
 392 bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv)
 393 {
 394         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 395 
 396         if (!btcoexist)
 397                 return false;
 398 
 399         return btcoexist->bt_info.limited_dig;
 400 }
 401 
 402 bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv)
 403 {
 404         bool bt_change_edca = false;
 405         u32 cur_edca_val;
 406         u32 edca_bt_hs_uplink = 0x5ea42b, edca_bt_hs_downlink = 0x5ea42b;
 407         u32 edca_hs;
 408         u32 edca_addr = 0x504;
 409 
 410         cur_edca_val = rtl_read_dword(rtlpriv, edca_addr);
 411         if (halbtc_is_wifi_uplink(rtlpriv)) {
 412                 if (cur_edca_val != edca_bt_hs_uplink) {
 413                         edca_hs = edca_bt_hs_uplink;
 414                         bt_change_edca = true;
 415                 }
 416         } else {
 417                 if (cur_edca_val != edca_bt_hs_downlink) {
 418                         edca_hs = edca_bt_hs_downlink;
 419                         bt_change_edca = true;
 420                 }
 421         }
 422 
 423         if (bt_change_edca)
 424                 rtl_write_dword(rtlpriv, edca_addr, edca_hs);
 425 
 426         return true;
 427 }
 428 
 429 bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv)
 430 {
 431         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 432 
 433         if (!btcoexist)
 434                 return true;
 435 
 436         /* It seems 'bt_disabled' is never be initialized or set. */
 437         if (btcoexist->bt_info.bt_disabled)
 438                 return true;
 439         else
 440                 return false;
 441 }
 442 
 443 void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type)
 444 {
 445         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 446 
 447         if (!btcoexist)
 448                 return;
 449 
 450         return exhalbtc_special_packet_notify(btcoexist, pkt_type);
 451 }
 452 
 453 void rtl_btc_switch_band_notify(struct rtl_priv *rtlpriv, u8 band_type,
 454                                 bool scanning)
 455 {
 456         struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
 457         u8 type = BTC_NOT_SWITCH;
 458 
 459         if (!btcoexist)
 460                 return;
 461 
 462         switch (band_type) {
 463         case BAND_ON_2_4G:
 464                 if (scanning)
 465                         type = BTC_SWITCH_TO_24G;
 466                 else
 467                         type = BTC_SWITCH_TO_24G_NOFORSCAN;
 468                 break;
 469 
 470         case BAND_ON_5G:
 471                 type = BTC_SWITCH_TO_5G;
 472                 break;
 473         }
 474 
 475         if (type != BTC_NOT_SWITCH)
 476                 exhalbtc_switch_band_notify(btcoexist, type);
 477 }
 478 
 479 void rtl_btc_switch_band_notify_wifionly(struct rtl_priv *rtlpriv, u8 band_type,
 480                                          bool scanning)
 481 {
 482         struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
 483         u8 is_5g = (band_type == BAND_ON_5G);
 484 
 485         if (!wifionly_cfg)
 486                 return;
 487 
 488         exhalbtc_switch_band_notify_wifi_only(wifionly_cfg, is_5g);
 489 }
 490 
 491 struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
 492 {
 493         return &rtl_btc_operation;
 494 }
 495 EXPORT_SYMBOL(rtl_btc_get_ops_pointer);
 496 
 497 
 498 enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw)
 499 {
 500         struct rtl_priv *rtlpriv = rtl_priv(hw);
 501         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 502         enum rt_media_status    m_status = RT_MEDIA_DISCONNECT;
 503 
 504         u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
 505 
 506         if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED)
 507                 m_status = RT_MEDIA_CONNECT;
 508 
 509         return m_status;
 510 }
 511 
 512 u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv)
 513 {
 514         return rtlpriv->btcoexist.btc_info.btcoexist;
 515 }
 516 
 517 MODULE_AUTHOR("Page He  <page_he@realsil.com.cn>");
 518 MODULE_AUTHOR("Realtek WlanFAE  <wlanfae@realtek.com>");
 519 MODULE_AUTHOR("Larry Finger     <Larry.FInger@lwfinger.net>");
 520 MODULE_LICENSE("GPL");
 521 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
 522 
 523 static int __init rtl_btcoexist_module_init(void)
 524 {
 525         return 0;
 526 }
 527 
 528 static void __exit rtl_btcoexist_module_exit(void)
 529 {
 530         return;
 531 }
 532 
 533 module_init(rtl_btcoexist_module_init);
 534 module_exit(rtl_btcoexist_module_exit);

/* [<][>][^][v][top][bottom][index][help] */