brintos

brintos / linux-shallow public Read only

0
0
Text · 12.6 KiB · 4641999 Raw
535 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 11static 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 44void 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 56void 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 72u8 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 82u8 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 92bool 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 102bool 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 112void 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 131static 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	else137		rtlpriv->btcoexist.btc_context =138			kzalloc(sizeof(struct btc_coexist), GFP_KERNEL);139}140 141static 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 150void 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 158void 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 165void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv)166{167	rtl_btc_free_variable(rtlpriv);168}169 170void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)171{172	/* move ant_num, bt_type and single_ant_path to173	 * exhalbtc_bind_bt_coex_withadapter()174	 */175}176 177void 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 187void 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	rtl_dbg(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 204void 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 214void 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, and225		 * this will cause btcoex in wrong state.226		 */227		exhalbtc_scan_notify(btcoexist, 1);228		exhalbtc_scan_notify(btcoexist, 0);229	}230}231 232void 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 242void 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 252void 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 264void 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 274void 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 285void 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 296void 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 306void 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 316void 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	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,387		"btmpinfo complete req_num=%d\n", seq);388 389	complete(&btcoexist->bt_mp_comp);390}391 392bool 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 402bool 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 429bool 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	else440		return false;441}442 443void 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 453void 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		else467			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 479void 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 491struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)492{493	return &rtl_btc_operation;494}495EXPORT_SYMBOL(rtl_btc_get_ops_pointer);496 497 498enum 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 512u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv)513{514	return rtlpriv->btcoexist.btc_info.btcoexist;515}516 517MODULE_AUTHOR("Page He	<page_he@realsil.com.cn>");518MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");519MODULE_AUTHOR("Larry Finger	<Larry.FInger@lwfinger.net>");520MODULE_LICENSE("GPL");521MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");522 523static int __init rtl_btcoexist_module_init(void)524{525	return 0;526}527 528static void __exit rtl_btcoexist_module_exit(void)529{530	return;531}532 533module_init(rtl_btcoexist_module_init);534module_exit(rtl_btcoexist_module_exit);535