* [PATCH 0/6 V2] Some changes for rtlwifi
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Larry Finger, netdev
The first of these patches changes the logging when an encryption key
is changed. The rest are for changes in the btcoexist driver. Most
contain the code needed to handle the RTL8812AE chips.
All patches are for -next.
V2 - Add license for btcoexist/halbtc8812a1ant.{c,h}
Improve subject and commit message for patch 5 of series.
Add comments explaining routine that formats and sends kernel socket.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
Larry Finger (2):
rtlwifi: Change logging level for key change
rtlwifi: btcoexist: Remove typedef statements
Troy Tan (4):
rtlwifi: btcoexist: Add routines for RTL8812AE with single antenna
rtlwifi: btcoexist: Add routines for RTL8812AE with dual antennae
rtlwifi: btcoexist: Add routines for RTL8812AE kernel socket
rtlwifi: btcoexist: Enable new routines for RTL8812AE
drivers/net/wireless/rtlwifi/btcoexist/Makefile | 9 +
.../net/wireless/rtlwifi/btcoexist/halbt_precomp.h | 3 +
.../wireless/rtlwifi/btcoexist/halbtc8192e2ant.c | 6 +-
.../wireless/rtlwifi/btcoexist/halbtc8723b2ant.h | 6 +-
.../wireless/rtlwifi/btcoexist/halbtc8812a1ant.c | 2073 ++++++++++
.../wireless/rtlwifi/btcoexist/halbtc8812a1ant.h | 152 +
.../wireless/rtlwifi/btcoexist/halbtc8812a2ant.c | 4207 ++++++++++++++++++++
.../wireless/rtlwifi/btcoexist/halbtc8812a2ant.h | 177 +
.../wireless/rtlwifi/btcoexist/halbtc8812a_ext.c | 921 +++++
.../wireless/rtlwifi/btcoexist/halbtc8812a_ext.h | 359 ++
.../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c | 713 +++-
.../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h | 108 +-
drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c | 37 +
drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h | 6 +-
drivers/net/wireless/rtlwifi/cam.c | 2 +-
drivers/net/wireless/rtlwifi/core.c | 17 +-
drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h | 14 -
drivers/net/wireless/rtlwifi/wifi.h | 12 +-
18 files changed, 8590 insertions(+), 232 deletions(-)
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.c
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.h
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.c
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.c
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.h
--
2.1.2
^ permalink raw reply
* [PATCH V2 1/6] rtlwifi: Change logging level for key change
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Larry Finger, netdev
In-Reply-To: <1422304934-9239-1-git-send-email-Larry.Finger@lwfinger.net>
A recent change in key handling included logging of these changes for
all debug levels. Such key changes should only be logged when a high
level of debugging is enabled.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
drivers/net/wireless/rtlwifi/cam.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 3ef870d..6e64792 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -406,7 +406,7 @@ u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
}
}
if (found) {
- RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG,
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
"key_index=%d,cam_bitmap: 0x%x entry_idx=%d\n",
key_index, rtlpriv->sec.cam_bitmap, entry_idx);
return entry_idx;
--
2.1.2
^ permalink raw reply related
* [PATCH V2 2/6] rtlwifi: btcoexist: Remove typedef statements
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Larry Finger, netdev
In-Reply-To: <1422304934-9239-1-git-send-email-Larry.Finger@lwfinger.net>
In btcoexist, there are a number of typedef statements. Not only do
they violate the rule of avoiding new typdef statements in the kernel,
these are also pointless as they use an extra level of indirection in
the definition of some function pointers.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
.../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c | 2 +-
.../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h | 84 +++++++---------------
2 files changed, 26 insertions(+), 60 deletions(-)
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
index b2791c8..7a72636 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -496,7 +496,7 @@ static u32 halbtc_read_4byte(void *bt_context, u32 reg_addr)
return rtl_read_dword(rtlpriv, reg_addr);
}
-static void halbtc_write_1byte(void *bt_context, u32 reg_addr, u32 data)
+static void halbtc_write_1byte(void *bt_context, u32 reg_addr, u8 data)
{
struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context;
struct rtl_priv *rtlpriv = btcoexist->adapter;
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
index 0a903ea..8c64acf 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -350,45 +350,6 @@ enum btc_notify_type_stack_operation {
BTC_STACK_OP_MAX
};
-typedef u8 (*bfp_btc_r1)(void *btc_context, u32 reg_addr);
-
-typedef u16 (*bfp_btc_r2)(void *btc_context, u32 reg_addr);
-
-typedef u32 (*bfp_btc_r4)(void *btc_context, u32 reg_addr);
-
-typedef void (*bfp_btc_w1)(void *btc_context, u32 reg_addr, u32 data);
-
-typedef void (*bfp_btc_w1_bit_mak)(void *btc_context, u32 reg_addr,
- u32 bit_mask, u8 data1b);
-
-typedef void (*bfp_btc_w2)(void *btc_context, u32 reg_addr, u16 data);
-
-typedef void (*bfp_btc_w4)(void *btc_context, u32 reg_addr, u32 data);
-
-typedef void (*bfp_btc_wr_1byte_bit_mask)(void *btc_context, u32 reg_addr,
- u8 bit_mask, u8 data);
-
-typedef void (*bfp_btc_set_bb_reg)(void *btc_context, u32 reg_addr,
- u32 bit_mask, u32 data);
-
-typedef u32 (*bfp_btc_get_bb_reg)(void *btc_context, u32 reg_addr,
- u32 bit_mask);
-
-typedef void (*bfp_btc_set_rf_reg)(void *btc_context, u8 rf_path, u32 reg_addr,
- u32 bit_mask, u32 data);
-
-typedef u32 (*bfp_btc_get_rf_reg)(void *btc_context, u8 rf_path,
- u32 reg_addr, u32 bit_mask);
-
-typedef void (*bfp_btc_fill_h2c)(void *btc_context, u8 element_id,
- u32 cmd_len, u8 *cmd_buffer);
-
-typedef bool (*bfp_btc_get)(void *btcoexist, u8 get_type, void *out_buf);
-
-typedef bool (*bfp_btc_set)(void *btcoexist, u8 set_type, void *in_buf);
-
-typedef void (*bfp_btc_disp_dbg_msg)(void *btcoexist, u8 disp_type);
-
struct btc_bt_info {
bool bt_disabled;
u8 rssi_adjust_for_agc_table_on;
@@ -484,26 +445,31 @@ struct btc_coexist {
u8 pwr_mode_val[10];
/* function pointers - io related */
- bfp_btc_r1 btc_read_1byte;
- bfp_btc_w1 btc_write_1byte;
- bfp_btc_w1_bit_mak btc_write_1byte_bitmask;
- bfp_btc_r2 btc_read_2byte;
- bfp_btc_w2 btc_write_2byte;
- bfp_btc_r4 btc_read_4byte;
- bfp_btc_w4 btc_write_4byte;
-
- bfp_btc_set_bb_reg btc_set_bb_reg;
- bfp_btc_get_bb_reg btc_get_bb_reg;
-
- bfp_btc_set_rf_reg btc_set_rf_reg;
- bfp_btc_get_rf_reg btc_get_rf_reg;
-
- bfp_btc_fill_h2c btc_fill_h2c;
-
- bfp_btc_disp_dbg_msg btc_disp_dbg_msg;
-
- bfp_btc_get btc_get;
- bfp_btc_set btc_set;
+ u8 (*btc_read_1byte)(void *btc_context, u32 reg_addr);
+ void (*btc_write_1byte)(void *btc_context, u32 reg_addr, u8 data);
+ void (*btc_write_1byte_bitmask)(void *btc_context, u32 reg_addr,
+ u32 bit_mask, u8 data1b);
+ u16 (*btc_read_2byte)(void *btc_context, u32 reg_addr);
+ void (*btc_write_2byte)(void *btc_context, u32 reg_addr, u16 data);
+ u32 (*btc_read_4byte)(void *btc_context, u32 reg_addr);
+ void (*btc_write_4byte)(void *btc_context, u32 reg_addr, u32 data);
+
+ void (*btc_set_bb_reg)(void *btc_context, u32 reg_addr,
+ u32 bit_mask, u32 data);
+ u32 (*btc_get_bb_reg)(void *btc_context, u32 reg_addr, u32 bit_mask);
+
+ void (*btc_set_rf_reg)(void *btc_context, u8 rf_path, u32 reg_addr,
+ u32 bit_mask, u32 data);
+ u32 (*btc_get_rf_reg)(void *btc_context, u8 rf_path,
+ u32 reg_addr, u32 bit_mask);
+
+ void (*btc_fill_h2c)(void *btc_context, u8 element_id,
+ u32 cmd_len, u8 *cmd_buffer);
+
+ void (*btc_disp_dbg_msg)(void *btcoexist, u8 disp_type);
+
+ bool (*btc_get)(void *btcoexist, u8 get_type, void *out_buf);
+ bool (*btc_set)(void *btcoexist, u8 set_type, void *in_buf);
};
bool halbtc_is_wifi_uplink(struct rtl_priv *adapter);
--
2.1.2
^ permalink raw reply related
* [PATCH V2 4/6] rtlwifi: btcoexist: Add routines for RTL8812AE with dual antennae
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Troy Tan, netdev, Larry Finger
In-Reply-To: <1422304934-9239-1-git-send-email-Larry.Finger@lwfinger.net>
From: Troy Tan <troy_tan@realsil.com.cn>
The RTL8812AE needs different BT coexistence routines than does the
RTL8821AE. This patch adds the necessary routines for devices with a
more than one antenna.
Signed-off-by: Troy Tan <troy_tan@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
.../wireless/rtlwifi/btcoexist/halbtc8812a2ant.c | 4207 ++++++++++++++++++++
.../wireless/rtlwifi/btcoexist/halbtc8812a2ant.h | 177 +
2 files changed, 4384 insertions(+)
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.c
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.c
new file mode 100644
index 0000000..5c9e003
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.c
@@ -0,0 +1,4207 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2014 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+/* This file is for RTL8812A Co-exist mechanism */
+/* History */
+/* 2012/08/22 Cosa first check in. */
+/* 2012/11/14 Cosa Revise for 8812A 2Ant out sourcing. */
+
+/* include files */
+#include "halbt_precomp.h"
+
+/* Global variables, these are static */
+
+static struct coex_dm_8812a_2ant glcoex_dm_8812a_2ant;
+static struct coex_dm_8812a_2ant *coex_dm = &glcoex_dm_8812a_2ant;
+static struct coex_sta_8812a_2ant glcoex_sta_8812a_2ant;
+static struct coex_sta_8812a_2ant *coex_sta = &glcoex_sta_8812a_2ant;
+static const char *const glbt_info_src_8812a_2ant[] = {
+ "BT Info[wifi fw]",
+ "BT Info[bt rsp]",
+ "BT Info[bt auto report]",
+};
+
+static u32 glcoex_ver_date_8812a_2ant = 20131017;
+static u32 glcoex_ver_8812a_2ant = 0x36;
+
+/* local function proto type if needed */
+/* local function start with halbtc8812a2ant_ */
+
+static u8 halbtc8812a2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh,
+ u8 rssi_thresh1)
+{
+ s32 bt_rssi = 0;
+ u8 bt_rssi_state = coex_sta->pre_bt_rssi_state;
+
+ bt_rssi = coex_sta->bt_rssi;
+
+ if (level_num == 2) {
+ if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) ||
+ (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi pre state =LOW\n");
+ if (bt_rssi >=
+ (rssi_thresh +
+ BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT)) {
+ bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state switch to High\n");
+ } else {
+ bt_rssi_state = BTC_RSSI_STATE_STAY_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state stay at Low\n");
+ }
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi pre state =HIGH\n");
+ if (bt_rssi < rssi_thresh) {
+ bt_rssi_state = BTC_RSSI_STATE_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state switch to Low\n");
+ } else {
+ bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state stay at High\n");
+ }
+ }
+ } else if (level_num == 3) {
+ if (rssi_thresh > rssi_thresh1) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi thresh error!!\n");
+ return coex_sta->pre_bt_rssi_state;
+ }
+
+ if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) ||
+ (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi pre state =LOW\n");
+ if (bt_rssi >=
+ (rssi_thresh +
+ BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT)) {
+ bt_rssi_state = BTC_RSSI_STATE_MEDIUM;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state switch to Medium\n");
+ } else {
+ bt_rssi_state = BTC_RSSI_STATE_STAY_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state stay at Low\n");
+ }
+ } else if ((coex_sta->pre_bt_rssi_state ==
+ BTC_RSSI_STATE_MEDIUM) ||
+ (coex_sta->pre_bt_rssi_state ==
+ BTC_RSSI_STATE_STAY_MEDIUM)) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi pre state =MEDIUM\n");
+ if (bt_rssi >=
+ (rssi_thresh1 +
+ BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT)) {
+ bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state switch to High\n");
+ } else if (bt_rssi < rssi_thresh) {
+ bt_rssi_state = BTC_RSSI_STATE_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state switch to Low\n");
+ } else {
+ bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state stay at Medium\n");
+ }
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi pre state =HIGH\n");
+ if (bt_rssi < rssi_thresh1) {
+ bt_rssi_state = BTC_RSSI_STATE_MEDIUM;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state switch to Medium\n");
+ } else {
+ bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE,
+ "[BTCoex], BT Rssi state stay at High\n");
+ }
+ }
+ }
+ coex_sta->pre_bt_rssi_state = bt_rssi_state;
+
+ return bt_rssi_state;
+}
+
+static u8 halbtc8812a2ant_wifi_rssi_state(struct btc_coexist *btcoexist,
+ u8 index, u8 level_num,
+ u8 rssi_thresh, u8 rssi_thresh1)
+{
+ s32 wifi_rssi = 0;
+ u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index];
+
+ btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
+
+ if (level_num == 2) {
+ if ((coex_sta->pre_wifi_rssi_state[index] ==
+ BTC_RSSI_STATE_LOW) ||
+ (coex_sta->pre_wifi_rssi_state[index] ==
+ BTC_RSSI_STATE_STAY_LOW)) {
+ if (wifi_rssi >=
+ (rssi_thresh +
+ BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT)) {
+ wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state switch to High\n");
+ } else {
+ wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state stay at Low\n");
+ }
+ } else {
+ if (wifi_rssi < rssi_thresh) {
+ wifi_rssi_state = BTC_RSSI_STATE_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state switch to Low\n");
+ } else {
+ wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state stay at High\n");
+ }
+ }
+ } else if (level_num == 3) {
+ if (rssi_thresh > rssi_thresh1) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI thresh error!!\n");
+ return coex_sta->pre_wifi_rssi_state[index];
+ }
+
+ if ((coex_sta->pre_wifi_rssi_state[index] ==
+ BTC_RSSI_STATE_LOW) ||
+ (coex_sta->pre_wifi_rssi_state[index] ==
+ BTC_RSSI_STATE_STAY_LOW)) {
+ if (wifi_rssi >=
+ (rssi_thresh +
+ BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT)) {
+ wifi_rssi_state = BTC_RSSI_STATE_MEDIUM;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state switch to Medium\n");
+ } else {
+ wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state stay at Low\n");
+ }
+ } else if ((coex_sta->pre_wifi_rssi_state[index] ==
+ BTC_RSSI_STATE_MEDIUM) ||
+ (coex_sta->pre_wifi_rssi_state[index] ==
+ BTC_RSSI_STATE_STAY_MEDIUM)) {
+ if (wifi_rssi >=
+ (rssi_thresh1 +
+ BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT)) {
+ wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state switch to High\n");
+ } else if (wifi_rssi < rssi_thresh) {
+ wifi_rssi_state = BTC_RSSI_STATE_LOW;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state switch to Low\n");
+ } else {
+ wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state stay at Medium\n");
+ }
+ } else {
+ if (wifi_rssi < rssi_thresh1) {
+ wifi_rssi_state = BTC_RSSI_STATE_MEDIUM;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state switch to Medium\n");
+ } else {
+ wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_WIFI_RSSI_STATE,
+ "[BTCoex], wifi RSSI state stay at High\n");
+ }
+ }
+ }
+ coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state;
+
+ return wifi_rssi_state;
+}
+
+static void hal8812a2_monitor_bt_enable_disable(struct btc_coexist *btcoexist)
+{
+ struct btc_stack_info *stack_info = &btcoexist->stack_info;
+ static bool pre_bt_disabled;
+ static u32 bt_disable_cnt;
+ bool bt_active = true, bt_disabled = false;
+
+ /* This function check if bt is disabled */
+
+ /* only 8812a need to consider if core stack is installed. */
+ if (!stack_info->hci_version)
+ bt_active = false;
+
+ if (coex_sta->high_priority_tx == 0 &&
+ coex_sta->high_priority_rx == 0 &&
+ coex_sta->low_priority_tx == 0 &&
+ coex_sta->low_priority_rx == 0)
+ bt_active = false;
+ if (coex_sta->high_priority_tx == 0xffff &&
+ coex_sta->high_priority_rx == 0xffff &&
+ coex_sta->low_priority_tx == 0xffff &&
+ coex_sta->low_priority_rx == 0xffff)
+ bt_active = false;
+ if (bt_active) {
+ bt_disable_cnt = 0;
+ bt_disabled = false;
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE,
+ &bt_disabled);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR,
+ "[BTCoex], BT is enabled !!\n");
+ } else {
+ bt_disable_cnt++;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR,
+ "[BTCoex], bt is detected as disabled %d times!!\n",
+ bt_disable_cnt);
+ if (bt_disable_cnt >= 2) {
+ bt_disabled = true;
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE,
+ &bt_disabled);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR,
+ "[BTCoex], BT is disabled !!\n");
+ }
+ }
+ if (pre_bt_disabled != bt_disabled) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR,
+ "[BTCoex], BT is from %s to %s!!\n",
+ (pre_bt_disabled ? "disabled" : "enabled"),
+ (bt_disabled ? "disabled" : "enabled"));
+ pre_bt_disabled = bt_disabled;
+ }
+}
+
+static u32 halbtc8812a2ant_decide_ra_mask(struct btc_coexist *btcoexist,
+ u32 ra_mask_type)
+{
+ u32 dis_ra_mask = 0x0;
+
+ switch (ra_mask_type) {
+ case 0: /* normal mode */
+ dis_ra_mask = 0x0;
+ break;
+ case 1: /* disable cck 1/2 */
+ dis_ra_mask = 0x00000003;
+ break;
+ case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4 */
+ dis_ra_mask = 0x0001f1f7;
+ break;
+ default:
+ break;
+ }
+
+ return dis_ra_mask;
+}
+
+static void halbtc8812a2ant_update_ra_mask(struct btc_coexist *btcoexist,
+ bool force_exec, u32 dis_rate_mask)
+{
+ coex_dm->cur_ra_mask = dis_rate_mask;
+
+ if (force_exec || (coex_dm->pre_ra_mask != coex_dm->cur_ra_mask))
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask,
+ &coex_dm->cur_ra_mask);
+ coex_dm->pre_ra_mask = coex_dm->cur_ra_mask;
+}
+
+static void hal8812a2_auto_rate_fallback_retry(struct btc_coexist *btcoexist,
+ bool force_exec, u8 type)
+{
+ bool wifi_under_bmode = false;
+
+ coex_dm->cur_arfr_type = type;
+
+ if (force_exec || (coex_dm->pre_arfr_type != coex_dm->cur_arfr_type)) {
+ switch (coex_dm->cur_arfr_type) {
+ case 0: /* normal mode */
+ btcoexist->btc_write_4byte(btcoexist, 0x430,
+ coex_dm->back_up_arfr_cnt1);
+ btcoexist->btc_write_4byte(btcoexist, 0x434,
+ coex_dm->backup_arfr_cnt2);
+ break;
+ case 1:
+ btcoexist->btc_get(btcoexist,
+ BTC_GET_BL_WIFI_UNDER_B_MODE,
+ &wifi_under_bmode);
+ if (wifi_under_bmode) {
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x430, 0x0);
+ btcoexist->btc_write_4byte(btcoexist, 0x434,
+ 0x01010101);
+ } else {
+ btcoexist->btc_write_4byte(btcoexist, 0x430,
+ 0x0);
+ btcoexist->btc_write_4byte(btcoexist, 0x434,
+ 0x04030201);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ coex_dm->pre_arfr_type = coex_dm->cur_arfr_type;
+}
+
+static void halbtc8812a2ant_retry_limit(struct btc_coexist *btcoexist,
+ bool force_exec, u8 type)
+{
+ coex_dm->cur_retry_limit_type = type;
+
+ if (force_exec ||
+ (coex_dm->pre_retry_limit_type != coex_dm->cur_retry_limit_type)) {
+ switch (coex_dm->cur_retry_limit_type) {
+ case 0: /* normal mode */
+ btcoexist->btc_write_2byte(btcoexist, 0x42a,
+ coex_dm->backup_retry_limit);
+ break;
+ case 1: /* retry limit =8 */
+ btcoexist->btc_write_2byte(btcoexist, 0x42a, 0x0808);
+ break;
+ default:
+ break;
+ }
+ }
+
+ coex_dm->pre_retry_limit_type = coex_dm->cur_retry_limit_type;
+}
+
+static void halbtc8812a2ant_ampdu_max_time(struct btc_coexist *btcoexist,
+ bool force_exec, u8 type)
+{
+ coex_dm->cur_ampdu_time_type = type;
+
+ if (force_exec ||
+ (coex_dm->pre_ampdu_time_type != coex_dm->cur_ampdu_time_type)) {
+ switch (coex_dm->cur_ampdu_time_type) {
+ case 0: /* normal mode */
+ btcoexist->btc_write_1byte(btcoexist, 0x456,
+ coex_dm->backup_ampdu_maxtime);
+ break;
+ case 1: /* AMPDU timw = 0x38 * 32us */
+ btcoexist->btc_write_1byte(btcoexist, 0x456, 0x38);
+ break;
+ default:
+ break;
+ }
+ }
+
+ coex_dm->pre_ampdu_time_type = coex_dm->cur_ampdu_time_type;
+}
+
+static void halbtc8812a2ant_limited_tx(struct btc_coexist *btcoexist,
+ bool force_exec, u8 ra_mask_type,
+ u8 arfr_type, u8 retry_limit_type,
+ u8 ampdu_time_type)
+{
+ u32 dis_ra_mask = 0x0;
+
+ coex_dm->curramasktype = ra_mask_type;
+ dis_ra_mask = halbtc8812a2ant_decide_ra_mask(btcoexist, ra_mask_type);
+ halbtc8812a2ant_update_ra_mask(btcoexist, force_exec, dis_ra_mask);
+
+ hal8812a2_auto_rate_fallback_retry(btcoexist, force_exec, arfr_type);
+ halbtc8812a2ant_retry_limit(btcoexist, force_exec, retry_limit_type);
+ halbtc8812a2ant_ampdu_max_time(btcoexist, force_exec,
+ ampdu_time_type);
+}
+
+static void halbtc8812a2ant_limited_rx(struct btc_coexist *btcoexist,
+ bool force_exec, bool rej_ap_agg_pkt,
+ bool b_bt_ctrl_buf_size, u8 agg_buf_size)
+{
+ bool reject_rx_agg = rej_ap_agg_pkt;
+ bool btctrlrxaggsize = b_bt_ctrl_buf_size;
+ u8 rx_agg_size = agg_buf_size;
+
+ /* Rx Aggregation related setting */
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT,
+ &reject_rx_agg);
+ /* decide BT control aggregation buf size or not */
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE,
+ &btctrlrxaggsize);
+ /* aggregation buf size, only work when BT control Rx aggr size. */
+ btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rx_agg_size);
+ /* real update aggregation setting */
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
+}
+
+static void halbtc8812a2ant_monitor_bt_ctr(struct btc_coexist *btcoexist)
+{
+ u32 reg_hp_tx_rx, reg_lp_tx_rx, u4_tmp;
+ u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0;
+
+ reg_hp_tx_rx = 0x770;
+ reg_lp_tx_rx = 0x774;
+
+ u4_tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_tx_rx);
+ reg_hp_tx = u4_tmp & MASKLWORD;
+ reg_hp_rx = (u4_tmp & MASKHWORD)>>16;
+
+ u4_tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_tx_rx);
+ reg_lp_tx = u4_tmp & MASKLWORD;
+ reg_lp_rx = (u4_tmp & MASKHWORD)>>16;
+
+ coex_sta->high_priority_tx = reg_hp_tx;
+ coex_sta->high_priority_rx = reg_hp_rx;
+ coex_sta->low_priority_tx = reg_lp_tx;
+ coex_sta->low_priority_rx = reg_lp_rx;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR,
+ "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n",
+ reg_hp_tx_rx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR,
+ "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n",
+ reg_lp_tx_rx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx);
+
+ /* reset counter */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
+}
+
+static void halbtc8812a2ant_query_bt_info(struct btc_coexist *btcoexist)
+{
+ u8 data_len = 3;
+ u8 buf[5] = {0};
+
+ if (!btcoexist->bt_info.bt_disabled) {
+ if (!coex_sta->bt_info_query_cnt ||
+ (coex_sta->bt_info_c2h_cnt[BT_INFO_SRC_8812A_2ANT_BT_RSP] -
+ coex_sta->bt_info_query_cnt) > 2) {
+ buf[0] = data_len;
+ buf[1] = 0x1; /* polling, 1 =enable, 0 =disable */
+ buf[2] = 0x2; /* polling time in seconds */
+ buf[3] = 0x1; /* auto report, 1 =enable, 0 =disable*/
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_INFO,
+ (void *)&buf[0]);
+ }
+ }
+ coex_sta->bt_info_query_cnt++;
+}
+
+static void halbtc8812a2ant_update_bt_link_info(struct btc_coexist *btcoexist)
+{
+ struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+ bool bt_hs_on = false;
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+
+ bt_link_info->bt_link_exist = coex_sta->bt_link_exist;
+ bt_link_info->sco_exist = coex_sta->sco_exist;
+ bt_link_info->a2dp_exist = coex_sta->a2dp_exist;
+ bt_link_info->pan_exist = coex_sta->pan_exist;
+ bt_link_info->hid_exist = coex_sta->hid_exist;
+
+ /* work around for HS mode. */
+ if (bt_hs_on) {
+ bt_link_info->pan_exist = true;
+ bt_link_info->bt_link_exist = true;
+ }
+ /* check if Sco only */
+ if (bt_link_info->sco_exist &&
+ !bt_link_info->a2dp_exist &&
+ !bt_link_info->pan_exist &&
+ !bt_link_info->hid_exist)
+ bt_link_info->sco_only = true;
+ else
+ bt_link_info->sco_only = false;
+
+ /* check if A2dp only */
+ if (!bt_link_info->sco_exist &&
+ bt_link_info->a2dp_exist &&
+ !bt_link_info->pan_exist &&
+ !bt_link_info->hid_exist)
+ bt_link_info->a2dp_only = true;
+ else
+ bt_link_info->a2dp_only = false;
+
+ /* check if Pan only */
+ if (!bt_link_info->sco_exist &&
+ !bt_link_info->a2dp_exist &&
+ bt_link_info->pan_exist &&
+ !bt_link_info->hid_exist)
+ bt_link_info->pan_only = true;
+ else
+ bt_link_info->pan_only = false;
+
+ /* check if Hid only */
+ if (!bt_link_info->sco_exist &&
+ !bt_link_info->a2dp_exist &&
+ !bt_link_info->pan_exist &&
+ bt_link_info->hid_exist)
+ bt_link_info->hid_only = true;
+ else
+ bt_link_info->hid_only = false;
+}
+
+static void hal8812a2_set_fw_dac_swing_level(struct btc_coexist *btcoexist,
+ u8 dac_swing_lvl)
+{
+ u8 h2c_parameter[1] = {0};
+
+ /* There are several type of dacswing */
+ /* 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 */
+ h2c_parameter[0] = dac_swing_lvl;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC,
+ "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC,
+ "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]);
+
+ btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter);
+}
+
+static void halbtc8812a2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist,
+ u8 dec_bt_pwr_lvl)
+{
+ u8 data_len = 4;
+ u8 buf[6] = {0};
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC,
+ "[BTCoex], decrease Bt Power level = %d\n",
+ dec_bt_pwr_lvl);
+
+ buf[0] = data_len;
+ buf[1] = 0x3; /* OP_Code */
+ buf[2] = 0x2; /* OP_Code_Length */
+ if (dec_bt_pwr_lvl)
+ buf[3] = 0x1; /* OP_Code_Content */
+ else
+ buf[3] = 0x0;
+ buf[4] = dec_bt_pwr_lvl;/* pwrlevel */
+
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_COEX,
+ (void *)&buf[0]);
+}
+
+static void halbtc8812a2ant_dec_bt_pwr(struct btc_coexist *btcoexist,
+ bool force_exec, u8 dec_bt_pwr_lvl)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], %s Dec BT power level = %d\n",
+ (force_exec ? "force to" : ""), dec_bt_pwr_lvl);
+ coex_dm->cur_dec_bt_pwr = dec_bt_pwr_lvl;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], pre_bt_dec_pwr_lvl =%d, cur_dec_bt_pwr =%d\n",
+ coex_dm->pre_bt_dec_pwr_lvl, coex_dm->cur_dec_bt_pwr);
+
+ if (coex_dm->pre_bt_dec_pwr_lvl == coex_dm->cur_dec_bt_pwr)
+ return;
+ }
+ halbtc8812a2ant_set_fw_dec_bt_pwr(btcoexist, coex_dm->cur_dec_bt_pwr);
+
+ coex_dm->pre_bt_dec_pwr_lvl = coex_dm->cur_dec_bt_pwr;
+}
+
+static void halbtc8812a2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist,
+ bool force_exec,
+ u8 fw_dac_swing_lvl)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], %s set FW Dac Swing level = %d\n",
+ (force_exec ? "force to" : ""), fw_dac_swing_lvl);
+ coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], pre_fw_dac_swing_lvl =%d, cur_fw_dac_swing_lvl =%d\n",
+ coex_dm->pre_fw_dac_swing_lvl,
+ coex_dm->cur_fw_dac_swing_lvl);
+
+ if (coex_dm->pre_fw_dac_swing_lvl ==
+ coex_dm->cur_fw_dac_swing_lvl)
+ return;
+ }
+
+ hal8812a2_set_fw_dac_swing_level(btcoexist,
+ coex_dm->cur_fw_dac_swing_lvl);
+
+ coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl;
+}
+
+static void hal8812a2_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist,
+ bool rx_rf_shrink_on)
+{
+ if (rx_rf_shrink_on) {
+ /* Shrink RF Rx LPF corner */
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], Shrink RF Rx LPF corner!!\n");
+ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e,
+ 0xfffff, 0xffffc);
+ } else {
+ /* Resume RF Rx LPF corner */
+ /* After initialized, we can use coex_dm->bt_rf0x1e_backup */
+ if (btcoexist->initilized) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], Resume RF Rx LPF corner!!\n");
+ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e,
+ 0xfffff,
+ coex_dm->bt_rf0x1e_backup);
+ }
+ }
+}
+
+static void halbtc8812a2ant_rf_shrink(struct btc_coexist *btcoexist,
+ bool force_exec, bool rx_rf_shrink_on)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW,
+ "[BTCoex], %s turn Rx RF Shrink = %s\n",
+ (force_exec ? "force to" : ""),
+ ((rx_rf_shrink_on) ? "ON" : "OFF"));
+ coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL,
+ "[BTCoex], pre_rf_rx_lpf_shrink =%d, cur_rf_rx_lpf_shrink =%d\n",
+ coex_dm->pre_rf_rx_lpf_shrink,
+ coex_dm->cur_rf_rx_lpf_shrink);
+ if (coex_dm->pre_rf_rx_lpf_shrink ==
+ coex_dm->cur_rf_rx_lpf_shrink)
+ return;
+ }
+ hal8812a2_set_sw_rf_rx_lpf_corner(btcoexist,
+ coex_dm->cur_rf_rx_lpf_shrink);
+
+ coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink;
+}
+
+static void halbtc8812a2ant_set_dac_swing_reg(struct btc_coexist *btcoexist,
+ u32 level)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], Write SwDacSwing = 0x%x\n", level);
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0xc5b, 0x3e, (u8)level);
+}
+
+static void hal8812a2_set_sw_fulltime_dac_swing(struct btc_coexist *btcoexist,
+ bool sw_dac_swing_on,
+ u32 sw_dac_swing_lvl)
+{
+ if (sw_dac_swing_on)
+ halbtc8812a2ant_set_dac_swing_reg(btcoexist, sw_dac_swing_lvl);
+ else
+ halbtc8812a2ant_set_dac_swing_reg(btcoexist, 0x18);
+}
+
+static void halbtc8812a2ant_dac_swing(struct btc_coexist *btcoexist,
+ bool force_exec, bool dac_swing_on,
+ u32 dac_swing_lvl)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW,
+ "[BTCoex], %s turn DacSwing =%s, dac_swing_lvl = 0x%x\n",
+ (force_exec ? "force to" : ""),
+ ((dac_swing_on) ? "ON" : "OFF"), dac_swing_lvl);
+ coex_dm->cur_dac_swing_on = dac_swing_on;
+ coex_dm->cur_dac_swing_lvl = dac_swing_lvl;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL,
+ "[BTCoex], pre_dac_swing_on =%d, pre_dac_swing_lvl = 0x%x, cur_dac_swing_on =%d, cur_dac_swing_lvl = 0x%x\n",
+ coex_dm->pre_dac_swing_on,
+ coex_dm->pre_dac_swing_lvl,
+ coex_dm->cur_dac_swing_on,
+ coex_dm->cur_dac_swing_lvl);
+
+ if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) &&
+ (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl))
+ return;
+ }
+ mdelay(30);
+ hal8812a2_set_sw_fulltime_dac_swing(btcoexist, dac_swing_on,
+ dac_swing_lvl);
+
+ coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on;
+ coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl;
+}
+
+static void halbtc8812a2ant_set_adc_back_off(struct btc_coexist *btcoexist,
+ bool adc_back_off)
+{
+ if (adc_back_off) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], BB BackOff Level On!\n");
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x3);
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], BB BackOff Level Off!\n");
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x1);
+ }
+}
+
+static void halbtc8812a2ant_adc_back_off(struct btc_coexist *btcoexist,
+ bool force_exec, bool adc_back_off)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW,
+ "[BTCoex], %s turn AdcBackOff = %s\n",
+ (force_exec ? "force to" : ""),
+ ((adc_back_off) ? "ON" : "OFF"));
+ coex_dm->cur_adc_back_off = adc_back_off;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL,
+ "[BTCoex], pre_adc_back_off =%d, cur_adc_back_off =%d\n",
+ coex_dm->pre_adc_back_off, coex_dm->cur_adc_back_off);
+
+ if (coex_dm->pre_adc_back_off == coex_dm->cur_adc_back_off)
+ return;
+ }
+ halbtc8812a2ant_set_adc_back_off(btcoexist, coex_dm->cur_adc_back_off);
+
+ coex_dm->pre_adc_back_off = coex_dm->cur_adc_back_off;
+}
+
+static void halbtc8812a2ant_set_coex_table(struct btc_coexist *btcoexist,
+ u32 val0x6c0, u32 val0x6c4,
+ u32 val0x6c8, u8 val0x6cc)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0);
+ btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0);
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4);
+ btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4);
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8);
+ btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8);
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC,
+ "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc);
+ btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc);
+}
+
+static void halbtc8812a2ant_coex_table(struct btc_coexist *btcoexist,
+ bool force_exec, u32 val0x6c0,
+ u32 val0x6c4, u32 val0x6c8,
+ u8 val0x6cc)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW,
+ "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n",
+ (force_exec ? "force to" : ""), val0x6c0, val0x6c4,
+ val0x6c8, val0x6cc);
+ coex_dm->cur_val_0x6c0 = val0x6c0;
+ coex_dm->cur_val_0x6c4 = val0x6c4;
+ coex_dm->cur_val_0x6c8 = val0x6c8;
+ coex_dm->cur_val_0x6cc = val0x6cc;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL,
+ "[BTCoex], pre_val_0x6c0 = 0x%x, pre_val_0x6c4 = 0x%x, pre_val_0x6c8 = 0x%x, pre_val_0x6cc = 0x%x !!\n",
+ coex_dm->pre_val_0x6c0, coex_dm->pre_val_0x6c4,
+ coex_dm->pre_val_0x6c8, coex_dm->pre_val_0x6cc);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL,
+ "[BTCoex], cur_val_0x6c0 = 0x%x, cur_val_0x6c4 = 0x%x, cur_val_0x6c8 = 0x%x, cur_val_0x6cc = 0x%x !!\n",
+ coex_dm->cur_val_0x6c0, coex_dm->cur_val_0x6c4,
+ coex_dm->cur_val_0x6c8, coex_dm->cur_val_0x6cc);
+
+ if ((coex_dm->pre_val_0x6c0 == coex_dm->cur_val_0x6c0) &&
+ (coex_dm->pre_val_0x6c4 == coex_dm->cur_val_0x6c4) &&
+ (coex_dm->pre_val_0x6c8 == coex_dm->cur_val_0x6c8) &&
+ (coex_dm->pre_val_0x6cc == coex_dm->cur_val_0x6cc))
+ return;
+ }
+ halbtc8812a2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4,
+ val0x6c8, val0x6cc);
+
+ coex_dm->pre_val_0x6c0 = coex_dm->cur_val_0x6c0;
+ coex_dm->pre_val_0x6c4 = coex_dm->cur_val_0x6c4;
+ coex_dm->pre_val_0x6c8 = coex_dm->cur_val_0x6c8;
+ coex_dm->pre_val_0x6cc = coex_dm->cur_val_0x6cc;
+}
+
+static void halbtc8812a2ant_coex_table_with_type(struct btc_coexist *btcoexist,
+ bool force_exec, u8 type)
+{
+ type = 6;/*troy force type to 6*/
+ switch (type) {
+ case 0:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0x55555555,
+ 0x5a5a5a5a, 0xffffff, 0x3);
+ break;
+ case 1:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a,
+ 0x5a5a5a5a, 0xffffff, 0x3);
+ break;
+ case 2:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0x55555555,
+ 0x5ffb5ffb, 0xffffff, 0x3);
+ break;
+ case 3:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0x5fdf5fdf,
+ 0x5fdb5fdb, 0xffffff, 0x3);
+ break;
+ case 4:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0xdfffdfff,
+ 0x5fdb5fdb, 0xffffff, 0x3);
+ break;
+ case 5:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0x5ddd5ddd,
+ 0x5fdb5fdb, 0xffffff, 0x3);
+ break;
+ case 6:
+ halbtc8812a2ant_coex_table(btcoexist, force_exec, 0x5f5f5f5f,
+ 0x5f5f5f5f, 0xffffff, 0x3);
+ default:
+ break;
+ }
+}
+
+static void hal8812a2_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist,
+ bool enable)
+{
+ u8 data_len = 3;
+ u8 buf[5] = {0};
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC,
+ "[BTCoex], %s BT Ignore Wlan_Act\n",
+ (enable ? "Enable" : "Disable"));
+
+ buf[0] = data_len;
+ buf[1] = 0x1; /* OP_Code */
+ buf[2] = 0x1; /* OP_Code_Length */
+ if (enable)
+ buf[3] = 0x1; /* OP_Code_Content */
+ else
+ buf[3] = 0x0;
+
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_COEX,
+ (void *)&buf[0]);
+}
+
+static void hal8812a2_ignore_wlan_act(struct btc_coexist *btcoexist,
+ bool force_exec, bool enable)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], %s turn Ignore WlanAct %s\n",
+ (force_exec ? "force to" : ""), (enable ? "ON" : "OFF"));
+ coex_dm->cur_ignore_wlan_act = enable;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n",
+ coex_dm->pre_ignore_wlan_act,
+ coex_dm->cur_ignore_wlan_act);
+ if (coex_dm->pre_ignore_wlan_act ==
+ coex_dm->cur_ignore_wlan_act)
+ return;
+ }
+ hal8812a2_set_fw_ignore_wlan_act(btcoexist, enable);
+
+ coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act;
+}
+
+static void halbtc8812a2ant_set_fw_pstdma(struct btc_coexist *btcoexist,
+ u8 byte1, u8 byte2, u8 byte3,
+ u8 byte4, u8 byte5)
+{
+ u8 h2c_parameter[5] = {0};
+
+ h2c_parameter[0] = byte1;
+ h2c_parameter[1] = byte2;
+ h2c_parameter[2] = byte3;
+ h2c_parameter[3] = byte4;
+ h2c_parameter[4] = byte5;
+
+ coex_dm->ps_tdma_para[0] = byte1;
+ coex_dm->ps_tdma_para[1] = byte2;
+ coex_dm->ps_tdma_para[2] = byte3;
+ coex_dm->ps_tdma_para[3] = byte4;
+ coex_dm->ps_tdma_para[4] = byte5;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC,
+ "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n",
+ h2c_parameter[0],
+ h2c_parameter[1]<<24 | h2c_parameter[2] << 16 |
+ h2c_parameter[3]<<8 | h2c_parameter[4]);
+ btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter);
+}
+
+static void halbtc8812a2ant_set_lps_rpwm(struct btc_coexist *btcoexist,
+ u8 lps_val, u8 rpwm_val)
+{
+ u8 lps = lps_val;
+ u8 rpwm = rpwm_val;
+
+ btcoexist->btc_set(btcoexist, BTC_SET_U1_LPS_VAL, &lps);
+ btcoexist->btc_set(btcoexist, BTC_SET_U1_RPWM_VAL, &rpwm);
+}
+
+static void halbtc8812a2ant_lps_rpwm(struct btc_coexist *btcoexist,
+ bool force_exec, u8 lps_val, u8 rpwm_val)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n",
+ (force_exec ? "force to" : ""), lps_val, rpwm_val);
+ coex_dm->cur_lps = lps_val;
+ coex_dm->cur_rpwm = rpwm_val;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], pre_lps/cur_lps = 0x%x/0x%x, pre_rpwm/cur_rpwm = 0x%x/0x%x!!\n",
+ coex_dm->pre_lps, coex_dm->cur_lps,
+ coex_dm->pre_rpwm, coex_dm->cur_rpwm);
+
+ if ((coex_dm->pre_lps == coex_dm->cur_lps) &&
+ (coex_dm->pre_rpwm == coex_dm->cur_rpwm))
+ return;
+ }
+ halbtc8812a2ant_set_lps_rpwm(btcoexist, lps_val, rpwm_val);
+
+ coex_dm->pre_lps = coex_dm->cur_lps;
+ coex_dm->pre_rpwm = coex_dm->cur_rpwm;
+}
+
+static void halbtc8812a2ant_sw_mechanism1(struct btc_coexist *btcoexist,
+ bool shrink_rx_LPF,
+ bool low_penalty_RA,
+ bool limited_DIG,
+ bool BT_LNA_constrain)
+{
+ halbtc8812a2ant_rf_shrink(btcoexist, NORMAL_EXEC, shrink_rx_LPF);
+}
+
+static void halbtc8812a2ant_sw_mechanism2(struct btc_coexist *btcoexist,
+ bool agc_table_shift,
+ bool adc_back_off,
+ bool sw_dac_swing,
+ u32 dac_swing_lvl)
+{
+ halbtc8812a2ant_adc_back_off(btcoexist, NORMAL_EXEC, adc_back_off);
+ halbtc8812a2ant_dac_swing(btcoexist, NORMAL_EXEC, sw_dac_swing,
+ dac_swing_lvl);
+}
+
+static void halbtc8812a2ant_set_ant_path(struct btc_coexist *btcoexist,
+ u8 ant_pos_type, bool init_hw_cfg,
+ bool wifi_off)
+{
+ u8 u1_tmp = 0;
+
+ if (init_hw_cfg) {
+ btcoexist->btc_write_4byte(btcoexist, 0x900, 0x00000400);
+ btcoexist->btc_write_1byte(btcoexist, 0x76d, 0x1);
+ }
+
+ /* ext switch setting */
+ switch (ant_pos_type) {
+ case BTC_ANT_WIFI_AT_CPL_MAIN:
+ break;
+ case BTC_ANT_WIFI_AT_CPL_AUX:
+ u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0xcb7);
+ u1_tmp &= ~BIT3;
+ u1_tmp |= BIT2;
+ btcoexist->btc_write_1byte(btcoexist, 0xcb7, u1_tmp);
+ break;
+ default:
+ break;
+ }
+}
+
+static void halbtc8812a2ant_ps_tdma(struct btc_coexist *btcoexist,
+ bool force_exec, bool turn_on, u8 type)
+{
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], %s turn %s PS TDMA, type =%d\n",
+ (force_exec ? "force to" : ""),
+ (turn_on ? "ON" : "OFF"), type);
+ coex_dm->cur_ps_tdma_on = turn_on;
+ coex_dm->cur_ps_tdma = type;
+
+ if (!force_exec) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], pre_ps_tdma_on = %d, cur_ps_tdma_on = %d!!\n",
+ coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], pre_ps_tdma = %d, cur_ps_tdma = %d!!\n",
+ coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma);
+
+ if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) &&
+ (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma))
+ return;
+ }
+ /*troy force case*/
+ turn_on = 1;
+ type = 1;
+ if (turn_on) {
+ switch (type) {
+ case 1:
+ default:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd1, 0x1d,
+ 0x1d, 0x01, 0x10);
+ break;
+ case 2:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12,
+ 0x12, 0xa1, 0x90);
+ break;
+ case 3:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c,
+ 0x3, 0xb1, 0x90);
+ break;
+ case 4:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x10,
+ 0x03, 0xb1, 0x90);
+ break;
+ case 5:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a,
+ 0x1a, 0x21, 0x10);
+ break;
+ case 6:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12,
+ 0x12, 0x21, 0x10);
+ break;
+ case 7:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c,
+ 0x3, 0x21, 0x10);
+ break;
+ case 8:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x10,
+ 0x3, 0x21, 0x10);
+ break;
+ case 9:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a,
+ 0x1a, 0xa1, 0x10);
+ break;
+ case 10:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12,
+ 0x12, 0xa1, 0x10);
+ break;
+ case 11:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c,
+ 0x03, 0xb1, 0x10);
+ break;
+ case 12:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x10,
+ 0x03, 0xb1, 0x10);
+ break;
+ case 13:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a,
+ 0x1a, 0x21, 0x10);
+ break;
+ case 14:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12,
+ 0x12, 0x21, 0x10);
+ break;
+ case 15:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c,
+ 0x03, 0x21, 0x10);
+ break;
+ case 16:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x10,
+ 0x03, 0x21, 0x10);
+ break;
+ case 17:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x15,
+ 0x03, 0xb1, 0x10);
+ break;
+ case 18:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5,
+ 0x5, 0xe1, 0x90);
+ break;
+ case 19:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x25,
+ 0x25, 0xe1, 0x90);
+ break;
+ case 20:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x25,
+ 0x25, 0x60, 0x90);
+ break;
+ case 21:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x15,
+ 0x03, 0x70, 0x90);
+ break;
+ case 71:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a,
+ 0x1a, 0xe1, 0x90);
+ break;
+
+ /* following cases is for wifi rssi low, started from 81 */
+ case 81:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd3, 0x3a,
+ 0x3, 0x90, 0x50);
+ break;
+ case 82:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd3, 0x2b,
+ 0x3, 0x90, 0x50);
+ break;
+ case 83:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd3, 0x21,
+ 0x3, 0x90, 0x50);
+ break;
+ case 84:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd3, 0x15,
+ 0x3, 0x90, 0x50);
+ break;
+ case 85:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd3, 0x1d,
+ 0x1d, 0x80, 0x50);
+ break;
+ case 86:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0xd3, 0x15,
+ 0x15, 0x80, 0x50);
+ break;
+ }
+ } else {
+ /* disable PS tdma */
+ switch (type) {
+ case 0: /* ANT2PTA, 0x778 = 0x1 */
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0x8, 0x0,
+ 0x0, 0x0, 0x0);
+ break;
+ case 1: /* ANT2BT, 0x778 =3 */
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0,
+ 0x0, 0x08, 0x0);
+ mdelay(5);
+ halbtc8812a2ant_set_ant_path(btcoexist,
+ BTC_ANT_WIFI_AT_CPL_AUX,
+ false, false);
+ break;
+ default:
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0,
+ 0x0, 0x00, 0x0);
+ break;
+ }
+ }
+
+ /* update pre state */
+ coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on;
+ coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma;
+}
+
+static void halbtc8812a2ant_coex_all_off(struct btc_coexist *btcoexist)
+{
+ /* fw all off */
+ /* halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); */
+ halbtc8812a2ant_set_fw_pstdma(btcoexist, 0x08, 0x0, 0x0, 0x0, 0x0);
+
+ mdelay(5);
+ halbtc8812a2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_CPL_AUX,
+ false, false);
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+
+ /* sw all off */
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false, false, 0x18);
+
+ /* hw all off */
+ halbtc8812a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55555555,
+ 0x55555555, 0xffff, 0x3);
+}
+
+static void halbtc8812a2ant_init_coex_dm(struct btc_coexist *btcoexist)
+{
+ /* force to reset coex mechanism */
+ halbtc8812a2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1);
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, FORCE_EXEC, 0);
+
+ halbtc8812a2ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false, false, 0x18);
+}
+
+static void hal8812a2_ps_tdma_chk_for_pwr_save(struct btc_coexist *btcoexist,
+ bool new_ps_state)
+{
+ u8 lps_mode = 0x0;
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_LPS_MODE, &lps_mode);
+
+ if (lps_mode) { /* already under LPS state */
+ if (new_ps_state) {
+ /* keep state under LPS, do nothing. */
+ } else {
+ /* will leave LPS state, turn off psTdma first */
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ false, 0);
+ }
+ } else { /* NO PS state */
+ if (new_ps_state) {
+ /* will enter LPS state, turn off psTdma first */
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ false, 0);
+ } else {
+ /* keep state under NO PS state, do nothing. */
+ }
+ }
+}
+
+static void halbtc8812a2ant_power_save_state(struct btc_coexist *btcoexist,
+ u8 ps_type, bool low_pwr_disable,
+ u8 lps_val, u8 rpwm_val)
+{
+ switch (ps_type) {
+ case BTC_PS_WIFI_NATIVE:
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
+ &low_pwr_disable);
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL);
+ break;
+ case BTC_PS_LPS_ON:
+ hal8812a2_ps_tdma_chk_for_pwr_save(btcoexist, true);
+ halbtc8812a2ant_lps_rpwm(btcoexist, NORMAL_EXEC, lps_val,
+ rpwm_val);
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
+ &low_pwr_disable);
+ /* power save must executed before psTdma. */
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+static void halbtc8812a2ant_action_bt_inquiry(struct btc_coexist *btcoexist)
+{
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3);
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false, false, 0x18);
+}
+
+/* Refactored routine */
+static void handle_wifi_not_busy(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Wifi Connected-Idle + BT Busy!!\n");
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+
+ if (BTC_RSSI_HIGH(wifi_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ if (BTC_RSSI_HIGH(wifi_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+
+ if (BTC_RSSI_HIGH(wifi_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 17);
+ else
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 83);
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false, false, 0x18);
+}
+
+static bool halbtc8812a2ant_is_common_action(struct btc_coexist *btcoexist)
+{
+ struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+ bool common = false, wifi_connected = false, wifi_busy = false;
+ bool bt_hs_on = false;
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+ &wifi_connected);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+
+ if (bt_link_info->sco_exist || bt_link_info->hid_exist)
+ halbtc8812a2ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 0, 0, 0);
+ else
+ halbtc8812a2ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
+
+ if (!wifi_connected) {
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ false, 0x0, 0x0);
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false,
+ 0x8);
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Wifi non-connected idle!!\n");
+
+ if ((BT_8812A_2ANT_BT_STATUS_NON_CONNECTED_IDLE ==
+ coex_dm->bt_status) ||
+ (BT_8812A_2ANT_BT_STATUS_CONNECTED_IDLE ==
+ coex_dm->bt_status)) {
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 1);
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ false, 0);
+ } else {
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 0);
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ false, 1);
+ }
+
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, false, false,
+ false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false, false,
+ 0x18);
+ common = true;
+ } else {
+ if (BT_8812A_2ANT_BT_STATUS_NON_CONNECTED_IDLE ==
+ coex_dm->bt_status) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Wifi connected + BT non connected-idle!!\n");
+ halbtc8812a2ant_power_save_state(btcoexist,
+ BTC_PS_WIFI_NATIVE,
+ false, 0x0, 0x0);
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC,
+ false, false, 0x8);
+
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 1);
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ false, 0);
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist,
+ NORMAL_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, false,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+
+ common = true;
+ } else if (BT_8812A_2ANT_BT_STATUS_CONNECTED_IDLE ==
+ coex_dm->bt_status) {
+ if (bt_hs_on)
+ return false;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Wifi connected + BT connected-idle!!\n");
+ halbtc8812a2ant_power_save_state(btcoexist,
+ BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC,
+ false, false, 0x8);
+
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 1);
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ false, 0);
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist,
+ NORMAL_EXEC, 6);
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, false,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ common = true;
+ } else {
+ if (wifi_busy) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Wifi Connected-Busy + BT Busy!!\n");
+ common = false;
+ } else {
+ handle_wifi_not_busy(btcoexist);
+ common = true;
+ }
+ }
+ }
+ return common;
+}
+
+/* Refactored routine */
+static void handle_sco_hid_true(struct btc_coexist *btcoexist, bool tx_pause,
+ u8 max_interval)
+{
+ if (tx_pause) {
+ if (max_interval == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 13);
+ coex_dm->ps_tdma_du_adj_type = 13;
+ } else if (max_interval == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (max_interval == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ }
+ } else {
+ if (max_interval == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 9);
+ coex_dm->ps_tdma_du_adj_type = 9;
+ } else if (max_interval == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (max_interval == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ }
+ }
+}
+
+/* Refactored routine */
+static void handle_sco_hid_false(struct btc_coexist *btcoexist, bool tx_pause,
+ u8 max_interval)
+{
+ if (tx_pause) {
+ if (max_interval == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 5);
+ coex_dm->ps_tdma_du_adj_type = 5;
+ } else if (max_interval == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (max_interval == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ }
+ } else {
+ if (max_interval == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 1);
+ coex_dm->ps_tdma_du_adj_type = 1;
+ } else if (max_interval == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (max_interval == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ }
+ }
+}
+
+/* Refactored routine */
+static void handle_max_int_1(struct btc_coexist *btcoexist, bool tx_pause,
+ u8 result)
+{
+ if (tx_pause) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], TxPause = 1\n");
+
+ if (coex_dm->cur_ps_tdma == 71) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 5);
+ coex_dm->ps_tdma_du_adj_type = 5;
+ } else if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 5);
+ coex_dm->ps_tdma_du_adj_type = 5;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 4) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 8);
+ coex_dm->ps_tdma_du_adj_type = 8;
+ }
+ if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 13);
+ coex_dm->ps_tdma_du_adj_type = 13;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 12) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 16);
+ coex_dm->ps_tdma_du_adj_type = 16;
+ }
+
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 5) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 8);
+ coex_dm->ps_tdma_du_adj_type = 8;
+ } else if (coex_dm->cur_ps_tdma == 13) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 16);
+ coex_dm->ps_tdma_du_adj_type = 16;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 8) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 5);
+ coex_dm->ps_tdma_du_adj_type = 5;
+ } else if (coex_dm->cur_ps_tdma == 16) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 13);
+ coex_dm->ps_tdma_du_adj_type = 13;
+ }
+ }
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], TxPause = 0\n");
+ if (coex_dm->cur_ps_tdma == 5) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 71);
+ coex_dm->ps_tdma_du_adj_type = 71;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 8) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 4);
+ coex_dm->ps_tdma_du_adj_type = 4;
+ }
+ if (coex_dm->cur_ps_tdma == 13) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 9);
+ coex_dm->ps_tdma_du_adj_type = 9;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 16) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 12);
+ coex_dm->ps_tdma_du_adj_type = 12;
+ }
+
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 71) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 1);
+ coex_dm->ps_tdma_du_adj_type = 1;
+ } else if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 4);
+ coex_dm->ps_tdma_du_adj_type = 4;
+ } else if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 12);
+ coex_dm->ps_tdma_du_adj_type = 12;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 4) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 1);
+ coex_dm->ps_tdma_du_adj_type = 1;
+ } else if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 71);
+ coex_dm->ps_tdma_du_adj_type = 71;
+ } else if (coex_dm->cur_ps_tdma == 12) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 9);
+ coex_dm->ps_tdma_du_adj_type = 9;
+ }
+ }
+ }
+}
+
+/* Refactored routine */
+static void handle_max_int_2(struct btc_coexist *btcoexist, bool tx_pause,
+ u8 result)
+{
+ if (tx_pause) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], TxPause = 1\n");
+ if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 4) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 8);
+ coex_dm->ps_tdma_du_adj_type = 8;
+ }
+ if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 12) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 16);
+ coex_dm->ps_tdma_du_adj_type = 16;
+ }
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 5) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 8);
+ coex_dm->ps_tdma_du_adj_type = 8;
+ } else if (coex_dm->cur_ps_tdma == 13) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 16);
+ coex_dm->ps_tdma_du_adj_type = 16;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 8) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 6);
+ coex_dm->ps_tdma_du_adj_type = 6;
+ } else if (coex_dm->cur_ps_tdma == 16) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 14);
+ coex_dm->ps_tdma_du_adj_type = 14;
+ }
+ }
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], TxPause = 0\n");
+ if (coex_dm->cur_ps_tdma == 5) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 8) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 4);
+ coex_dm->ps_tdma_du_adj_type = 4;
+ }
+ if (coex_dm->cur_ps_tdma == 13) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 16) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 12);
+ coex_dm->ps_tdma_du_adj_type = 12;
+ }
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 4);
+ coex_dm->ps_tdma_du_adj_type = 4;
+ } else if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 12);
+ coex_dm->ps_tdma_du_adj_type = 12;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 4) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 12) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 10);
+ coex_dm->ps_tdma_du_adj_type = 10;
+ }
+ }
+ }
+}
+
+/* Refactored routine */
+static void handle_max_int_3(struct btc_coexist *btcoexist, bool tx_pause,
+ u8 result)
+{
+ if (tx_pause) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], TxPause = 1\n");
+ if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 4) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 8);
+ coex_dm->ps_tdma_du_adj_type = 8;
+ }
+ if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 12) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 16);
+ coex_dm->ps_tdma_du_adj_type = 16;
+ }
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 5) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 8);
+ coex_dm->ps_tdma_du_adj_type = 8;
+ } else if (coex_dm->cur_ps_tdma == 13) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 16);
+ coex_dm->ps_tdma_du_adj_type = 16;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 8) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 7);
+ coex_dm->ps_tdma_du_adj_type = 7;
+ } else if (coex_dm->cur_ps_tdma == 16) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 15);
+ coex_dm->ps_tdma_du_adj_type = 15;
+ }
+ }
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], TxPause = 0\n");
+ if (coex_dm->cur_ps_tdma == 5) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 6) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 7) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 8) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 4);
+ coex_dm->ps_tdma_du_adj_type = 4;
+ }
+ if (coex_dm->cur_ps_tdma == 13) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 14) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 15) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 16) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 12);
+ coex_dm->ps_tdma_du_adj_type = 12;
+ }
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 4);
+ coex_dm->ps_tdma_du_adj_type = 4;
+ } else if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 12);
+ coex_dm->ps_tdma_du_adj_type = 12;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 4) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 3) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 3);
+ coex_dm->ps_tdma_du_adj_type = 3;
+ } else if (coex_dm->cur_ps_tdma == 12) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ } else if (coex_dm->cur_ps_tdma == 10) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ }
+ }
+ }
+}
+
+static void halbtc8812a2ant_tdma_duration_adjust(struct btc_coexist *btcoexist,
+ bool sco_hid, bool tx_pause,
+ u8 max_interval)
+{
+ static s32 up, dn, m, n, wait_count;
+ long result; /* 0: no change, +1: inc, -1: dec WiFi duration */
+ u8 retry_count = 0;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], TdmaDurationAdjust()\n");
+
+ coex_dm->auto_tdma_adjust_low_rssi = false;
+
+ if (!coex_dm->reset_tdma_adjust) {
+ coex_dm->reset_tdma_adjust = true;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], first run TdmaDurationAdjust()!!\n");
+ if (sco_hid)
+ handle_sco_hid_true(btcoexist, tx_pause, max_interval);
+ else
+ handle_sco_hid_false(btcoexist, tx_pause, max_interval);
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ wait_count = 0;
+ } else {
+ /* acquire the BT TRx retry count from BT_Info byte2 */
+ retry_count = coex_sta->bt_retry_cnt;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], retry_count = %d\n", retry_count);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], up =%d, dn =%d, m =%d, n =%d, wait_count =%d\n",
+ up, dn, m, n, wait_count);
+ result = 0;
+ wait_count++;
+
+ if (retry_count == 0) {
+ /* no retry in the last 2-second duration */
+ up++;
+ dn--;
+
+ if (dn <= 0)
+ dn = 0;
+
+ if (up >= n) {
+ wait_count = 0;
+ n = 3;
+ up = 0;
+ dn = 0;
+ result = 1;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], Increase wifi duration!!\n");
+ }
+ } else if (retry_count <= 3) {
+ /* <=3 retry in the last 2-second duration */
+ up--;
+ dn++;
+
+ if (up <= 0)
+ up = 0;
+
+ if (dn == 2) {
+ if (wait_count <= 2)
+ m++;
+ else
+ m = 1;
+
+ if (m >= 20)
+ m = 20;
+
+ n = 3*m;
+ up = 0;
+ dn = 0;
+ wait_count = 0;
+ result = -1;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], Decrease wifi duration for retryCounter<3!!\n");
+ }
+ } else {
+ if (wait_count == 1)
+ m++;
+ else
+ m = 1;
+
+ if (m >= 20)
+ m = 20;
+
+ n = 3*m;
+ up = 0;
+ dn = 0;
+ wait_count = 0;
+ result = -1;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], Decrease wifi duration for retryCounter>3!!\n");
+ }
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], max Interval = %d\n", max_interval);
+ if (max_interval == 1)
+ handle_max_int_1(btcoexist, tx_pause, result);
+ else if (max_interval == 2)
+ handle_max_int_2(btcoexist, tx_pause, result);
+ else if (max_interval == 3)
+ handle_max_int_3(btcoexist, tx_pause, result);
+ }
+
+ /* if current PsTdma does not match with the recorded one
+ * (when scan, dhcp...), then we have to adjust it back to
+ * the previous record one.
+ */
+ if (coex_dm->cur_ps_tdma != coex_dm->ps_tdma_du_adj_type) {
+ bool scan = false, link = false, roam = false;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], PsTdma type dismatch!!!, cur_ps_tdma =%d, recordPsTdma =%d\n",
+ coex_dm->cur_ps_tdma, coex_dm->ps_tdma_du_adj_type);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam);
+
+ if (!scan && !link && !roam) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ coex_dm->ps_tdma_du_adj_type);
+ } else {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n");
+ }
+ }
+}
+
+/* pstdma for wifi rssi low */
+static void hal8812a2_tdma_dur_adj_wifi_rssi_lo(struct btc_coexist *btcoexist)
+{
+ static s32 up, dn, m, n, wait_count;
+ s32 result; /* 0: no change, +1: inc, -1: dec WiFi duration */
+ u8 retry_count = 0, bt_info_ext;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+ "[BTCoex], hal8812a2_tdma_dur_adj_wifi_rssi_lo()\n");
+ coex_dm->reset_tdma_adjust = false;
+
+ if (!coex_dm->auto_tdma_adjust_low_rssi) {
+ coex_dm->auto_tdma_adjust_low_rssi = true;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], first run TdmaDurationAdjustForWifiRssiLow()!!\n");
+
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 82);
+ coex_dm->ps_tdma_du_adj_type = 82;
+ /* */
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ wait_count = 0;
+ } else {
+ /* acquire the BT TRx retry count from BT_Info byte2 */
+ retry_count = coex_sta->bt_retry_cnt;
+ bt_info_ext = coex_sta->bt_info_ext;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], retry_count = %d\n", retry_count);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], up =%d, dn =%d, m =%d, n =%d, wait_count =%d\n",
+ up, dn, m, n, wait_count);
+ result = 0;
+ wait_count++;
+
+ if (retry_count == 0) {
+ /* no retry in the last 2-second duration */
+ up++;
+ dn--;
+
+ if (dn <= 0)
+ dn = 0;
+
+ if (up >= n) {
+ wait_count = 0;
+ n = 3;
+ up = 0;
+ dn = 0;
+ result = 1;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], Increase wifi duration!!\n");
+ }
+ } else if (retry_count <= 3) {
+ /* <=3 retry in the last 2-second duration */
+ up--;
+ dn++;
+
+ if (up <= 0)
+ up = 0;
+
+ if (dn == 2) {
+ if (wait_count <= 2)
+ m++;
+ else
+ m = 1;
+ if (m >= 20)
+ m = 20;
+
+ n = 3*m;
+ up = 0;
+ dn = 0;
+ wait_count = 0;
+ result = -1;
+ BTC_PRINT(BTC_MSG_ALGORITHM,
+ ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], Decrease wifi duration for retryCounter<3!!\n");
+ }
+ } else {
+ if (wait_count == 1)
+ m++;
+ else
+ m = 1;
+
+ if (m >= 20)
+ m = 20;
+
+ n = 3*m;
+ up = 0;
+ dn = 0;
+ wait_count = 0;
+ result = -1;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+ "[BTCoex], Decrease wifi duration for retryCounter>3!!\n");
+ }
+
+ if (result == -1) {
+ if ((BT_INFO_8812A_2ANT_A2DP_BASIC_RATE(bt_info_ext)) &&
+ ((coex_dm->cur_ps_tdma == 81) ||
+ (coex_dm->cur_ps_tdma == 82))) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 83);
+ coex_dm->ps_tdma_du_adj_type = 83;
+ } else if (coex_dm->cur_ps_tdma == 81) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 82);
+ coex_dm->ps_tdma_du_adj_type = 82;
+ } else if (coex_dm->cur_ps_tdma == 82) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 83);
+ coex_dm->ps_tdma_du_adj_type = 83;
+ } else if (coex_dm->cur_ps_tdma == 83) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 84);
+ coex_dm->ps_tdma_du_adj_type = 84;
+ }
+ } else if (result == 1) {
+ if ((BT_INFO_8812A_2ANT_A2DP_BASIC_RATE(bt_info_ext)) &&
+ ((coex_dm->cur_ps_tdma == 81) ||
+ (coex_dm->cur_ps_tdma == 82))) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 83);
+ coex_dm->ps_tdma_du_adj_type = 83;
+ } else if (coex_dm->cur_ps_tdma == 84) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 83);
+ coex_dm->ps_tdma_du_adj_type = 83;
+ } else if (coex_dm->cur_ps_tdma == 83) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 82);
+ coex_dm->ps_tdma_du_adj_type = 82;
+ } else if (coex_dm->cur_ps_tdma == 82) {
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 81);
+ coex_dm->ps_tdma_du_adj_type = 81;
+ }
+ }
+
+ if (coex_dm->cur_ps_tdma != 81 &&
+ coex_dm->cur_ps_tdma != 82 &&
+ coex_dm->cur_ps_tdma != 83 &&
+ coex_dm->cur_ps_tdma != 84) {
+ /* recover to previous adjust type */
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ coex_dm->ps_tdma_du_adj_type);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_sco(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+
+ /* coex table */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+
+ /* pstdma */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+ else
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ true, 0x6);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ true, 0x6);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ true, 0x6);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ true, 0x6);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_sco_hid(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+
+ /* coex table */
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+
+ /* pstdma */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+ else
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, true, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x6);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x6);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x6);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x6);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_hid(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 3);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9);
+ else
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ true, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ }
+}
+
+/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */
+static void halbtc8812a2ant_action_a2dp(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, false,
+ false, 1);
+ else
+ hal8812a2_tdma_dur_adj_wifi_rssi_lo(btcoexist);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ /* sw mechanism */
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0,
+ 2, 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, false,
+ false, 2);
+ else
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, false,
+ true, 2);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ /* sw mechanism */
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, true, 0x6);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, true, 0x6);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, true, 0x6);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, true, 0x6);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_pan_edr(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1);
+ else
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 85);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ /* sw mechanism */
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ }
+}
+
+/* PAN(HS) only */
+static void halbtc8812a2ant_action_pan_hs(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+
+ /* coex table */
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+
+ /* pstdma */
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ }
+}
+
+/* PAN(EDR)+A2DP */
+static void halbtc8812a2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist,
+ BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist,
+ BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 2);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 5);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 0);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state)) {
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, false,
+ false, 3);
+ } else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state)) {
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, false, true, 3);
+ } else {
+ coex_dm->reset_tdma_adjust = false;
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 86);
+ }
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ false, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 3);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
+ else
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 85);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ true, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true,
+ false, false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false,
+ true, false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false,
+ false, false, 0x18);
+ }
+ }
+}
+
+/* HID+A2DP+PAN(EDR) */
+static void hal8812a2_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 3);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state)) {
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, false, 3);
+ } else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state)) {
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, true, 3);
+ } else {
+ coex_dm->reset_tdma_adjust = false;
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 86);
+ }
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ true, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ }
+ }
+}
+
+static void hal8812a2ant_action_hid_a2dp_pan_hs(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 3);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, false, 2);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, true, 2);
+ else
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, true, 2);
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ true, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ }
+ }
+}
+
+static void halbtc8812a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
+{
+ u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH;
+ u8 bt_rssi_state = BTC_RSSI_STATE_HIGH;
+ u32 wifi_bw;
+
+ wifi_rssi_state = halbtc8812a2ant_wifi_rssi_state(btcoexist, 0, 2,
+ 34, 0);
+ bt_rssi_state = halbtc8812a2ant_bt_rssi_state(3, 34, 42);
+
+ /* power save state */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ true, 0x0, 0x0);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_power_save_state(btcoexist,
+ BTC_PS_WIFI_NATIVE, true,
+ 0x0, 0x0);
+ else
+ halbtc8812a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ true, 0x50, 0x4);
+
+ /* coex table */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 3);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+ else
+ halbtc8812a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+
+ /* pstdma */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state)) {
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, false, 2);
+ } else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state)) {
+ halbtc8812a2ant_tdma_duration_adjust(btcoexist, true, true, 2);
+ } else {
+ coex_dm->reset_tdma_adjust = false;
+ halbtc8812a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 82);
+ }
+
+ /* decrease BT power */
+ if (BTC_RSSI_LOW(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ halbtc8812a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 4);
+
+ /* limited Rx */
+ if (BTC_RSSI_HIGH(wifi_rssi_state) && BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else if (BTC_RSSI_LOW(wifi_rssi_state) &&
+ BTC_RSSI_HIGH(bt_rssi_state))
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ false, 0x8);
+ else
+ halbtc8812a2ant_limited_rx(btcoexist, NORMAL_EXEC, false,
+ true, 0x8);
+
+ /* fw dac swing level */
+ halbtc8812a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ /* sw mechanism */
+ if (BTC_WIFI_BW_HT40 == wifi_bw) {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, true, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ }
+ } else {
+ if (BTC_RSSI_HIGH(wifi_rssi_state)) {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, true, false,
+ false, 0x18);
+ } else {
+ halbtc8812a2ant_sw_mechanism1(btcoexist, false, true,
+ false, false);
+ halbtc8812a2ant_sw_mechanism2(btcoexist, false, false,
+ false, 0x18);
+ }
+ }
+}
+
+static void halbtc8812a2ant_coex_under_5g(struct btc_coexist *btcoexist)
+{
+ halbtc8812a2ant_coex_all_off(btcoexist);
+ hal8812a2_ignore_wlan_act(btcoexist, NORMAL_EXEC, true);
+}
+
+static void halbtc8812a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
+{
+ bool wifi_under_5g = false;
+ u8 algorithm = 0;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], RunCoexistMechanism() ===>\n");
+
+ if (btcoexist->manual_control) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n");
+ return;
+ }
+
+ if (coex_sta->under_ips) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], wifi is under IPS !!!\n");
+ return;
+ }
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g);
+ if (wifi_under_5g) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], RunCoexistMechanism(), run 5G coex setting!!<===\n");
+ halbtc8812a2ant_coex_under_5g(btcoexist);
+ return;
+ }
+
+ algorithm = BT_8812A_2ANT_COEX_ALGO_PANEDR;
+ if (coex_sta->c2h_bt_inquiry_page &&
+ (BT_8812A_2ANT_COEX_ALGO_PANHS != algorithm)) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BT is under inquiry/page scan !!\n");
+ halbtc8812a2ant_action_bt_inquiry(btcoexist);
+ return;
+ }
+
+ coex_dm->cur_algorithm = algorithm;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm);
+
+ if (halbtc8812a2ant_is_common_action(btcoexist)) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant common.\n");
+ coex_dm->reset_tdma_adjust = false;
+ coex_dm->auto_tdma_adjust_low_rssi = false;
+ } else {
+ if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], pre_algorithm =%d, cur_algorithm =%d\n",
+ coex_dm->pre_algorithm,
+ coex_dm->cur_algorithm);
+ coex_dm->reset_tdma_adjust = false;
+ coex_dm->auto_tdma_adjust_low_rssi = false;
+ }
+ switch (coex_dm->cur_algorithm) {
+ case BT_8812A_2ANT_COEX_ALGO_SCO:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = SCO.\n");
+ halbtc8812a2ant_action_sco(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_SCO_HID:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = SCO+HID.\n");
+ halbtc8812a2ant_action_sco_hid(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_HID:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = HID.\n");
+ halbtc8812a2ant_action_hid(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_A2DP:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = A2DP.\n");
+ halbtc8812a2ant_action_a2dp(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_A2DP_PANHS:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS).\n");
+ halbtc8812a2ant_action_a2dp_pan_hs(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_PANEDR:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = PAN(EDR).\n");
+ halbtc8812a2ant_action_pan_edr(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_PANHS:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = HS mode.\n");
+ halbtc8812a2ant_action_pan_hs(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_PANEDR_A2DP:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = PAN+A2DP.\n");
+ halbtc8812a2ant_action_pan_edr_a2dp(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_PANEDR_HID:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID.\n");
+ halbtc8812a2ant_action_pan_edr_hid(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN.\n");
+ hal8812a2_action_hid_a2dp_pan_edr(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_HID_A2DP_PANHS:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN(HS).\n");
+ hal8812a2ant_action_hid_a2dp_pan_hs(btcoexist);
+ break;
+ case BT_8812A_2ANT_COEX_ALGO_HID_A2DP:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n");
+ halbtc8812a2ant_action_hid_a2dp(btcoexist);
+ break;
+ default:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n");
+ halbtc8812a2ant_coex_all_off(btcoexist);
+ break;
+ }
+ coex_dm->pre_algorithm = coex_dm->cur_algorithm;
+ }
+}
+
+static void halbtc8812a2ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool back_up)
+{
+ u8 u1_tmp = 0;
+
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], 2Ant Init HW Config!!\n");
+
+ if (back_up) {
+ /* backup rf 0x1e value */
+ coex_dm->bt_rf0x1e_backup =
+ btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, 0x1e,
+ 0xfffff);
+
+ coex_dm->back_up_arfr_cnt1 =
+ btcoexist->btc_read_4byte(btcoexist, 0x430);
+ coex_dm->backup_arfr_cnt2 =
+ btcoexist->btc_read_4byte(btcoexist, 0x434);
+ coex_dm->backup_retry_limit =
+ btcoexist->btc_read_2byte(btcoexist, 0x42a);
+ coex_dm->backup_ampdu_maxtime =
+ btcoexist->btc_read_1byte(btcoexist, 0x456);
+ }
+
+ /* ant sw control to BT */
+ halbtc8812a2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_CPL_AUX,
+ true, false);
+
+ /* 0x790[5:0]= 0x5 */
+ u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0x790);
+ u1_tmp &= 0xc0;
+ u1_tmp |= 0x5;
+ btcoexist->btc_write_1byte(btcoexist, 0x790, u1_tmp);
+
+ /* PTA parameter */
+ btcoexist->btc_write_1byte(btcoexist, 0x6cc, 0x0);
+ btcoexist->btc_write_4byte(btcoexist, 0x6c8, 0xffff);
+ btcoexist->btc_write_4byte(btcoexist, 0x6c4, 0x55555555);
+ btcoexist->btc_write_4byte(btcoexist, 0x6c0, 0x55555555);
+
+ /* coex parameters */
+ btcoexist->btc_write_1byte(btcoexist, 0x778, 0x1);
+
+ /* enable counter statistics */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+ /* enable PTA */
+ btcoexist->btc_write_1byte(btcoexist, 0x40, 0x20);
+
+ /* bt clock related */
+ u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0x4);
+ u1_tmp |= BIT7;
+ btcoexist->btc_write_1byte(btcoexist, 0x4, u1_tmp);
+
+ /* bt clock related */
+ u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0x7);
+ u1_tmp |= BIT1;
+ btcoexist->btc_write_1byte(btcoexist, 0x7, u1_tmp);
+}
+
+/* work around function start with wa_halbtc8812a2ant_ */
+/* extern function start with EXhalbtc8812a2ant_ */
+void ex_halbtc8812a2ant_power_on_setting(struct btc_coexist *btcoexist)
+{
+}
+
+void ex_halbtc8812a2ant_init_hwconfig(struct btc_coexist *btcoexist)
+{
+ halbtc8812a2ant_init_hwconfig(btcoexist, true);
+}
+
+void ex_halbtc8812a2ant_init_coex_dm(struct btc_coexist *btcoexist)
+{
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], Coex Mechanism Init!!\n");
+
+ halbtc8812a2ant_init_coex_dm(btcoexist);
+}
+
+void ex_halbtc8812a2ant_display_coex_info(struct btc_coexist *btcoexist)
+{
+ struct btc_board_info *board_info = &btcoexist->board_info;
+ struct btc_stack_info *stack_info = &btcoexist->stack_info;
+ struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ u8 u1_tmp[4], i, bt_info_ext, ps_tdma_case = 0;
+ u16 u2_tmp[4];
+ u32 u4_tmp[4];
+ bool roam = false, scan = false, link = false, wifi_under_5g = false;
+ bool bt_hs_on = false, wifi_busy = false;
+ s32 wifi_rssi = 0, bt_hs_rssi = 0;
+ u32 wifi_bw, wifi_traffic_dir;
+ u8 wifi_dot11_chnl, wifi_hs_chnl;
+ u32 fw_ver = 0, bt_patch_ver = 0;
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ " ============[BT Coexist info]============\n");
+
+ if (btcoexist->manual_control) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "============[Under Manual Control]============\n");
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "==========================================\n");
+ }
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d\n",
+ "Ant PG number/ Ant mechanism:",
+ board_info->pg_ant_num, board_info->btdm_ant_num);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %s / %d\n",
+ "BT stack/ hci ext ver",
+ ((stack_info->profile_notified) ? "Yes" : "No"),
+ stack_info->hci_version);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%-35s = %d_%d/ 0x%x/ 0x%x(%d)\n", "CoexVer/ FwVer/ PatchVer",
+ glcoex_ver_date_8812a_2ant, glcoex_ver_8812a_2ant, fw_ver,
+ bt_patch_ver, bt_patch_ver);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL,
+ &wifi_dot11_chnl);
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d / %d(%d)\n",
+ "Dot11 channel / HsMode(HsChnl)",
+ wifi_dot11_chnl, bt_hs_on, wifi_hs_chnl);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %02x %02x %02x\n",
+ "H2C Wifi inform bt chnl Info",
+ coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1],
+ coex_dm->wifi_chnl_info[2]);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
+ btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d\n",
+ "Wifi rssi/ HS rssi", wifi_rssi, bt_hs_rssi);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d/ %d\n",
+ "Wifi link/ roam/ scan", link, roam, scan);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION,
+ &wifi_traffic_dir);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %s / %s/ %s\n",
+ "Wifi status",
+ (wifi_under_5g ? "5G" : "2.4G"),
+ ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" :
+ (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))),
+ ((!wifi_busy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX ==
+ wifi_traffic_dir) ? "uplink" : "downlink")));
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = [%s/ %d/ %d]\n",
+ "BT [status/ rssi/ retryCnt]",
+ ((btcoexist->bt_info.bt_disabled) ? ("disabled") :
+ ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") :
+ ((BT_8812A_2ANT_BT_STATUS_NON_CONNECTED_IDLE ==
+ coex_dm->bt_status) ? "non-connected idle" :
+ ((BT_8812A_2ANT_BT_STATUS_CONNECTED_IDLE ==
+ coex_dm->bt_status) ? "connected-idle" : "busy")))),
+ coex_sta->bt_rssi, coex_sta->bt_retry_cnt);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d / %d / %d / %d\n",
+ "SCO/HID/PAN/A2DP", bt_link_info->sco_exist,
+ bt_link_info->hid_exist, bt_link_info->pan_exist,
+ bt_link_info->a2dp_exist);
+
+ bt_info_ext = coex_sta->bt_info_ext;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %s\n",
+ "BT Info A2DP rate",
+ (bt_info_ext & BIT0) ? "Basic rate" : "EDR rate");
+
+ for (i = 0; i < BT_INFO_SRC_8812A_2ANT_MAX; i++) {
+ if (coex_sta->bt_info_c2h_cnt[i]) {
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%-35s = %02x %02x %02x %02x %02x %02x %02x(%d)\n",
+ glbt_info_src_8812a_2ant[i],
+ coex_sta->bt_info_c2h[i][0],
+ coex_sta->bt_info_c2h[i][1],
+ coex_sta->bt_info_c2h[i][2],
+ coex_sta->bt_info_c2h[i][3],
+ coex_sta->bt_info_c2h[i][4],
+ coex_sta->bt_info_c2h[i][5],
+ coex_sta->bt_info_c2h[i][6],
+ coex_sta->bt_info_c2h_cnt[i]);
+ }
+ }
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %s/%s, (0x%x/0x%x)\n",
+ "PS state, IPS/LPS, (lps/rpwm)",
+ ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")),
+ ((coex_sta->under_lps ? "LPS ON" : "LPS OFF")),
+ btcoexist->bt_info.lps_val,
+ btcoexist->bt_info.rpwm_val);
+
+ /* Sw mechanism */
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "============[Sw mechanism]============\n");
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d/ %d\n",
+ "SM1[ShRf/ LpRA/ LimDig]",
+ coex_dm->cur_rf_rx_lpf_shrink, coex_dm->cur_low_penalty_ra,
+ coex_dm->limited_dig);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d/ %d(0x%x)\n",
+ "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]",
+ coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off,
+ coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x\n", "Rate Mask",
+ btcoexist->bt_info.ra_mask);
+
+ /* Fw mechanism */
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "============[Fw mechanism]============\n");
+
+ ps_tdma_case = coex_dm->cur_ps_tdma;
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%-35s = %02x %02x %02x %02x %02x case-%d (auto:%d/%d)\n",
+ "PS TDMA",
+ coex_dm->ps_tdma_para[0],
+ coex_dm->ps_tdma_para[1],
+ coex_dm->ps_tdma_para[2],
+ coex_dm->ps_tdma_para[3],
+ coex_dm->ps_tdma_para[4], ps_tdma_case,
+ coex_dm->reset_tdma_adjust,
+ coex_dm->auto_tdma_adjust_low_rssi);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d\n",
+ "DecBtPwr/ IgnWlanAct",
+ coex_dm->cur_dec_bt_pwr, coex_dm->cur_ignore_wlan_act);
+
+ /* Hw setting */
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "============[Hw setting]============\n");
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x\n",
+ "RF-A, 0x1e initVal",
+ coex_dm->bt_rf0x1e_backup);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/0x%x/0x%x/0x%x\n",
+ "backup ARFR1/ARFR2/RL/AMaxTime",
+ coex_dm->back_up_arfr_cnt1, coex_dm->backup_arfr_cnt2,
+ coex_dm->backup_retry_limit, coex_dm->backup_ampdu_maxtime);
+
+ u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430);
+ u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434);
+ u2_tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a);
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/0x%x/0x%x/0x%x\n",
+ "0x430/0x434/0x42a/0x456",
+ u4_tmp[0], u4_tmp[1], u2_tmp[0], u1_tmp[0]);
+
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778);
+ u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x6cc);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x\n",
+ "0x778 (W_Act)/ 0x6cc (CoTab Sel)",
+ u1_tmp[0], u1_tmp[1]);
+
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x8db);
+ u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xc5b);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x\n",
+ "0x8db(ADC)/0xc5b[29:25](DAC)",
+ ((u1_tmp[0]&0x60)>>5), ((u1_tmp[1]&0x3e)>>1));
+
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xcb3);
+ u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xcb7);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x\n",
+ "0xcb3/ 0xcb7", u1_tmp[0], u1_tmp[1]);
+
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40);
+ u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c);
+ u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x974);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x/ 0x%x\n",
+ "0x40/ 0x4c[24:23]/ 0x974",
+ u1_tmp[0], ((u4_tmp[0]&0x01800000)>>23), u4_tmp[1]);
+
+ u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550);
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x\n",
+ "0x550(bcn ctrl)/0x522",
+ u4_tmp[0], u1_tmp[0]);
+
+ u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50);
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa0a);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x\n",
+ "0xc50(DIG)/0xa0a(CCK-TH)",
+ u4_tmp[0], u1_tmp[0]);
+
+ u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xf48);
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b);
+ u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x/ 0x%x\n",
+ "0xf48/ 0xa5b (FA cnt-- OFDM : CCK)",
+ u4_tmp[0], (u1_tmp[0]<<8) + u1_tmp[1]);
+
+ u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0);
+ u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4);
+ u4_tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8);
+ u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x\n",
+ "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)",
+ u4_tmp[0], u4_tmp[1], u4_tmp[2], u1_tmp[0]);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%-35s = %d/ %d\n", "0x770(high-pri rx/tx)",
+ coex_sta->high_priority_rx, coex_sta->high_priority_tx);
+
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%-35s = %d/ %d\n", "0x774(low-pri rx/tx)",
+ coex_sta->low_priority_rx, coex_sta->low_priority_tx);
+
+#if (BT_AUTO_REPORT_ONLY_8812A_2ANT == 1)
+ halbtc8812a2ant_monitor_bt_ctr(btcoexist);
+#endif
+}
+
+void ex_halbtc8812a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ bool wifi_under_5g = false;
+
+ if (BTC_IPS_ENTER == type) {
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], IPS ENTER notify\n");
+ coex_sta->under_ips = true;
+ halbtc8812a2ant_coex_all_off(btcoexist);
+ halbtc8812a2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_CPL_AUX,
+ false, true);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], IPS notify, force set BT to ignore Wlan active!!\n");
+ hal8812a2_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
+ ex_btc8812a2ant_media_stat_notify(btcoexist,
+ BTC_MEDIA_DISCONNECT);
+ } else if (BTC_IPS_LEAVE == type) {
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], IPS LEAVE notify\n");
+ coex_sta->under_ips = false;
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G,
+ &wifi_under_5g);
+ if (!wifi_under_5g) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], IPS notify, force set BT NOT to ignore Wlan active!!\n");
+ hal8812a2_ignore_wlan_act(btcoexist, FORCE_EXEC, false);
+ }
+ }
+}
+
+void ex_halbtc8812a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ if (BTC_LPS_ENABLE == type) {
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], LPS ENABLE notify\n");
+ coex_sta->under_lps = true;
+ } else if (BTC_LPS_DISABLE == type) {
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], LPS DISABLE notify\n");
+ coex_sta->under_lps = false;
+ }
+}
+
+void ex_halbtc8812a2ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ if (BTC_SCAN_START == type)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], SCAN START notify\n");
+ else if (BTC_SCAN_FINISH == type)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], SCAN FINISH notify\n");
+}
+
+void ex_halbtc8812a2ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ if (BTC_ASSOCIATE_START == type)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], CONNECT START notify\n");
+ else if (BTC_ASSOCIATE_FINISH == type)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], CONNECT FINISH notify\n");
+}
+
+void ex_btc8812a2ant_media_stat_notify(struct btc_coexist *btcoexist,
+ u8 type)
+{
+ u8 data_len = 5;
+ u8 buf[6] = {0};
+ u8 h2c_parameter[3] = {0};
+ u32 wifi_bw;
+ u8 wifi_central_chnl;
+
+ if (btcoexist->manual_control ||
+ btcoexist->stop_coex_dm ||
+ btcoexist->bt_info.bt_disabled)
+ return;
+
+ if (BTC_MEDIA_CONNECT == type)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], MEDIA connect notify\n");
+ else
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], MEDIA disconnect notify\n");
+
+ /* only 2.4G we need to inform bt the chnl mask */
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL,
+ &wifi_central_chnl);
+ if ((BTC_MEDIA_CONNECT == type) &&
+ (wifi_central_chnl <= 14)) {
+ h2c_parameter[0] = 0x1;
+ h2c_parameter[1] = wifi_central_chnl;
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ if (BTC_WIFI_BW_HT40 == wifi_bw)
+ h2c_parameter[2] = 0x30;
+ else
+ h2c_parameter[2] = 0x20;
+ }
+
+ coex_dm->wifi_chnl_info[0] = h2c_parameter[0];
+ coex_dm->wifi_chnl_info[1] = h2c_parameter[1];
+ coex_dm->wifi_chnl_info[2] = h2c_parameter[2];
+
+ buf[0] = data_len;
+ buf[1] = 0x5; /* OP_Code */
+ buf[2] = 0x3; /* OP_Code_Length */
+ buf[3] = h2c_parameter[0]; /* OP_Code_Content */
+ buf[4] = h2c_parameter[1];
+ buf[5] = h2c_parameter[2];
+
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_COEX,
+ (void *)&buf[0]);
+}
+
+void ex_halbtc8812a2ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type)
+{
+ if (type == BTC_PACKET_DHCP)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], DHCP Packet notify\n");
+}
+
+void ex_halbtc8812a2ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmp_buf, u8 length)
+{
+ u8 bt_info = 0;
+ u8 i, rsp_source = 0;
+ bool bt_busy = false, limited_dig = false;
+ bool wifi_connected = false, wifi_under_5g = false;
+
+ coex_sta->c2h_bt_info_req_sent = false;
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g);
+
+ rsp_source = tmp_buf[0]&0xf;
+ if (rsp_source >= BT_INFO_SRC_8812A_2ANT_MAX)
+ rsp_source = BT_INFO_SRC_8812A_2ANT_WIFI_FW;
+ coex_sta->bt_info_c2h_cnt[rsp_source]++;
+
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+ "[BTCoex], Bt info[%d], length =%d, hex data =[",
+ rsp_source, length);
+ for (i = 0; i < length; i++) {
+ coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i];
+ if (i == 1)
+ bt_info = tmp_buf[i];
+ if (i == length-1)
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "0x%02x]\n",
+ tmp_buf[i]);
+ else
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "0x%02x, ",
+ tmp_buf[i]);
+ }
+
+ if (BT_INFO_SRC_8812A_2ANT_WIFI_FW != rsp_source) {
+ coex_sta->bt_retry_cnt = /* [3:0] */
+ coex_sta->bt_info_c2h[rsp_source][2]&0xf;
+
+ coex_sta->bt_rssi =
+ coex_sta->bt_info_c2h[rsp_source][3]*2+10;
+
+ coex_sta->bt_info_ext =
+ coex_sta->bt_info_c2h[rsp_source][4];
+
+ /* Here we need to resend some wifi info to BT */
+ /* because bt is reset and loss of the info. */
+ if ((coex_sta->bt_info_ext & BIT1)) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n");
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+ &wifi_connected);
+ if (wifi_connected)
+ ex_btc8812a2ant_media_stat_notify(btcoexist,
+ BTC_MEDIA_CONNECT);
+ else
+ ex_btc8812a2ant_media_stat_notify(btcoexist,
+ BTC_MEDIA_DISCONNECT);
+ }
+
+ if ((coex_sta->bt_info_ext&BIT3) && !wifi_under_5g) {
+ if (!btcoexist->manual_control &&
+ !btcoexist->stop_coex_dm) {
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
+ hal8812a2_ignore_wlan_act(btcoexist, FORCE_EXEC,
+ false);
+ }
+ } else {
+ if (coex_sta->under_ips) {
+ /* work around for 8812a combo hw bug => when
+ * IPS, wlanAct is always high.
+ */
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], wifi is under IPS, set BT to ignore Wlan active!!\n");
+ hal8812a2_ignore_wlan_act(btcoexist, FORCE_EXEC,
+ true);
+ }
+ }
+ }
+
+ /* check BIT2 first ==> check if bt is under inquiry or page scan */
+ if (bt_info & BT_INFO_8812A_2ANT_B_INQ_PAGE)
+ coex_sta->c2h_bt_inquiry_page = true;
+ else
+ coex_sta->c2h_bt_inquiry_page = false;
+
+ /* set link exist status */
+ if (!(bt_info&BT_INFO_8812A_2ANT_B_CONNECTION)) {
+ coex_sta->bt_link_exist = false;
+ coex_sta->pan_exist = false;
+ coex_sta->a2dp_exist = false;
+ coex_sta->hid_exist = false;
+ coex_sta->sco_exist = false;
+ } else { /* connection exists */
+ coex_sta->bt_link_exist = true;
+ if (bt_info & BT_INFO_8812A_2ANT_B_FTP)
+ coex_sta->pan_exist = true;
+ else
+ coex_sta->pan_exist = false;
+ if (bt_info & BT_INFO_8812A_2ANT_B_A2DP)
+ coex_sta->a2dp_exist = true;
+ else
+ coex_sta->a2dp_exist = false;
+ if (bt_info & BT_INFO_8812A_2ANT_B_HID)
+ coex_sta->hid_exist = true;
+ else
+ coex_sta->hid_exist = false;
+ if (bt_info & BT_INFO_8812A_2ANT_B_SCO_ESCO)
+ coex_sta->sco_exist = true;
+ else
+ coex_sta->sco_exist = false;
+ }
+
+ halbtc8812a2ant_update_bt_link_info(btcoexist);
+
+ if (!(bt_info&BT_INFO_8812A_2ANT_B_CONNECTION)) {
+ coex_dm->bt_status = BT_8812A_2ANT_BT_STATUS_NON_CONNECTED_IDLE;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n");
+ } else if (bt_info == BT_INFO_8812A_2ANT_B_CONNECTION) {
+ /* connection exists but no busy */
+ coex_dm->bt_status = BT_8812A_2ANT_BT_STATUS_CONNECTED_IDLE;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n");
+ } else if ((bt_info&BT_INFO_8812A_2ANT_B_SCO_ESCO) ||
+ (bt_info&BT_INFO_8812A_2ANT_B_SCO_BUSY)) {
+ coex_dm->bt_status = BT_8812A_2ANT_BT_STATUS_SCO_BUSY;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n");
+ } else if (bt_info&BT_INFO_8812A_2ANT_B_ACL_BUSY) {
+ coex_dm->bt_status = BT_8812A_2ANT_BT_STATUS_ACL_BUSY;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n");
+ } else {
+ coex_dm->bt_status = BT_8812A_2ANT_BT_STATUS_MAX;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n");
+ }
+
+ if ((BT_8812A_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) ||
+ (BT_8812A_2ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
+ (BT_8812A_2ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) {
+ bt_busy = true;
+ if (!wifi_under_5g)
+ limited_dig = true;
+ } else {
+ bt_busy = false;
+ limited_dig = false;
+ }
+
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy);
+
+ coex_dm->limited_dig = limited_dig;
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig);
+
+ halbtc8812a2ant_run_coexist_mechanism(btcoexist);
+}
+
+void ex_halbtc8812a2ant_halt_notify(struct btc_coexist *btcoexist)
+{
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Halt notify\n"));
+
+ halbtc8812a2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_CPL_AUX,
+ false, true);
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Halt notify, force set BT to ignore Wlan active!!\n");
+ hal8812a2_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
+ ex_btc8812a2ant_media_stat_notify(btcoexist, BTC_MEDIA_DISCONNECT);
+
+ /* 0x522 = 0xff, pause tx */
+ btcoexist->btc_write_1byte(btcoexist, 0x522, 0xff);
+ /* 0x40[7:6]=2'b01, modify BT mode. */
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0xc0, 0x2);
+}
+
+void ex_halbtc8812a2ant_periodical(struct btc_coexist *btcoexist)
+{
+ static u8 dis_ver_info_cnt;
+ struct btc_board_info *board_info = &btcoexist->board_info;
+ struct btc_stack_info *stack_info = &btcoexist->stack_info;
+ u32 fw_ver = 0, bt_patch_ver = 0;
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], ==========================Periodical ===========================\n");
+
+ if (dis_ver_info_cnt <= 5) {
+ dis_ver_info_cnt += 1;
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], ****************************************************************\n");
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n",
+ board_info->pg_ant_num, board_info->btdm_ant_num,
+ board_info->btdm_ant_pos);
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], BT stack/ hci ext ver = %s / %d\n",
+ ((stack_info->profile_notified) ? "Yes" : "No"),
+ stack_info->hci_version);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER,
+ &bt_patch_ver);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n",
+ glcoex_ver_date_8812a_2ant, glcoex_ver_8812a_2ant,
+ fw_ver, bt_patch_ver, bt_patch_ver);
+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+ "[BTCoex], ****************************************************************\n");
+ }
+
+#if (BT_AUTO_REPORT_ONLY_8812A_2ANT == 0)
+ halbtc8812a2ant_query_bt_info(btcoexist);
+ halbtc8812a2ant_monitor_bt_ctr(btcoexist);
+ hal8812a2_monitor_bt_enable_disable(btcoexist);
+#else
+ if (halbtc8812a2ant_is_wifi_status_changed(btcoexist) ||
+ coex_dm->reset_tdma_adjust ||
+ coex_dm->auto_tdma_adjust_low_rssi)
+ halbtc8812a2ant_run_coexist_mechanism(btcoexist);
+#endif
+}
+
+void ex_halbtc8812a2ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code,
+ u8 op_len, u8 *data)
+{
+ u8 data_len;
+ u8 buf[6] = {0};
+ u8 decbtpwr = 0, pwrlevel;
+
+ switch (op_code) {
+ case BTC_DBG_SET_COEX_DEC_BT_PWR:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Set Dec BT power\n");
+ data_len = 4;
+ decbtpwr = 0;
+ if (op_len == 2) {
+ decbtpwr = data[0];
+ pwrlevel = data[1];
+
+ buf[0] = data_len;
+ buf[1] = 0x3; /* OP_Code */
+ buf[2] = 0x2; /* OP_Code_Length */
+
+ buf[3] = decbtpwr; /* OP_Code_Content */
+ buf[4] = pwrlevel;
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Set Dec BT power =%d, pwrlevel =%d\n",
+ decbtpwr, pwrlevel);
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_COEX,
+ (void *)&buf[0]);
+ }
+ break;
+ case BTC_DBG_SET_COEX_BT_AFH_MAP:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Set BT AFH Map\n");
+ data_len = 5;
+ if (op_len == 3) {
+ buf[0] = data_len;
+ buf[1] = 0x5; /* OP_Code */
+ buf[2] = 0x3; /* OP_Code_Length */
+
+ buf[3] = data[0]; /* OP_Code_Content */
+ buf[4] = data[1];
+ buf[5] = data[2];
+
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Set BT AFH Map = %02x %02x %02x\n",
+ data[0], data[1], data[2]);
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_COEX,
+ (void *)&buf[0]);
+ }
+ break;
+ case BTC_DBG_SET_COEX_BT_IGNORE_WLAN_ACT:
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Set BT Ignore Wlan Active\n");
+ data_len = 3;
+ if (op_len == 1) {
+ buf[0] = data_len;
+ buf[1] = 0x1; /* OP_Code */
+ buf[2] = 0x1; /* OP_Code_Length */
+
+ buf[3] = data[0]; /* OP_Code_Content */
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "[BTCoex], Set BT Ignore Wlan Active = 0x%x\n",
+ data[0]);
+
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_COEX,
+ (void *)&buf[0]);
+ }
+ break;
+ default:
+ break;
+ }
+}
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
new file mode 100644
index 0000000..0c02134
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
@@ -0,0 +1,177 @@
+#ifndef __HAL8812A2ANT__
+#define __HAL8812A2ANT__
+
+/* The following is for 8812A 2Ant BT Co-exist definition */
+
+/* enum btc_dbg_opcode ,add new*/
+#define BTC_DBG_SET_COEX_DEC_BT_PWR 0x3
+#define BTC_DBG_SET_COEX_BT_AFH_MAP 0x4
+#define BTC_DBG_SET_COEX_BT_IGNORE_WLAN_ACT 0x5
+
+#define BT_AUTO_REPORT_ONLY_8812A_2ANT 0
+
+#define BT_INFO_8812A_2ANT_B_FTP BIT7
+#define BT_INFO_8812A_2ANT_B_A2DP BIT6
+#define BT_INFO_8812A_2ANT_B_HID BIT5
+#define BT_INFO_8812A_2ANT_B_SCO_BUSY BIT4
+#define BT_INFO_8812A_2ANT_B_ACL_BUSY BIT3
+#define BT_INFO_8812A_2ANT_B_INQ_PAGE BIT2
+#define BT_INFO_8812A_2ANT_B_SCO_ESCO BIT1
+#define BT_INFO_8812A_2ANT_B_CONNECTION BIT0
+
+#define BT_INFO_8812A_2ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \
+ (((_BT_INFO_EXT_&BIT0)) ? true : false)
+
+#define BTC_RSSI_COEX_THRESH_TOL_8812A_2ANT 2
+
+enum BT_INFO_SRC_8812A_2ANT {
+ BT_INFO_SRC_8812A_2ANT_WIFI_FW = 0x0,
+ BT_INFO_SRC_8812A_2ANT_BT_RSP = 0x1,
+ BT_INFO_SRC_8812A_2ANT_BT_ACTIVE_SEND = 0x2,
+ BT_INFO_SRC_8812A_2ANT_MAX
+};
+
+enum BT_8812A_2ANT_BT_STATUS {
+ BT_8812A_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0,
+ BT_8812A_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1,
+ BT_8812A_2ANT_BT_STATUS_INQ_PAGE = 0x2,
+ BT_8812A_2ANT_BT_STATUS_ACL_BUSY = 0x3,
+ BT_8812A_2ANT_BT_STATUS_SCO_BUSY = 0x4,
+ BT_8812A_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5,
+ BT_8812A_2ANT_BT_STATUS_MAX
+};
+
+enum BT_8812A_2ANT_COEX_ALGO {
+ BT_8812A_2ANT_COEX_ALGO_UNDEFINED = 0x0,
+ BT_8812A_2ANT_COEX_ALGO_SCO = 0x1,
+ BT_8812A_2ANT_COEX_ALGO_SCO_HID = 0x2,
+ BT_8812A_2ANT_COEX_ALGO_HID = 0x3,
+ BT_8812A_2ANT_COEX_ALGO_A2DP = 0x4,
+ BT_8812A_2ANT_COEX_ALGO_A2DP_PANHS = 0x5,
+ BT_8812A_2ANT_COEX_ALGO_PANEDR = 0x6,
+ BT_8812A_2ANT_COEX_ALGO_PANHS = 0x7,
+ BT_8812A_2ANT_COEX_ALGO_PANEDR_A2DP = 0x8,
+ BT_8812A_2ANT_COEX_ALGO_PANEDR_HID = 0x9,
+ BT_8812A_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0xa,
+ BT_8812A_2ANT_COEX_ALGO_HID_A2DP_PANHS = 0xb,
+ BT_8812A_2ANT_COEX_ALGO_HID_A2DP = 0xc,
+ BT_8812A_2ANT_COEX_ALGO_MAX = 0xd
+};
+
+struct coex_dm_8812a_2ant {
+ /* fw mechanism */
+ u8 pre_bt_dec_pwr_lvl;
+ u8 cur_dec_bt_pwr;
+ u8 pre_fw_dac_swing_lvl;
+ u8 cur_fw_dac_swing_lvl;
+ bool cur_ignore_wlan_act;
+ bool pre_ignore_wlan_act;
+ u8 pre_ps_tdma;
+ u8 cur_ps_tdma;
+ u8 ps_tdma_para[5];
+ u8 ps_tdma_du_adj_type;
+ bool reset_tdma_adjust;
+ bool auto_tdma_adjust_low_rssi;
+ bool pre_ps_tdma_on;
+ bool cur_ps_tdma_on;
+ bool pre_bt_auto_report;
+ bool cur_bt_auto_report;
+ u8 pre_lps;
+ u8 cur_lps;
+ u8 pre_rpwm;
+ u8 cur_rpwm;
+
+ /* sw mechanism */
+ bool pre_rf_rx_lpf_shrink;
+ bool cur_rf_rx_lpf_shrink;
+ u32 bt_rf0x1e_backup;
+ bool pre_low_penalty_ra;
+ bool cur_low_penalty_ra;
+ bool pre_dac_swing_on;
+ u32 pre_dac_swing_lvl;
+ bool cur_dac_swing_on;
+ u32 cur_dac_swing_lvl;
+ bool pre_adc_back_off;
+ bool cur_adc_back_off;
+ bool pre_agc_table_en;
+ bool cur_agc_table_en;
+ u32 pre_val_0x6c0;
+ u32 cur_val_0x6c0;
+ u32 pre_val_0x6c4;
+ u32 cur_val_0x6c4;
+ u32 pre_val_0x6c8;
+ u32 cur_val_0x6c8;
+ u8 pre_val_0x6cc;
+ u8 cur_val_0x6cc;
+
+ bool limited_dig;
+ u32 back_up_arfr_cnt1;/* Auto Rate Fallback Retry cnt */
+ u32 backup_arfr_cnt2; /* Auto Rate Fallback Retry cnt */
+ u16 backup_retry_limit;
+ u8 backup_ampdu_maxtime;
+
+ /* algorithm related */
+ u8 pre_algorithm;
+ u8 cur_algorithm;
+ u8 bt_status;
+ u8 wifi_chnl_info[3];
+
+ u32 pre_ra_mask;
+ u32 cur_ra_mask;
+
+ u8 curramasktype;
+ u8 pre_arfr_type;
+ u8 cur_arfr_type;
+ u8 pre_retry_limit_type;
+ u8 cur_retry_limit_type;
+ u8 pre_ampdu_time_type;
+ u8 cur_ampdu_time_type;
+};
+
+struct coex_sta_8812a_2ant {
+ bool bt_link_exist;
+ bool sco_exist;
+ bool a2dp_exist;
+ bool hid_exist;
+ bool pan_exist;
+
+ bool under_lps;
+ bool under_ips;
+ u32 high_priority_tx;
+ u32 high_priority_rx;
+ u32 low_priority_tx;
+ u32 low_priority_rx;
+ u8 bt_rssi;
+ u8 pre_bt_rssi_state;
+ u8 pre_wifi_rssi_state[4];
+ bool c2h_bt_info_req_sent;
+
+ u8 bt_info_c2h[BT_INFO_SRC_8812A_2ANT_MAX][10];
+ u32 bt_info_c2h_cnt[BT_INFO_SRC_8812A_2ANT_MAX];
+ u32 bt_info_query_cnt;
+ bool c2h_bt_inquiry_page;
+ u8 bt_retry_cnt;
+ u8 bt_info_ext;
+};
+
+/* The following is interface which will notify coex module. */
+void ex_halbtc8812a2ant_power_on_setting(struct btc_coexist *btcoexist);
+void ex_halbtc8812a2ant_init_hwconfig(struct btc_coexist *btcoexist);
+void ex_halbtc8812a2ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_halbtc8812a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a2ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_halbtc8812a2ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_halbtc8812a2ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmp_buf, u8 length);
+void ex_halbtc8812a2ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_halbtc8812a2ant_periodical(struct btc_coexist *btcoexist);
+void ex_halbtc8812a2ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_halbtc8812a2ant_dbg_control(struct btc_coexist *btcoexist,
+ u8 op_code, u8 op_len, u8 *data);
+
+#endif
--
2.1.2
^ permalink raw reply related
* [PATCH V2 5/6] rtlwifi: btcoexist: Add routines for RTL8812AE kernel socket communications
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Troy Tan, netdev, Larry Finger
In-Reply-To: <1422304934-9239-1-git-send-email-Larry.Finger@lwfinger.net>
From: Troy Tan <troy_tan@realsil.com.cn>
This patch adds the routines used to communicate between the RTL8812AE (wifi)
device and the RTL8761AU (bluetooth) device that are part of the same chip.
Unlike other similar dual-function devices, this chip does not contain special
hardware that lets the firmware pass coexistence info from one part to the
other. As a result, this driver implements such communication as a kernel
socket.
Signed-off-by: Troy Tan <troy_tan@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
V2 - Add comments explaining the routine that sends a message via the socket.
---
.../wireless/rtlwifi/btcoexist/halbtc8812a_ext.c | 921 +++++++++++++++++++++
.../wireless/rtlwifi/btcoexist/halbtc8812a_ext.h | 359 ++++++++
2 files changed, 1280 insertions(+)
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.c
create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.h
Index: wireless-drivers/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.c
===================================================================
--- /dev/null
+++ wireless-drivers/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.c
@@ -0,0 +1,929 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "halbt_precomp.h"
+#include "halbtc8812a_ext.h"
+
+/*global for socket TRX, it is actually rtlpriv*/
+static struct rtl_priv *pbtcoexadapter;
+
+static void *safe_memcpy(void *dest, const void *src, u32 n, u32 max_len)
+{
+ if (n > max_len) {
+ memcpy(dest, src, max_len);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "critical error in memcpy!\n");
+ } else {
+ /*ok case*/
+ memcpy(dest, src, n);
+ }
+ return NULL;
+}
+
+static void btinfo_evt_dump(struct btinfo_8761au *info)
+{
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "cid:0x%02x, len:%u\n", info->cid, info->len);
+
+ if (info->len > 2)
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "byte2:%s%s%s%s%s%s%s%s\n",
+ info->connection ? "connection " : "",
+ info->scoe_sco ? "scoe_sco " : "",
+ info->inq_page ? "inq_page " : "",
+ info->acl_busy ? "acl_busy " : "",
+ info->sco_busy ? "sco_busy " : "",
+ info->hid ? "hid " : "",
+ info->a2dp ? "a2dp " : "",
+ info->ftp ? "ftp" : "");
+
+ if (info->len > 3)
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "retry_cnt:%u\n", info->retry_cnt);
+
+ if (info->len > 4)
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "rssi:%u\n",
+ info->rssi);
+
+ if (info->len > 5)
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "byte5:%s%s\n",
+ info->esco_sco ? "eSCO_SCO " : "",
+ info->master_slave ? "Master_Slave " : "");
+}
+
+static void rtl_btcoex_btinfo_cmd(struct rtl_priv *rtlpriv, u8 *buf,
+ u16 buf_len)
+{
+ struct btinfo_8761au *info = (struct btinfo_8761au *)buf;
+ u8 cmd_idx;
+ u8 len;
+
+ cmd_idx = info->cid;
+
+ if (info->len > buf_len-2) {
+ WARN_ON(1);
+ len = buf_len-2;
+ } else {
+ len = info->len;
+ }
+
+ btinfo_evt_dump(info);
+
+ /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
+ if (cmd_idx == BTINFO_WIFI_FETCH) {
+ buf[1] = 0;
+ } else if (cmd_idx == BTINFO_BT_AUTO_RPT) {
+ buf[1] = 2;
+ } else if (0x01 == cmd_idx || 0x02 == cmd_idx) {
+ /* troy, it should run here */
+ buf[1] = buf[0];
+ }
+
+ rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, &buf[1], len+1);
+}
+
+static u8 rtl_send_comp_ev_to_bt(struct rtl_priv *rtlpriv,
+ enum HCI_EXTENSION_COMMANDS BT_RELATED_CMD,
+ enum HCI_STATUS status)
+{
+ struct rtl_hci_event *hci_event;
+ u8 local_buf[6] = "";
+ u8 len = 0, tx_event_length = 0;
+ u8 *ret_par;
+ u8 *event_data = NULL;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL_END, rtl_send_comp_ev_to_bt\n");
+
+ hci_event = (struct rtl_hci_event *)(&local_buf[0]);
+ event_data = hci_event->data;
+ hci_event->event_code = HCI_EVENT_COMMAND_COMPLETE;
+ *event_data = 0x1;
+ *(event_data + 1) = HCIOPCODELOW(BT_RELATED_CMD, OGF_EXTENSION);
+ *(event_data + 2) = HCIOPCODEHIGHT(BT_RELATED_CMD, OGF_EXTENSION);
+
+ len = len + 3;
+ ret_par = &hci_event->data[len];
+ ret_par[0] = status;
+ len++;
+ hci_event->length = len;
+ /* total tx event length + event_code length + sizeof(length) */
+ tx_event_length = hci_event->length + 2;
+ rtl_btcoex_dump_tx_msg((u8 *)hci_event, tx_event_length,
+ "rtl_send_comp_ev_to_bt");
+ status = rtl_btcoex_sendmsgbysocket(rtlpriv, (u8 *)hci_event,
+ tx_event_length, false);
+ return status;
+}
+
+static u8 rtl_btcoex_parse_BT_info_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ u8 curpollenable = pcmd[0];
+ u8 curpolltime = pcmd[1];
+ u8 btinforeason = pcmd[2];
+ u8 btinfolen = pcmd[3];
+ u8 btinfo[BT_INFO_LENGTH];
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "%s\n", __func__);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "current Poll Enable: %d, currrent Poll Time: %d\n",
+ curpollenable, curpolltime);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "BT Info reason: %d, BT Info length: %d\n",
+ btinforeason, btinfolen);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pcmd[4], pcmd[5], pcmd[6], pcmd[7], pcmd[8],
+ pcmd[9], pcmd[10], pcmd[11]);
+
+ memset(btinfo, 0, BT_INFO_LENGTH);
+
+ if (BT_INFO_LENGTH != btinfolen) {
+ status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "Error BT Info Length: %d\n", btinfolen);
+ } else {
+ if (0x1 == btinforeason || 0x2 == btinforeason) {
+ safe_memcpy(btinfo, &pcmd[4], btinfolen,
+ BT_INFO_LENGTH);
+ btinfo[0] = btinforeason;
+ rtl_btcoex_btinfo_cmd(rtlpriv, btinfo, btinfolen);
+ } else {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "Other BT info reason\n");
+ }
+ }
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_INFO_NOTIFY, status);
+}
+
+static u8 rtl_btcoex_parse_BT_patch_ver_info_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+ u16 btpatchver = 0x0, bthciver = 0x0;
+
+ bthciver = pcmd[0] | pcmd[1]<<8;
+ btpatchver = pcmd[2] | pcmd[3]<<8;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "%s, cmd:%02x %02x %02x %02x\n",
+ __func__, pcmd[0], pcmd[1], pcmd[2], pcmd[3]);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "%s, HCI Ver:%d, Patch Ver:%d\n",
+ __func__, bthciver, btpatchver);
+ rtlpriv->btcoexist.btc_ops->btc_set_bt_patch_version(bthciver,
+ btpatchver);
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_PATCH_VERSION_NOTIFY,
+ status);
+}
+
+static u8 rtl_btcoex_parse_HCI_Ver_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+ u16 hciver = pcmd[0] | pcmd[1] << 8;
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ struct bt_mgnt *bt_mgnt = &pcoex_info->btmgnt;
+
+ bt_mgnt->ext_config.hci_ext_ver = hciver;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "%s, HCI Version: %d\n",
+ __func__, bt_mgnt->ext_config.hci_ext_ver);
+ if (bt_mgnt->ext_config.hci_ext_ver < 4) {
+ status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "%s, Version = %d, HCI Version must be < 4\n",
+ __func__, bt_mgnt->ext_config.hci_ext_ver);
+
+ } else {
+ rtlpriv->btcoexist.btc_ops->btc_set_hci_version(hciver);
+ }
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_EXTENSION_VERSION_NOTIFY,
+ status);
+}
+
+static u8 rtl_btcoex_parse_WIFI_scan_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ struct bt_mgnt *bt_mgnt = &pcoex_info->btmgnt;
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ bt_mgnt->ext_config.enable_wifi_scan_notify = pcmd[0];
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "%s, enable_wifi_scan_notify: %d\n", __func__,
+ bt_mgnt->ext_config.enable_wifi_scan_notify);
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_ENABLE_WIFI_SCAN_NOTIFY,
+ status);
+}
+
+static u8 rtl_btcoex_parse_HCI_link_status_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ struct bt_mgnt *bt_mgnt = &pcoex_info->btmgnt;
+ u8 i, num_of_handle = 0;
+ u16 connect_handle;
+ u8 bt_profile, bt_corespec, link_role;
+ u8 *ptriple;
+
+ bt_mgnt->support_profile = false;
+
+ bt_mgnt->ext_config.number_of_acl = 0;
+ bt_mgnt->ext_config.number_of_sco = 0;
+
+ num_of_handle = pcmd[0];
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "num_of_handle = 0x%x\n",
+ num_of_handle);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "hci_extension_ver = %d\n",
+ bt_mgnt->ext_config.hci_ext_ver);
+
+ ptriple = &pcmd[1];
+ for (i = 0; i < num_of_handle; i++) {
+ if (bt_mgnt->ext_config.hci_ext_ver < 1) {
+ connect_handle = *((u8 *)&ptriple[0]);
+ bt_profile = ptriple[2];
+ bt_corespec = ptriple[3];
+ if (BT_PROFILE_SCO == bt_profile) {
+ bt_mgnt->ext_config.number_of_sco++;
+ } else {
+ bt_mgnt->ext_config.number_of_acl++;
+ bt_mgnt->ext_config.acl_link[i].connect_handle =
+ connect_handle;
+ bt_mgnt->ext_config.acl_link[i].bt_profile =
+ bt_profile;
+ bt_mgnt->ext_config.acl_link[i].bt_corespec =
+ bt_corespec;
+ }
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "Connection_Handle =0x%x, bt_profile =%d, BTSpec =%d\n",
+ connect_handle, bt_profile, bt_corespec);
+ ptriple += 4;
+ } else if (bt_mgnt->ext_config.hci_ext_ver >= 1) {
+ connect_handle = *((u16 *)&ptriple[0]);
+ bt_profile = ptriple[2];
+ bt_corespec = ptriple[3];
+ link_role = ptriple[4];
+ if (BT_PROFILE_SCO == bt_profile) {
+ bt_mgnt->ext_config.number_of_sco++;
+ } else {
+ bt_mgnt->ext_config.number_of_acl++;
+ bt_mgnt->ext_config.acl_link[i].connect_handle =
+ connect_handle;
+ bt_mgnt->ext_config.acl_link[i].bt_profile =
+ bt_profile;
+ bt_mgnt->ext_config.acl_link[i].bt_corespec =
+ bt_corespec;
+ bt_mgnt->ext_config.acl_link[i].link_role =
+ link_role;
+ }
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "Connection_Handle =0x%x, bt_profile =%d, BTSpec =%d, link_role =%d\n",
+ connect_handle, bt_profile, bt_corespec,
+ link_role);
+
+ ptriple += 5;
+ }
+ }
+ rtlpriv->btcoexist.btc_ops->btc_stack_update_profile_info();
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_LINK_STATUS_NOTIFY, status);
+}
+
+static u8 rtl_btcoex_parse_HCI_BT_coex_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_COEX_NOTIFY, status);
+}
+
+static u8 rtl_btcoex_parse_HCI_BT_operation_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "%s, OP code: %d\n", __func__, pcmd[0]);
+
+ switch (pcmd[0]) {
+ case HCI_BT_OP_NONE:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Operation None!!\n");
+ break;
+ case HCI_BT_OP_INQUIRY_START:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Inquiry start!!\n");
+ break;
+ case HCI_BT_OP_INQUIRY_FINISH:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Inquiry finished!!\n");
+ break;
+ case HCI_BT_OP_PAGING_START:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Paging is started!!\n");
+ break;
+ case HCI_BT_OP_PAGING_SUCCESS:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Paging complete successfully!!\n");
+ break;
+ case HCI_BT_OP_PAGING_UNSUCCESS:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Paging complete unsuccessfully!!\n");
+ break;
+ case HCI_BT_OP_PAIRING_START:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Pairing start!!\n");
+ break;
+ case HCI_BT_OP_PAIRING_FINISH:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Pairing finished!!\n");
+ break;
+ case HCI_BT_OP_BT_DEV_ENABLE:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : BT Device is enabled!!\n");
+ break;
+ case HCI_BT_OP_BT_DEV_DISABLE:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : BT Device is disabled!!\n");
+ break;
+ default:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "[bt operation] : Unknown, error!!\n");
+ break;
+ }
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_OPERATION_NOTIFY, status);
+}
+
+static u8 rtl_btcoex_parse_BT_AFH_MAP_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_AFH_MAP_NOTIFY, status);
+}
+
+static u8 rtl_btcoex_parse_BT_register_val_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_REGISTER_VALUE_NOTIFY,
+ status);
+}
+
+static u8 rtl_btcoex_parse_HCI_BT_abnormal_notify_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_BT_ABNORMAL_NOTIFY, status);
+}
+
+static u8 rtl_btcoex_parse_HCI_query_RF_status_cmd(struct rtl_priv *rtlpriv,
+ u8 *pcmd, u16 cmdlen)
+{
+ enum HCI_STATUS status = HCI_STATUS_SUCCESS;
+
+ return rtl_send_comp_ev_to_bt(rtlpriv, HCI_QUERY_RF_STATUS, status);
+}
+
+/*****************************************
+* HCI cmd format :
+*| 15 - 0 |
+*| OPcode (OCF|OGF<<10) |
+*| 15 - 8 |7 - 0 |
+*|Cmd para |Cmd para Length |
+*|Cmd para...... |
+******************************************/
+
+/* bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+/* | OCF | OGF | */
+static void rtl_btcoex_parse_hci_extend_cmd(struct rtl_priv *rtlpriv, u8 *pcmd,
+ u16 len, const u16 hci_OCF)
+{
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, "#LEVEL2,");
+ switch (hci_OCF) {
+ case HCI_EXTENSION_VERSION_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_EXTENSION_VERSION_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_HCI_Ver_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_LINK_STATUS_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_LINK_STATUS_NOTIFY#LEVEL3\n");
+ rtl_btcoex_parse_HCI_link_status_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_OPERATION_NOTIFY:
+ /* only for 8723a 2ant*/
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_OPERATION_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_HCI_BT_operation_notify_cmd(rtlpriv,
+ pcmd, len);
+ break;
+ case HCI_ENABLE_WIFI_SCAN_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_ENABLE_WIFI_SCAN_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_WIFI_scan_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_QUERY_RF_STATUS:
+ /* only for 8723b 2ant */
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_QUERY_RF_STATUS\n#LEVEL3,");
+ rtl_btcoex_parse_HCI_query_RF_status_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_ABNORMAL_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_ABNORMAL_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_HCI_BT_abnormal_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_INFO_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_INFO_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_BT_info_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_COEX_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_COEX_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_HCI_BT_coex_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_PATCH_VERSION_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_PATCH_VERSION_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_BT_patch_ver_info_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_AFH_MAP_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_AFH_MAP_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_BT_AFH_MAP_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ case HCI_BT_REGISTER_VALUE_NOTIFY:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "HCI_BT_REGISTER_VALUE_NOTIFY\n#LEVEL3,");
+ rtl_btcoex_parse_BT_register_val_notify_cmd(rtlpriv, pcmd, len);
+ break;
+ default:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "ERROR!!! Unknown OCF: %x\n", hci_OCF);
+ break;
+ }
+}
+
+static void rtl_btcoex_parse_hci_cmd(struct rtl_priv *rtlpriv, u8 *pcmd,
+ u16 len)
+{
+ u16 opcode = pcmd[0] | pcmd[1]<<8;
+ u16 hci_OGF = HCI_OGF(opcode);
+ u16 hci_OCF = HCI_OCF(opcode);
+ u8 cmdlen = len - 3;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL1, OGF: %x, OCF: %x\n", hci_OGF, hci_OCF);
+
+ switch (hci_OGF) {
+ case OGF_EXTENSION:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL1, HCI_EXTENSION_CMD_OGF\n");
+ rtl_btcoex_parse_hci_extend_cmd(rtlpriv, &pcmd[3], cmdlen,
+ hci_OCF);
+ break;
+ default:
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL1, Other OGF: %x\n", hci_OGF);
+ break;
+ }
+}
+
+static u16 rtl_btcoex_parse_recv_data(u8 *msg, u8 msg_size)
+{
+ u8 *cmp_msg1 = attend_ack;
+ u8 *cmp_msg2 = leave_ack;
+ u8 *cmp_msg3 = bt_leave;
+ u8 *cmp_msg4 = invite_req;
+ u8 *cmp_msg5 = attend_req;
+ u8 *cmp_msg6 = invite_rsp;
+ u8 res = OTHER;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "\n>>>>>>>>>>>>>>>>>>>>>>>BT_TO_WIFI");
+
+ if (memcmp(cmp_msg1, msg, msg_size) == 0) {
+ res = RX_ATTEND_ACK;
+ } else if (memcmp(cmp_msg2, msg, msg_size) == 0) {
+ res = RX_LEAVE_ACK;
+ } else if (memcmp(cmp_msg3, msg, msg_size) == 0) {
+ res = RX_BT_LEAVE;
+ } else if (memcmp(cmp_msg4, msg, msg_size) == 0) {
+ res = RX_INVITE_REQ;
+ } else if (memcmp(cmp_msg5, msg, msg_size) == 0) {
+ res = RX_ATTEND_REQ;
+ } else if (memcmp(cmp_msg6, msg, msg_size) == 0) {
+ res = RX_INVITE_RSP;
+ } else {
+ res = OTHER;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL, ", other_cmd!\n");
+ }
+
+ if (OTHER != res)
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ ", base_cmd:%s\n", msg);
+ return res;
+}
+
+static void rtl_btcoex_recvmsg_int(struct sock *sk_in)
+{
+ struct rtl_priv *rtlpriv = pbtcoexadapter;
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+
+ pcoex_info->sk_store = sk_in;
+ queue_delayed_work(pbtcoexadapter->works.rtl_wq,
+ &rtlpriv->works.socket_wq, 0);
+}
+
+static void rtl_btcoex_recvmsgbysocket(void *data)
+{
+ struct rtl_priv *rtlpriv = pbtcoexadapter;
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ struct sock *sk = pcoex_info->sk_store;
+ struct sk_buff *skb = NULL;
+ u8 *recv_data;
+ u32 len = 0;
+ u16 recv_length = 0;
+ u16 parse_res = 0;
+
+ recv_data = kzalloc(RECV_DATA_MAX_LEN, GFP_ATOMIC);
+ if (!recv_data)
+ return;
+ if (!sk) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "critical error when receive socket data!\n");
+ return;
+ }
+ len = skb_queue_len(&sk->sk_receive_queue);
+ while (len > 0) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
+
+ /* important: cut the udp header from skb->data!
+ * header length is 8 byte
+ */
+ recv_length = skb->len-8;
+ memset(recv_data, 0, RECV_DATA_MAX_LEN);
+ safe_memcpy(recv_data, skb->data+8, recv_length,
+ RECV_DATA_MAX_LEN);
+
+ parse_res = rtl_btcoex_parse_recv_data(recv_data, recv_length);
+ if (RX_ATTEND_ACK == parse_res) { /* attend ack */
+ pcoex_info->bt_attend = true;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "RX_ATTEND_ACK!, sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open,
+ pcoex_info->bt_attend);
+ }
+ if (RX_ATTEND_REQ == parse_res) { /* attend req from BT */
+ pcoex_info->bt_attend = true;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "RX_BT_ATTEND_REQ!, sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open,
+ pcoex_info->bt_attend);
+ rtl_btcoex_sendmsgbysocket(pbtcoexadapter, attend_ack,
+ sizeof(attend_ack), false);
+ }
+ if (RX_INVITE_REQ == parse_res) { /* attend req from BT */
+ pcoex_info->bt_attend = true;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "RX_INVITE_REQ!, sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open,
+ pcoex_info->bt_attend);
+ rtl_btcoex_sendmsgbysocket(pbtcoexadapter, invite_rsp,
+ sizeof(invite_rsp), false);
+ }
+ if (RX_INVITE_RSP == parse_res) {
+ /* attend req from BT */
+ pcoex_info->bt_attend = true;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "RX_INVITE_RSP!, sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open,
+ pcoex_info->bt_attend);
+ } else if (RX_LEAVE_ACK == parse_res) {
+ /* mean BT know wifi will leave */
+ pcoex_info->bt_attend = false;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "RX_LEAVE_ACK!, sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open,
+ pcoex_info->bt_attend);
+ } else if (RX_BT_LEAVE == parse_res) { /* BT leave */
+ rtl_btcoex_sendmsgbysocket(pbtcoexadapter, leave_ack,
+ sizeof(leave_ack),
+ false); /* no ack */
+ pcoex_info->bt_attend = false;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "RX_BT_LEAVE!sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open,
+ pcoex_info->bt_attend);
+ } else { /*todo: check if recv data are really hci cmds*/
+ if (pcoex_info->bt_attend)
+ rtl_btcoex_parse_hci_cmd(pbtcoexadapter,
+ recv_data,
+ recv_length);
+ }
+ len--;
+ kfree_skb(skb);
+ /*never do a sleep in this context!*/
+ }
+ kfree(recv_data);
+}
+
+u8 rtl_btcoex_sendmsgbysocket(struct rtl_priv *rtlpriv, u8 *msg, u8 msg_size,
+ bool force)
+{
+ struct msghdr udpmsg;
+ struct iovec iov;
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ u8 error;
+ mm_segment_t oldfs;
+
+ /* This driver uses a kernel socket to allow 8812AE (wifi) and
+ * 8761AU (bluetooth) to communicate with each other to maintain
+ * coexistance. Other wifi chips use special hardware available
+ * to the firmware, but that feature does not exist on the 8812AE,
+ * thus the need for a kernel socket.
+ */
+ if (!force) {
+ if (!pcoex_info->bt_attend) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "TX Blocked: WiFi-BT disconnected\n");
+ return _FAIL;
+ }
+ }
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "<<<<<<<<<<<<<<<<<<<<<<<<WIFI_TO_BT, msg:%s\n", msg);
+
+ /* load message parameters into socket */
+ iov.iov_base = (void __user *)msg;
+ iov.iov_len = msg_size;
+ udpmsg.msg_name = &pcoex_info->bt_addr;
+ udpmsg.msg_namelen = sizeof(struct sockaddr_in);
+ udpmsg.msg_control = NULL;
+ udpmsg.msg_controllen = 0;
+ udpmsg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+ udpmsg.msg_flags = 0;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ /* send the message */
+ error = sock_sendmsg(pcoex_info->udpsock, &udpmsg, msg_size);
+ set_fs(oldfs);
+ if (error < 0) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "Error when sendimg msg, error:%d\n", error);
+ return _FAIL;
+ }
+ return _SUCCESS;
+}
+
+static u8 rtl_btcoex_create_kernel_socket(struct rtl_priv *rtlpriv,
+ u8 is_invite)
+{
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ s8 kernel_socket_err;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "%s CONNECT_PORT %d\n", __func__, CONNECT_PORT);
+
+ if (!pcoex_info) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL, "coex_info: NULL\n");
+ return _FAIL;
+ }
+
+ kernel_socket_err = sock_create(PF_INET, SOCK_DGRAM, 0,
+ &pcoex_info->udpsock);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "binding socket, err = %d\n", kernel_socket_err);
+
+ if (kernel_socket_err < 0) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "Error during creation of socket error:%d\n",
+ kernel_socket_err);
+ return _FAIL;
+ }
+ memset(&pcoex_info->sin, 0, sizeof(pcoex_info->sin));
+ pcoex_info->sin.sin_family = AF_INET;
+ pcoex_info->sin.sin_port = htons(CONNECT_PORT);
+ pcoex_info->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ memset(&pcoex_info->bt_addr, 0, sizeof(pcoex_info->bt_addr));
+ pcoex_info->bt_addr.sin_family = AF_INET;
+ pcoex_info->bt_addr.sin_port = htons(CONNECT_PORT_BT);
+ pcoex_info->bt_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ pcoex_info->sk_store = NULL;
+
+ kernel_socket_err =
+ pcoex_info->udpsock->ops->bind(pcoex_info->udpsock,
+ (struct sockaddr *)&pcoex_info->sin,
+ sizeof(pcoex_info->sin));
+ if (kernel_socket_err == 0) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "binding socket success\n");
+ pcoex_info->udpsock->sk->sk_data_ready =
+ rtl_btcoex_recvmsg_int;
+ pcoex_info->sock_open |= KERNEL_SOCKET_OK;
+ pcoex_info->bt_attend = false;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "WIFI sending attend_req\n");
+ rtl_btcoex_sendmsgbysocket(rtlpriv, attend_req,
+ sizeof(attend_req), true);
+ return _SUCCESS;
+ }
+ pcoex_info->bt_attend = false;
+ sock_release(pcoex_info->udpsock);
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "Error binding socket: %d\n",
+ kernel_socket_err);
+ return _FAIL;
+}
+
+static void rtl_btcoex_close_kernel_socket(struct rtl_priv *rtlpriv)
+{
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+
+ if (pcoex_info->sock_open & KERNEL_SOCKET_OK) {
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "release kernel socket\n");
+ cancel_delayed_work(&rtlpriv->works.socket_wq);
+
+ sock_release(pcoex_info->udpsock);
+ pcoex_info->sock_open &= ~(KERNEL_SOCKET_OK);
+ if (pcoex_info->bt_attend)
+ pcoex_info->bt_attend = false;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "sock_open:%d, bt_attend:%d\n",
+ pcoex_info->sock_open, pcoex_info->bt_attend);
+ }
+}
+
+void rtl_btcoex_init_socket(struct rtl_priv *rtlpriv)
+{
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ u8 is_invite = false;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "8812AE:init socket with 8761AU\n");
+
+ INIT_DELAYED_WORK(&rtlpriv->works.socket_wq,
+ (void *)rtl_btcoex_recvmsgbysocket);
+
+ if (!pcoex_info->is_exist) {
+ memset(pcoex_info, 0, sizeof(struct bt_coex_info));
+ pbtcoexadapter = rtlpriv;
+ rtl_btcoex_create_kernel_socket(rtlpriv, is_invite);
+ pcoex_info->is_exist = true;
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "set coex_info->is_exist: %d\n",
+ pcoex_info->is_exist);
+ }
+}
+
+void rtl_btcoex_close_socket(struct rtl_priv *rtlpriv)
+{
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "set coex_info->is_exist: %d\n", pcoex_info->is_exist);
+ if (pcoex_info->is_exist) {
+ pcoex_info->is_exist = false;
+ if (pcoex_info->bt_attend) {/*inform BT wifi leave*/
+ rtl_btcoex_sendmsgbysocket(rtlpriv, wifi_leave,
+ sizeof(wifi_leave), false);
+ msleep(50);
+ }
+ rtl_btcoex_close_kernel_socket(rtlpriv);
+ pbtcoexadapter = NULL;
+ }
+}
+
+void rtl_btcoex_dump_tx_msg(u8 *tx_msg, u8 len, u8 *msg_name)
+{
+}
+
+void rtl_btcoex_sendeventextbtcoexcontrol(struct rtl_priv *rtlpriv,
+ u8 needdbgrsp, u8 datalen,
+ void *pdata)
+{
+ u8 len = 0, tx_event_length = 0;
+ u8 local_buf[32] = "";
+ u8 *ret_par;
+ u8 opcode = 0;
+ u8 *pinbuf = (u8 *)pdata;
+ struct rtl_hci_event *hci_event;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL_WIFI_ACTIVE, SendEventExtBtCoexControl\n");
+ opcode = pinbuf[0];
+
+ hci_event = (struct rtl_hci_event *)(&local_buf[0]);
+
+ hci_event->event_code = HCI_EVENT_EXTENSION_RTK;
+ /* extension event code */
+ hci_event->data[0] = HCI_EVENT_EXT_BT_COEX_CONTROL;
+ len++;
+ ret_par = hci_event->data + len;
+ memcpy(&ret_par[0], pdata, datalen); /*maybe not safe here*/
+ len += datalen;
+ hci_event->length = len;
+ /* total tx event length + event_code length + sizeof(length) */
+ tx_event_length = hci_event->length + 2;
+ rtl_btcoex_dump_tx_msg((u8 *)hci_event, tx_event_length,
+ "BT COEX CONTROL");
+ rtl_btcoex_sendmsgbysocket(rtlpriv, (u8 *)hci_event, tx_event_length,
+ false);
+}
+
+void rtl_btcoex_sendeventextbtinfocontrol(struct rtl_priv *rtlpriv, u8 datalen,
+ void *pdata)
+{
+ struct rtl_hci_event *hci_event;
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ struct bt_mgnt *bt_mgnt = &pcoex_info->btmgnt;
+ u8 *ret_par;
+ u8 len = 0, tx_event_length = 0;
+ u8 local_buf[32] = "";
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL_WIFI_ACTIVE, SendEventExtBtInfoControl\n");
+
+ if (bt_mgnt->ext_config.hci_ext_ver < 4) { /* no support */
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,
+ "ERROR: hci_extension_ver = %d, oonly versions < 4 supported\n",
+ bt_mgnt->ext_config.hci_ext_ver);
+ return;
+ }
+ hci_event = (struct rtl_hci_event *)(&local_buf[0]);
+ hci_event->event_code = HCI_EVENT_EXTENSION_RTK;
+ hci_event->data[0] = HCI_EVENT_EXT_BT_INFO_CONTROL;
+ len++;
+ ret_par = hci_event->data + len;
+
+ memcpy(&ret_par[0], pdata, datalen);/*maybe not safe here*/
+ len += datalen;
+ hci_event->length = len;
+ /* total tx event length + event_code length + sizeof(length) */
+ tx_event_length = hci_event->length + 2;
+ rtl_btcoex_dump_tx_msg((u8 *)hci_event, tx_event_length,
+ "BT INFO CONTROL");
+ rtl_btcoex_sendmsgbysocket(rtlpriv, (u8 *)hci_event, tx_event_length,
+ false);
+}
+
+void rtl_btcoex_sendscannotify(struct rtl_priv *rtlpriv, u8 scantype)
+{
+ struct rtl_hci_event *hci_event;
+ u8 tx_event_length = 0;
+ u8 local_buf[7] = "";
+ u8 *event_data = NULL;
+
+ BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,
+ "#LEVEL_WIFI_ACTIVE, SendScanNotify\n");
+
+ hci_event = (struct rtl_hci_event *)(&local_buf[0]);
+ hci_event->event_code = HCI_EVENT_EXTENSION_RTK;
+ event_data = hci_event->data;
+ *(event_data) = HCI_EVENT_EXT_WIFI_SCAN_NOTIFY;
+ *(event_data + 1) = scantype;
+ hci_event->length = 2;
+ /* total tx event length + event_code length + sizeof(length) */
+ tx_event_length = hci_event->length + 2;
+ rtl_btcoex_dump_tx_msg((u8 *)hci_event, tx_event_length,
+ "WIFI SCAN OPERATION");
+ rtl_btcoex_sendmsgbysocket(rtlpriv, (u8 *)hci_event, tx_event_length,
+ false);
+}
Index: wireless-drivers/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.h
===================================================================
--- /dev/null
+++ wireless-drivers/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a_ext.h
@@ -0,0 +1,359 @@
+#ifndef __8812A_EXT_H__
+#define __8812A_EXT_H__
+
+/* for socket */
+#include <net/sock.h>
+#include <net/tcp.h>
+#include <linux/udp.h>
+#include <linux/in.h>
+#include <linux/netlink.h>
+
+#define _FAIL 0
+#define _SUCCESS 1
+#define BT_INFO_LENGTH 8
+#define RECV_DATA_MAX_LEN 255
+#define BTINFO_WIFI_FETCH 0x23
+#define BTINFO_BT_AUTO_RPT 0x27
+
+#define CONNECT_PORT 30000
+#define CONNECT_PORT_BT 30001
+#define KERNEL_SOCKET_OK 0x01
+
+#define OTHER 0
+#define RX_ATTEND_ACK 1
+#define RX_LEAVE_ACK 2
+#define RX_BT_LEAVE 3
+#define RX_INVITE_REQ 4
+#define RX_ATTEND_REQ 5
+#define RX_INVITE_RSP 6
+
+#define invite_req "INVITE_REQ"
+#define invite_rsp "INVITE_RSP"
+#define attend_req "ATTEND_REQ"
+#define attend_ack "ATTEND_ACK"
+#define wifi_leave "WIFI_LEAVE"
+#define leave_ack "LEAVE_ACK"
+#define bt_leave "BT_LEAVE"
+
+#define BT_INFO_NOTIFY_CMD 0x0106
+#define BT_INFO_LEN 8
+
+struct hci_link_info {
+ u16 connect_handle;
+ u8 incoming_traffic_mode;
+ u8 outgoing_traffic_mode;
+ u8 bt_profile;
+ u8 bt_corespec;
+ s8 bt_RSSI;
+ u8 traffic_profile;
+ u8 link_role;
+};
+
+#define MAX_BT_ACL_LINK_NUM 8
+
+struct hci_ext_config {
+ struct hci_link_info acl_link[MAX_BT_ACL_LINK_NUM];
+ u8 bt_operation_code;
+ u16 current_connect_handle;
+ u8 current_incoming_traffic_mode;
+ u8 current_outgoing_traffic_mode;
+
+ u8 number_of_acl;
+ u8 number_of_sco;
+ u8 current_bt_status;
+ u16 hci_ext_ver;
+ bool enable_wifi_scan_notify;
+};
+
+struct hci_phy_link_bss_info {
+ u16 bdcap; /* capability information */
+};
+
+enum BT_CONNECT_TYPE {
+ BT_CONNECT_AUTH_REQ = 0x00,
+ BT_CONNECT_AUTH_RSP = 0x01,
+ BT_CONNECT_ASOC_REQ = 0x02,
+ BT_CONNECT_ASOC_RSP = 0x03,
+ BT_DISCONNECT = 0x04
+};
+
+struct rtl_hci_event {
+ u8 event_code;
+ u8 length; /* total cmd length = extension event length+1
+ * (extension event code length)
+ */
+ u8 data[1]; /* byte1 is extension event code */
+};
+
+struct btinfo_8761au {
+ u8 cid;
+ u8 len;
+
+ u8 connection:1;
+ u8 scoe_sco:1;
+ u8 inq_page:1;
+ u8 acl_busy:1;
+ u8 sco_busy:1;
+ u8 hid:1;
+ u8 a2dp:1;
+ u8 ftp:1;
+
+ u8 retry_cnt:4;
+ u8 rsvd_34:1;
+ u8 page:1;
+ u8 trx_mask:1;
+ u8 sniff_attempt:1;
+
+ u8 rssi;
+
+ u8 a2dp_rate:1;
+ u8 re_init:1;
+ u8 max_power:1;
+ u8 en_ignore_wlan_act:1;
+ u8 tx_power_low:1;
+ u8 tx_power_high:1;
+ u8 esco_sco:1;
+ u8 master_slave:1;
+
+ u8 acl_trx_tp_low;
+ u8 acl_trx_tp_high;
+};
+
+#define HCIOPCODE(_OCF, _OGF) ((_OGF)<<10|(_OCF))
+#define HCIOPCODELOW(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)&0x00ff)
+#define HCIOPCODEHIGHT(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)>>8)
+#define HCI_OGF(__opcode) (unsigned char)((0xFC00 & (__opcode)) >> 10)
+#define HCI_OCF(__opcode) (0x3FF & (__opcode))
+
+enum HCI_STATUS {
+ /* Success */
+ HCI_STATUS_SUCCESS = 0x00,
+ /* Unknown HCI Command */
+ HCI_STATUS_UNKNOW_HCI_CMD = 0x01,
+ /* Unknown Connection Identifier */
+ HCI_STATUS_UNKNOW_CONNECT_ID = 0X02,
+ /* Hardware Failure */
+ HCI_STATUS_HW_FAIL = 0X03,
+ /* Page Timeout */
+ HCI_STATUS_PAGE_TIMEOUT = 0X04,
+ /* Authentication Failure */
+ HCI_STATUS_AUTH_FAIL = 0X05,
+ /* PIN or Key Missing */
+ HCI_STATUS_PIN_OR_KEY_MISSING = 0X06,
+ /* Memory Capacity Exceeded */
+ HCI_STATUS_MEM_CAP_EXCEED = 0X07,
+ /* Connection Timeout */
+ HCI_STATUS_CONNECT_TIMEOUT = 0X08,
+ /* Connection Limit Exceeded */
+ HCI_STATUS_CONNECT_LIMIT = 0X09,
+ /* Synchronous Connection Limit To A Device Exceeded */
+ HCI_STATUS_SYN_CONNECT_LIMIT = 0X0a,
+ /* ACL Connection Already Exists */
+ HCI_STATUS_ACL_CONNECT_EXISTS = 0X0b,
+ /* Command Disallowed */
+ HCI_STATUS_CMD_DISALLOW = 0X0c,
+ /* Connection Rejected due to Limited Resources */
+ HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE = 0X0d,
+ /* Connection Rejected Due To Security Reasons */
+ HCI_STATUS_CONNECT_RJT_SEC_REASON = 0X0e,
+ /* Connection Rejected due to Unacceptable BD_ADDR */
+ HCI_STATUS_CONNECT_RJT_UNACCEPT_BD_ADDR = 0X0f,
+ /* Connection Accept Timeout Exceeded */
+ HCI_STATUS_CONNECT_ACCEPT_TIMEOUT = 0X10,
+ /* Unsupported Feature or Parameter Value */
+ HCI_STATUS_UNSUPPORT_FEATURE_PARA_VALUE = 0X11,
+ /* Invalid HCI Command Parameters */
+ HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE = 0X12,
+ /* Remote User Terminated Connection */
+ HCI_STATUS_REMOTE_USER_TERMINATE_CONNECT = 0X13,
+ /* Remote Device Terminated Connection due to Low Resources */
+ HCI_STATUS_REMOTE_DEV_TERMINATE_LOW_RESOURCE = 0X14,
+ /* Remote Device Terminated Connection due to Power Off */
+ HCI_STATUS_REMOTE_DEV_TERMINATE_CONNECT_POWER_OFF = 0X15,
+ /* Connection Terminated By Local Host */
+ HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST = 0X16,
+ /* Repeated Attempts */
+ HCI_STATUS_REPEATE_ATTEMPT = 0X17,
+ /* Pairing Not Allowed */
+ HCI_STATUS_PAIR_NOT_ALLOW = 0X18,
+ /* Unknown LMP PDU */
+ HCI_STATUS_UNKNOW_LMP_PDU = 0X19,
+ /* Unsupported Remote Feature / Unsupported LMP Feature */
+ HCI_STATUS_UNSUPPORT_REMOTE_LMP_FEATURE = 0X1a,
+ /* SCO Offset Rejected */
+ HCI_STATUS_SOC_OFFSET_REJECT = 0X1b,
+ /* SCO Interval Rejected */
+ HCI_STATUS_SOC_INTERVAL_REJECT = 0X1c,
+ /* SCO Air Mode Rejected */
+ HCI_STATUS_SOC_AIR_MODE_REJECT = 0X1d,
+ /* Invalid LMP Parameters */
+ HCI_STATUS_INVALID_LMP_PARA = 0X1e,
+ /* Unspecified Error */
+ HCI_STATUS_UNSPECIFIC_ERROR = 0X1f,
+ /* Unsupported LMP Parameter Value */
+ HCI_STATUS_UNSUPPORT_LMP_PARA_VALUE = 0X20,
+ /* Role Change Not Allowed */
+ HCI_STATUS_ROLE_CHANGE_NOT_ALLOW = 0X21,
+ /* LMP Response Timeout */
+ HCI_STATUS_LMP_RESPONSE_TIMEOUT = 0X22,
+ /* LMP Error Transaction Collision */
+ HCI_STATUS_LMP_ERROR_TRANSACTION_COLLISION = 0X23,
+ /* LMP PDU Not Allowed */
+ HCI_STATUS_LMP_PDU_NOT_ALLOW = 0X24,
+ /* Encryption Mode Not Acceptable */
+ HCI_STATUS_ENCRYPTION_MODE_NOT_ALLOW = 0X25,
+ /* Link Key Can Not be Changed */
+ HCI_STATUS_LINK_KEY_CAN_NOT_CHANGE = 0X26,
+ /* Requested QoS Not Supported */
+ HCI_STATUS_REQUEST_QOS_NOT_SUPPORT = 0X27,
+ /* Instant Passed */
+ HCI_STATUS_INSTANT_PASSED = 0X28,
+ /* Pairing With Unit Key Not Supported */
+ HCI_STATUS_PAIRING_UNIT_KEY_NOT_SUPPORT = 0X29,
+ /* Different Transaction Collision */
+ HCI_STATUS_DIFFERENT_TRANSACTION_COLLISION = 0X2a,
+ /* Reserved */
+ HCI_STATUS_RESERVE_1 = 0X2b,
+ /* QoS Unacceptable Parameter */
+ HCI_STATUS_QOS_UNACCEPT_PARA = 0X2c,
+ /* QoS Rejected */
+ HCI_STATUS_QOS_REJECT = 0X2d,
+ /* Channel Classification Not Supported */
+ HCI_STATUS_CHNL_CLASSIFICATION_NOT_SUPPORT = 0X2e,
+ /* Insufficient Security */
+ HCI_STATUS_INSUFFICIENT_SECURITY = 0X2f,
+ /* Parameter Out Of Mandatory Range */
+ HCI_STATUS_PARA_OUT_OF_RANGE = 0x30,
+ /* Reserved */
+ HCI_STATUS_RESERVE_2 = 0X31,
+ /* Role Switch Pending */
+ HCI_STATUS_ROLE_SWITCH_PENDING = 0X32,
+ /* Reserved */
+ HCI_STATUS_RESERVE_3 = 0X33,
+ /* Reserved Slot Violation */
+ HCI_STATUS_RESERVE_SOLT_VIOLATION = 0X34,
+ /* Role Switch Failed */
+ HCI_STATUS_ROLE_SWITCH_FAIL = 0X35,
+ /* Extended Inquiry Response Too Large */
+ HCI_STATUS_EXTEND_INQUIRY_RSP_TOO_LARGE = 0X36,
+ /* Secure Simple Pairing Not Supported By Host. */
+ HCI_STATUS_SEC_SIMPLE_PAIRING_NOT_SUPPORT = 0X37,
+ /* Host Busy - Pairing */
+ HCI_STATUS_HOST_BUSY_PAIRING = 0X38,
+ /* Connection Rejected due to No Suitable Channel Found */
+ HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND = 0X39,
+ /* CONTROLLER BUSY */
+ HCI_STATUS_CONTROLLER_BUSY = 0X3a
+};
+
+#define HCI_EVENT_COMMAND_COMPLETE 0x0e
+
+#define OGF_EXTENSION 0X3f
+
+enum HCI_EXTENSION_COMMANDS {
+ HCI_SET_ACL_LINK_DATA_FLOW_MODE = 0x0010,
+ HCI_SET_ACL_LINK_STATUS = 0x0020,
+ HCI_SET_SCO_LINK_STATUS = 0x0030,
+ HCI_SET_RSSI_VALUE = 0x0040,
+ HCI_SET_CURRENT_BLUETOOTH_STATUS = 0x0041,
+
+ /* The following is for RTK8723 */
+ HCI_EXTENSION_VERSION_NOTIFY = 0x0100,
+ HCI_LINK_STATUS_NOTIFY = 0x0101,
+ HCI_BT_OPERATION_NOTIFY = 0x0102,
+ HCI_ENABLE_WIFI_SCAN_NOTIFY = 0x0103,
+ HCI_QUERY_RF_STATUS = 0x0104,
+ HCI_BT_ABNORMAL_NOTIFY = 0x0105,
+ HCI_BT_INFO_NOTIFY = 0x0106,
+ HCI_BT_COEX_NOTIFY = 0x0107,
+ HCI_BT_PATCH_VERSION_NOTIFY = 0x0108,
+ HCI_BT_AFH_MAP_NOTIFY = 0x0109,
+ HCI_BT_REGISTER_VALUE_NOTIFY = 0x010a,
+
+ /* The following is for IVT */
+ HCI_WIFI_CURRENT_CHANNEL = 0x0300,
+ HCI_WIFI_CURRENT_BANDWIDTH = 0x0301,
+ HCI_WIFI_CONNECTION_STATUS = 0x0302
+};
+
+#define HCI_EVENT_EXTENSION_RTK 0xfe
+enum RTW_HCI_EXT_EVENT {
+ HCI_EVENT_EXT_WIFI_SCAN_NOTIFY = 0x01,
+ HCI_EVENT_EXT_WIFI_RF_STATUS_NOTIFY = 0x02,
+ HCI_EVENT_EXT_BT_INFO_CONTROL = 0x03,
+ HCI_EVENT_EXT_BT_COEX_CONTROL = 0x04
+};
+
+enum BT_TRAFFIC_MODE {
+ /* Best Effort. Default. for HCRP, PAN, SDP, RFCOMM-based
+ * profiles like FTP, OPP, SPP, DUN, etc.
+ */
+ BT_MOTOR_EXT_BE = 0x00,
+ /* Guaranteed Latency. This is used e.g. for HID and AVRCP. */
+ BT_MOTOR_EXT_GUL = 0x01,
+ /* Guaranteed Bandwidth. */
+ BT_MOTOR_EXT_GUB = 0X02,
+ /* Guaranteed Latency and Bandwidth. for A2DP and VDP. */
+ BT_MOTOR_EXT_GULB = 0X03
+};
+
+enum BT_TRAFFIC_MODE_PROFILE {
+ BT_PROFILE_NONE,
+ BT_PROFILE_A2DP,
+ BT_PROFILE_PAN,
+ BT_PROFILE_HID,
+ BT_PROFILE_SCO
+};
+
+struct bt_mgnt {
+ bool bt_connect_in_progress;
+ bool loglink_in_progress;
+ bool phylink_in_progress;
+ bool phylink_in_progress_start_ll;
+ u8 bt_current_phy_link_handle;
+ u16 bt_current_log_link_handle;
+ u8 current_connect_entry_num;
+ u8 disconnect_entry_num;
+ u8 current_bt_connection_cnt;
+ enum BT_CONNECT_TYPE bt_current_connect_type;
+ enum BT_CONNECT_TYPE bt_receive_connect_pkt;
+ u8 bt_auth_count;
+ u8 bt_asoc_count;
+ bool start_send_supervision_pkt;
+ bool bt_operation_on;
+ bool bt_need_amp_status_chg;
+ bool joiner_need_send_auth;
+ struct hci_phy_link_bss_info bss_desc;
+ struct hci_ext_config ext_config;
+ bool need_notify_amp_no_cap;
+ bool create_support_qos;
+ bool support_profile;
+ u8 bt_hannel;
+ bool check_chnl_is_suit;
+ bool bt_scan;
+ bool bt_logo_rest;
+ bool rf_status_notified;
+ bool bt_rsved_page_download;
+};
+
+#define SOCK_STORE_MAX 10
+struct bt_coex_info {
+ /* For Kernel Socket */
+ struct socket *udpsock;
+ struct sockaddr_in sin;
+ struct sockaddr_in bt_addr;
+ struct sock *sk_store;/*back up socket for UDP RX int*/
+ u32 pid;
+ /* store which socket is OK */
+ u8 sock_open;
+ u8 bt_attend;
+ u8 is_exist; /* socket exist */
+ struct bt_mgnt btmgnt;
+};
+
+#define PACKET_NORMAL 0
+#define PACKET_DHCP 1
+#define PACKET_ARP 2
+#define PACKET_EAPOL 3
+
+#endif
^ permalink raw reply
* [PATCH V2 6/6] rtlwifi: btcoexist: Enable new routines for RTL8812AE
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Troy Tan, netdev, Larry Finger
In-Reply-To: <1422304934-9239-1-git-send-email-Larry.Finger@lwfinger.net>
From: Troy Tan <troy_tan@realsil.com.cn>
In addition to turning on the build of the new routines, there are several
fixes found by Realtek engineers.
Signed-off-by: Troy Tan <troy_tan@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
drivers/net/wireless/rtlwifi/btcoexist/Makefile | 9 +
.../net/wireless/rtlwifi/btcoexist/halbt_precomp.h | 3 +
.../wireless/rtlwifi/btcoexist/halbtc8192e2ant.c | 6 +-
.../wireless/rtlwifi/btcoexist/halbtc8723b2ant.h | 6 +-
.../wireless/rtlwifi/btcoexist/halbtc8812a2ant.h | 4 +-
.../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c | 711 ++++++++++++++++-----
.../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h | 24 +
drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c | 37 ++
drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h | 6 +-
drivers/net/wireless/rtlwifi/core.c | 17 +-
drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h | 14 -
drivers/net/wireless/rtlwifi/wifi.h | 12 +-
12 files changed, 676 insertions(+), 173 deletions(-)
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/Makefile b/drivers/net/wireless/rtlwifi/btcoexist/Makefile
index 47ceecf..a86e0c2 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/Makefile
+++ b/drivers/net/wireless/rtlwifi/btcoexist/Makefile
@@ -1,5 +1,14 @@
btcoexist-objs := halbtc8723b2ant.o \
halbtcoutsrc.o \
+ halbtc8192e2ant.o \
+ halbtc8723b1ant.o \
+ halbtc8723b2ant.o \
+ halbtc8812a_ext.o \
+ halbtc8821a1ant.o \
+ halbtc8821a2ant.o \
+ halbtc8812a2ant.o \
+ halbtc8812a1ant.o \
+ halbtcoutsrc.o \
rtl_btc.o
obj-$(CONFIG_RTLBTCOEXIST) += btcoexist.o
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h
index 39b9a33..c56ad98 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h
@@ -42,6 +42,9 @@
#include "halbtc8723b2ant.h"
#include "halbtc8821a2ant.h"
#include "halbtc8821a1ant.h"
+#include "halbtc8812a2ant.h"
+#include "halbtc8812a1ant.h"
+#include "halbtc8812a_ext.h"
#define GetDefaultAdapter(padapter) padapter
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c
index 53261d6..c33c37f 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c
@@ -1367,16 +1367,14 @@ static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist,
btcoexist->btc_write_1byte(btcoexist, 0xd04, 0x1);
btcoexist->btc_write_4byte(btcoexist, 0x90c, 0x81111111);
/* switch cck patch */
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0xe77, 0x4, 0x1);
- btcoexist->btc_write_1byte(btcoexist, 0xa07, 0x81);
+
mimops = BTC_MIMO_PS_STATIC;
} else if (sstype == 2) {
halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
btcoexist->btc_write_1byte(btcoexist, 0xc04, 0x33);
btcoexist->btc_write_1byte(btcoexist, 0xd04, 0x3);
btcoexist->btc_write_4byte(btcoexist, 0x90c, 0x81121313);
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0xe77, 0x4, 0x0);
- btcoexist->btc_write_1byte(btcoexist, 0xa07, 0x41);
+
mimops = BTC_MIMO_PS_DYNAMIC;
}
/* set rx 1ss or 2ss */
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h
index 567f354..ea6e383 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h
@@ -160,11 +160,11 @@ void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
void ex_btc8723b2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
void ex_btc8723b2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type);
+ u8 type);
void ex_btc8723b2ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
+ u8 type);
void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
+ u8 *tmpbuf, u8 length);
void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist);
void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist);
void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist);
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
index 0c02134..48ecdeb 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a2ant.h
@@ -162,8 +162,8 @@ void ex_halbtc8812a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
void ex_halbtc8812a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
void ex_halbtc8812a2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
void ex_halbtc8812a2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8812a2ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type);
+void ex_btc8812a2ant_media_stat_notify(struct btc_coexist *btcoexist,
+ u8 type);
void ex_halbtc8812a2ant_special_packet_notify(struct btc_coexist *btcoexist,
u8 type);
void ex_halbtc8812a2ant_bt_info_notify(struct btc_coexist *btcoexist,
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
index 7a72636..c428a59 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -11,23 +11,58 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
******************************************************************************/
#include "halbt_precomp.h"
+/*#if (BT_30_SUPPORT == 1)*/
+#if 1
/***********************************************
* Global variables
***********************************************/
+static const char *const bt_profile_string[] = {
+ "NONE",
+ "A2DP",
+ "PAN",
+ "HID",
+ "SCO",
+};
+
+static const char *const bt_spec_string[] = {
+ "1.0b",
+ "1.1",
+ "1.2",
+ "2.0+EDR",
+ "2.1+EDR",
+ "3.0+HS",
+ "4.0",
+};
+
+static const char *const bt_link_role_string[] = {
+ "Master",
+ "Slave",
+};
+
+static const char *const h2c_state_string[] = {
+ "successful",
+ "h2c busy",
+ "rf off",
+ "fw not read",
+};
+
+static const char *const io_state_string[] = {
+ "IO_STATUS_SUCCESS",
+ "IO_STATUS_FAIL_CANNOT_IO",
+ "IO_STATUS_FAIL_RF_OFF",
+ "IO_STATUS_FAIL_FW_READ_CLEAR_TIMEOUT",
+ "IO_STATUS_FAIL_WAIT_IO_EVENT_TIMEOUT",
+ "IO_STATUS_INVALID_LEN",
+ "IO_STATUS_IO_IDLE_QUEUE_EMPTY",
+ "IO_STATUS_IO_INSERT_WAIT_QUEUE_FAIL",
+ "IO_STATUS_UNKNOWN_FAIL",
+ "IO_STATUS_WRONG_LEVEL",
+ "IO_STATUS_H2C_STOPPED",
+};
struct btc_coexist gl_bt_coexist;
@@ -36,6 +71,34 @@ u32 btc_dbg_type[BTC_MSG_MAX];
/***************************************************
* Debug related function
***************************************************/
+static bool is_any_client_connect_to_ap(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+ struct rtl_sta_info *drv_priv;
+ u8 cnt = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+ mac->opmode == NL80211_IFTYPE_MESH_POINT ||
+ mac->opmode == NL80211_IFTYPE_AP) {
+ if (in_interrupt() > 0) {
+ list_for_each_entry(drv_priv, &rtlpriv->entry_list,
+ list)
+ cnt++;
+ } else {
+ spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+ list_for_each_entry(drv_priv, &rtlpriv->entry_list,
+ list)
+ cnt++;
+ spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
+ }
+ }
+ if (cnt > 0)
+ return true;
+ else
+ return false;
+}
+
static bool halbtc_is_bt_coexist_available(struct btc_coexist *btcoexist)
{
if (!btcoexist->binded || NULL == btcoexist->adapter)
@@ -59,23 +122,9 @@ static void halbtc_dbg_init(void)
for (i = 0; i < BTC_MSG_MAX; i++)
btc_dbg_type[i] = 0;
- btc_dbg_type[BTC_MSG_INTERFACE] =
-/* INTF_INIT | */
-/* INTF_NOTIFY | */
- 0;
-
- btc_dbg_type[BTC_MSG_ALGORITHM] =
-/* ALGO_BT_RSSI_STATE | */
-/* ALGO_WIFI_RSSI_STATE | */
-/* ALGO_BT_MONITOR | */
-/* ALGO_TRACE | */
-/* ALGO_TRACE_FW | */
-/* ALGO_TRACE_FW_DETAIL | */
-/* ALGO_TRACE_FW_EXEC | */
-/* ALGO_TRACE_SW | */
-/* ALGO_TRACE_SW_DETAIL | */
-/* ALGO_TRACE_SW_EXEC | */
- 0;
+ btc_dbg_type[BTC_MSG_INTERFACE] = 0;
+
+ btc_dbg_type[BTC_MSG_ALGORITHM] = 0;
}
static bool halbtc_is_bt40(struct rtl_priv *adapter)
@@ -142,7 +191,7 @@ static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist)
if (rtlphy->current_channel != 0)
chnl = rtlphy->current_channel;
BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
- "static halbtc_get_wifi_central_chnl:%d\n", chnl);
+ "halbtc_get_wifi_central_chnl:%d\n", chnl);
return chnl;
}
@@ -159,12 +208,14 @@ static void halbtc_leave_lps(struct btc_coexist *btcoexist)
&ap_enable);
if (ap_enable) {
- pr_info("halbtc_leave_lps()<--dont leave lps under AP mode\n");
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "halbtc_leave_lps()<--dont leave lps under AP mode\n");
return;
}
btcoexist->bt_info.bt_ctrl_lps = true;
btcoexist->bt_info.bt_lps_on = false;
+ rtl_lps_leave(rtlpriv->mac80211.hw);
}
static void halbtc_enter_lps(struct btc_coexist *btcoexist)
@@ -180,12 +231,14 @@ static void halbtc_enter_lps(struct btc_coexist *btcoexist)
&ap_enable);
if (ap_enable) {
- pr_info("halbtc_enter_lps()<--dont enter lps under AP mode\n");
+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+ "halbtc_enter_lps()<--dont enter lps under AP mode\n");
return;
}
btcoexist->bt_info.bt_ctrl_lps = true;
btcoexist->bt_info.bt_lps_on = false;
+ rtl_lps_enter(rtlpriv->mac80211.hw);
}
static void halbtc_normal_lps(struct btc_coexist *btcoexist)
@@ -194,27 +247,54 @@ static void halbtc_normal_lps(struct btc_coexist *btcoexist)
btcoexist->bt_info.bt_lps_on = false;
btcoexist->bt_info.bt_ctrl_lps = false;
}
-}
-static void halbtc_leave_low_power(void)
-{
}
-static void halbtc_nomal_low_power(void)
+static u32 halbtcoutsrc_get_wifi_link_status(struct btc_coexist *btcoexist)
{
-}
+ /*------------------------------------
+ * return value:
+ * [31:16]=> connected port number
+ * [15:0]=> port connected bit define
+ *------------------------------------
+ */
-static void halbtc_disable_low_power(void)
-{
-}
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+ u32 ret_val = 0;
+ u32 port_connected_status = 0, num_of_connected_port = 0;
-static void halbtc_aggregation_check(void)
-{
+ if (mac->opmode == NL80211_IFTYPE_STATION &&
+ mac->link_state >= MAC80211_LINKED) {
+ port_connected_status |= WIFI_STA_CONNECTED;
+ num_of_connected_port++;
+ }
+ /* AP & ADHOC & MESH */
+ if (is_any_client_connect_to_ap(btcoexist)) {
+ port_connected_status |= WIFI_AP_CONNECTED;
+ num_of_connected_port++;
+ }
+ /* TODO: * P2P Connected Status */
+
+ ret_val = (num_of_connected_port << 16) | port_connected_status;
+
+ return ret_val;
}
static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist)
{
- return 0;
+ u8 datalen = 2;
+ u8 buf[4] = {0};
+ u8 cnt = 0;
+
+ if (!btcoexist->bt_info.bt_real_fw_ver && cnt <= 5) {
+ buf[0] = 0x0; /* OP_Code*/
+ buf[1] = 0x0; /* OP_Code_Length*/
+ bt_sendeventextbtcoexcontrol(btcoexist->adapter, false,
+ datalen, &buf[0]);
+ cnt++;
+ }
+ return btcoexist->bt_info.bt_real_fw_ver;
}
static s32 halbtc_get_wifi_rssi(struct rtl_priv *adapter)
@@ -244,7 +324,6 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
if (!halbtc_is_bt_coexist_available(btcoexist))
return false;
-
switch (get_type) {
case BTC_GET_BL_HS_OPERATION:
*bool_tmp = false;
@@ -253,7 +332,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*bool_tmp = false;
break;
case BTC_GET_BL_WIFI_CONNECTED:
- if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
+ rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ tmp = true;
+ if (is_any_client_connect_to_ap(btcoexist))
tmp = true;
*bool_tmp = tmp;
break;
@@ -276,14 +358,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*bool_tmp = false;
break;
case BTC_GET_BL_WIFI_ROAM: /*TODO*/
- if (mac->link_state == MAC80211_LINKING)
- *bool_tmp = true;
- else
- *bool_tmp = false;
+ *bool_tmp = false;
break;
case BTC_GET_BL_WIFI_4_WAY_PROGRESS: /*TODO*/
- *bool_tmp = false;
-
+ *bool_tmp = false;
break;
case BTC_GET_BL_WIFI_UNDER_5G:
*bool_tmp = false; /*TODO*/
@@ -309,7 +387,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*bool_tmp = true;
break;
case BTC_GET_BL_WIFI_UNDER_B_MODE:
- *bool_tmp = false; /*TODO*/
+ if (WIRELESS_MODE_B == rtlpriv->mac80211.mode)
+ *bool_tmp = true;
+ else
+ *bool_tmp = false;
break;
case BTC_GET_BL_EXT_SWITCH:
*bool_tmp = false;
@@ -330,7 +411,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*u32_tmp = BTC_WIFI_TRAFFIC_RX;
break;
case BTC_GET_U4_WIFI_FW_VER:
- *u32_tmp = rtlhal->fw_version;
+ *u32_tmp = (rtlhal->fw_version << 16) | rtlhal->fw_subversion;
+ break;
+ case BTC_GET_U4_WIFI_LINK_STATUS:
+ *u32_tmp = halbtcoutsrc_get_wifi_link_status(btcoexist);
break;
case BTC_GET_U4_BT_PATCH_VER:
*u32_tmp = halbtc_get_bt_patch_version(btcoexist);
@@ -342,13 +426,19 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*u8_tmp = halbtc_get_wifi_central_chnl(btcoexist);
break;
case BTC_GET_U1_WIFI_HS_CHNL:
- *u8_tmp = 1;/*BT_OperateChnl(rtlpriv);*/
+ *u8_tmp = 1;/* BT_OperateChnl(rtlpriv); */
break;
case BTC_GET_U1_MAC_PHY_MODE:
*u8_tmp = BTC_MP_UNKNOWN;
break;
+ case BTC_GET_U1_AP_NUM:
+ /* driver don't know AP num in Linux,
+ * So, the return value here is not right
+ */
+ *u8_tmp = 1;/* pDefMgntInfo->NumBssDesc4Query; */
+ break;
- /************* 1Ant **************/
+ /************* 1Ant **************/
case BTC_GET_U1_LPS_MODE:
*u8_tmp = btcoexist->pwr_mode_val[0];
break;
@@ -366,6 +456,7 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
bool *bool_tmp = (bool *)in_buf;
u8 *u8_tmp = (u8 *)in_buf;
u32 *u32_tmp = (u32 *)in_buf;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
if (!halbtc_is_bt_coexist_available(btcoexist))
return false;
@@ -405,20 +496,16 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
/*BTHCI_SendGetBtRssiEvent(rtlpriv);*/
break;
case BTC_SET_ACT_AGGREGATE_CTRL:
- halbtc_aggregation_check();
break;
/* 1Ant */
case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE:
btcoexist->bt_info.rssi_adjust_for_1ant_coex_type = *u8_tmp;
break;
- case BTC_SET_UI_SCAN_SIG_COMPENSATION:
- /* rtlpriv->mlmepriv.scan_compensation = *u8_tmp; */
- break;
- case BTC_SET_U1_1ANT_LPS:
+ case BTC_SET_U1_LPS_VAL:
btcoexist->bt_info.lps_val = *u8_tmp;
break;
- case BTC_SET_U1_1ANT_RPWM:
+ case BTC_SET_U1_RPWM_VAL:
btcoexist->bt_info.rpwm_val = *u8_tmp;
break;
/* the following are some action which will be triggered */
@@ -432,7 +519,6 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
halbtc_normal_lps(btcoexist);
break;
case BTC_SET_ACT_DISABLE_LOW_POWER:
- halbtc_disable_low_power();
break;
case BTC_SET_ACT_UPDATE_ra_mask:
btcoexist->bt_info.ra_mask = *u32_tmp;
@@ -442,9 +528,29 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
case BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT:
btcoexist->bt_info.force_exec_pwr_cmd_cnt++;
break;
- case BTC_SET_ACT_CTRL_BT_INFO: /*wait for 8812/8821*/
+ /*8812 only*/
+ case BTC_SET_ACT_CTRL_BT_INFO:
+ {
+ u8 datalen = *u8_tmp;
+ u8 tmpbuf[20];
+
+ if (datalen)
+ memcpy(tmpbuf, u8_tmp+1, datalen);
+ bt_sendeventextbtinfocontrol(rtlpriv, datalen,
+ &tmpbuf[0]);
+ }
break;
+ /*8812 only*/
case BTC_SET_ACT_CTRL_BT_COEX:
+ {
+ u8 datalen = *u8_tmp;
+ u8 tmpbuf[20];
+
+ if (datalen)
+ memcpy(tmpbuf, u8_tmp+1, datalen);
+ bt_sendeventextbtcoexcontrol(rtlpriv, false, datalen,
+ &tmpbuf[0]);
+ }
break;
default:
break;
@@ -453,22 +559,6 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
return true;
}
-static void halbtc_display_coex_statistics(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_bt_link_info(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_bt_fw_info(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_fw_pwr_mode_cmd(struct btc_coexist *btcoexist)
-{
-}
-
/************************************************************
* IO related function
************************************************************/
@@ -512,10 +602,10 @@ static void halbtc_bitmask_write_1byte(void *bt_context, u32 reg_addr,
u8 original_value, bit_shift = 0;
u8 i;
- if (bit_mask != MASKDWORD) {/*if not "double word" write*/
+ if (bit_mask != MASKBYTE0) {/*if not "byte" write*/
original_value = rtl_read_byte(rtlpriv, reg_addr);
for (i = 0; i <= 7; i++) {
- if ((bit_mask>>i) & 0x1)
+ if ((bit_mask>>i)&0x1)
break;
}
bit_shift = i;
@@ -560,7 +650,7 @@ static u32 halbtc_get_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask)
}
static void halbtc_set_rfreg(void *bt_context, u8 rf_path, u32 reg_addr,
- u32 bit_mask, u32 data)
+ u32 bit_mask, u32 data)
{
struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context;
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -578,7 +668,7 @@ static u32 halbtc_get_rfreg(void *bt_context, u8 rf_path, u32 reg_addr,
}
static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id,
- u32 cmd_len, u8 *cmd_buf)
+ u32 cmd_len, u8 *cmd_buf)
{
struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context;
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -589,23 +679,22 @@ static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id,
static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type)
{
- struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context;
- switch (disp_type) {
- case BTC_DBG_DISP_COEX_STATISTICS:
- halbtc_display_coex_statistics(btcoexist);
- break;
- case BTC_DBG_DISP_BT_LINK_INFO:
- halbtc_display_bt_link_info(btcoexist);
- break;
- case BTC_DBG_DISP_BT_FW_VER:
- halbtc_display_bt_fw_info(btcoexist);
- break;
- case BTC_DBG_DISP_FW_PWR_MODE_CMD:
- halbtc_display_fw_pwr_mode_cmd(btcoexist);
- break;
- default:
- break;
+}
+
+static bool halbtc_under_ips(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ enum rf_pwrstate rtstate;
+
+ if (ppsc->inactiveps) {
+ rtstate = ppsc->rfpwr_state;
+
+ if (rtstate != ERFON &&
+ ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+ return true;
}
+ return false;
}
/*****************************************************************
@@ -624,7 +713,7 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
else
btcoexist->binded = true;
- btcoexist->chip_interface = BTC_INTF_UNKNOWN;
+ btcoexist->chip_interface = BTC_INTF_PCI;
if (NULL == btcoexist->adapter)
btcoexist->adapter = adapter;
@@ -668,8 +757,25 @@ void exhalbtc_init_hw_config(struct btc_coexist *btcoexist)
btcoexist->statistics.cnt_init_hw_config++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_init_hwconfig(btcoexist);
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_init_hwconfig(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_init_hwconfig(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_init_hwconfig(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_init_hwconfig(btcoexist);
+ }
+
}
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist)
@@ -682,8 +788,24 @@ void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist)
btcoexist->statistics.cnt_init_coex_dm++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_init_coex_dm(btcoexist);
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_init_coex_dm(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_init_coex_dm(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_init_coex_dm(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_init_coex_dm(btcoexist);
+ }
btcoexist->initilized = true;
}
@@ -705,12 +827,24 @@ void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type)
else
ips_type = BTC_IPS_LEAVE;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_ips_notify(btcoexist, ips_type);
-
- halbtc_nomal_low_power();
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_ips_notify(btcoexist, ips_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_ips_notify(btcoexist, ips_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_ips_notify(btcoexist, ips_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_ips_notify(btcoexist, ips_type);
+ }
}
void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type)
@@ -730,8 +864,24 @@ void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type)
else
lps_type = BTC_LPS_ENABLE;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_lps_notify(btcoexist, lps_type);
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_lps_notify(btcoexist, lps_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_lps_notify(btcoexist, lps_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_lps_notify(btcoexist, lps_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_lps_notify(btcoexist, lps_type);
+ }
}
void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
@@ -751,12 +901,24 @@ void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
else
scan_type = BTC_SCAN_FINISH;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_scan_notify(btcoexist, scan_type);
-
- halbtc_nomal_low_power();
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_scan_notify(btcoexist, scan_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_scan_notify(btcoexist, scan_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_scan_notify(btcoexist, scan_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_scan_notify(btcoexist, scan_type);
+ }
}
void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
@@ -776,15 +938,31 @@ void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
else
asso_type = BTC_ASSOCIATE_FINISH;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_connect_notify(btcoexist, asso_type);
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_connect_notify(btcoexist, asso_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_connect_notify(btcoexist, asso_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_connect_notify(btcoexist, asso_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_connect_notify(btcoexist, asso_type);
+ }
}
void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
enum rt_media_status media_status)
{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 status;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -798,9 +976,30 @@ void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
else
status = BTC_MEDIA_DISCONNECT;
- halbtc_leave_low_power();
-
- halbtc_nomal_low_power();
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_media_status_notify(btcoexist,
+ status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_media_status_notify(btcoexist,
+ status);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_media_status_notify(btcoexist, status);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_media_status_notify(btcoexist,
+ status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_media_status_notify(btcoexist,
+ status);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8812a2ant_media_stat_notify(btcoexist,
+ status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8812a1ant_media_stat_notify(btcoexist,
+ status);
+ }
}
void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type)
@@ -815,15 +1014,39 @@ void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type)
if (btcoexist->manual_control)
return;
- packet_type = BTC_PACKET_DHCP;
-
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_special_packet_notify(btcoexist,
- packet_type);
+ if (PACKET_DHCP == pkt_type) {
+ packet_type = BTC_PACKET_DHCP;
+ } else if (PACKET_EAPOL == pkt_type) {
+ packet_type = BTC_PACKET_EAPOL;
+ } else if (PACKET_ARP == pkt_type) {
+ packet_type = BTC_PACKET_ARP;
+ } else {
+ packet_type = BTC_PACKET_UNKNOWN;
+ return;
+ }
- halbtc_nomal_low_power();
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_special_packet_notify(btcoexist,
+ packet_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_special_packet_notify(btcoexist,
+ packet_type);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_special_packet_notify(btcoexist,
+ packet_type);
+ }
}
void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist,
@@ -835,8 +1058,31 @@ void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist,
return;
btcoexist->statistics.cnt_bt_info_notify++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf, length);
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ }
}
void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
@@ -849,11 +1095,18 @@ void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
if (btcoexist->manual_control)
return;
- stack_op_type = BTC_STACK_OP_NONE;
-
- halbtc_leave_low_power();
+ if ((HCI_BT_OP_INQUIRY_START == type) ||
+ (HCI_BT_OP_PAGING_START == type) ||
+ (HCI_BT_OP_PAIRING_START == type))
+ stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_START;
+ else if ((HCI_BT_OP_INQUIRY_FINISH == type) ||
+ (HCI_BT_OP_PAGING_SUCCESS == type) ||
+ (HCI_BT_OP_PAGING_UNSUCCESS == type) ||
+ (HCI_BT_OP_PAIRING_FINISH == type))
+ stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_FINISH;
+ else
+ stack_op_type = BTC_STACK_OP_NONE;
- halbtc_nomal_low_power();
}
void exhalbtc_halt_notify(struct btc_coexist *btcoexist)
@@ -863,42 +1116,168 @@ void exhalbtc_halt_notify(struct btc_coexist *btcoexist)
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_halt_notify(btcoexist);
+ btcoexist->binded = false;
+
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_halt_notify(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_halt_notify(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_halt_notify(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_halt_notify(btcoexist);
+ }
}
void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
+
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_pnp_notify(btcoexist, pnp_state);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_pnp_notify(btcoexist, pnp_state);
+ }
}
-void exhalbtc_periodical(struct btc_coexist *btcoexist)
+void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- btcoexist->statistics.cnt_periodical++;
+ btcoexist->statistics.cnt_coex_dm_switch++;
+
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 1) {
+ btcoexist->stop_coex_dm = true;
+ ex_halbtc8723b1ant_coex_dm_reset(btcoexist);
+ exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_DETECTED, 2);
+ ex_btc8723b2ant_init_hwconfig(btcoexist);
+ ex_btc8723b2ant_init_coex_dm(btcoexist);
+ btcoexist->stop_coex_dm = false;
+ }
+ }
+}
- halbtc_leave_low_power();
+void exhalbtc_periodical(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_periodical(btcoexist);
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+ btcoexist->statistics.cnt_periodical++;
- halbtc_nomal_low_power();
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_periodical(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_periodical(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) {
+ ex_halbtc8192e2ant_periodical(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2) {
+ ex_halbtc8821a2ant_periodical(btcoexist);
+ } else if (btcoexist->board_info.btdm_ant_num == 1) {
+ if (!halbtc_under_ips(btcoexist))
+ ex_halbtc8821a1ant_periodical(btcoexist);
+ }
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_periodical(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_periodical(btcoexist);
+ }
}
void exhalbtc_dbg_control(struct btc_coexist *btcoexist,
u8 code, u8 len, u8 *data)
{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_dbg_ctrl++;
+
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a1ant_dbg_control(btcoexist, code,
+ len, data);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_dbg_control(btcoexist, code,
+ len, data);
+ }
}
void exhalbtc_stack_update_profile_info(void)
{
+ struct btc_coexist *btcoexist = &gl_bt_coexist;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct bt_mgnt *btmgnt = &rtlpriv->coex_info.btmgnt;
+ u8 i;
+
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ btcoexist->stack_info.profile_notified = true;
+
+ btcoexist->stack_info.num_of_link =
+ btmgnt->ext_config.number_of_acl +
+ btmgnt->ext_config.number_of_sco;
+
+ /* reset first*/
+ btcoexist->stack_info.bt_link_exist = false;
+ btcoexist->stack_info.sco_exist = false;
+ btcoexist->stack_info.acl_exist = false;
+ btcoexist->stack_info.a2dp_exist = false;
+ btcoexist->stack_info.hid_exist = false;
+ btcoexist->stack_info.num_of_hid = 0;
+ btcoexist->stack_info.pan_exist = false;
+
+ if (!btmgnt->ext_config.number_of_acl)
+ btcoexist->stack_info.min_bt_rssi = 0;
+
+ if (btcoexist->stack_info.num_of_link) {
+ btcoexist->stack_info.bt_link_exist = true;
+ if (btmgnt->ext_config.number_of_sco)
+ btcoexist->stack_info.sco_exist = true;
+ if (btmgnt->ext_config.number_of_acl)
+ btcoexist->stack_info.acl_exist = true;
+ }
+
+ for (i = 0; i < btmgnt->ext_config.number_of_acl; i++) {
+ if (BT_PROFILE_A2DP ==
+ btmgnt->ext_config.acl_link[i].bt_profile) {
+ btcoexist->stack_info.a2dp_exist = true;
+ } else if (BT_PROFILE_PAN ==
+ btmgnt->ext_config.acl_link[i].bt_profile) {
+ btcoexist->stack_info.pan_exist = true;
+ } else if (BT_PROFILE_HID ==
+ btmgnt->ext_config.acl_link[i].bt_profile) {
+ btcoexist->stack_info.hid_exist = true;
+ btcoexist->stack_info.num_of_hid++;
+ } else {
+ btcoexist->stack_info.unknown_acl_exist = true;
+ }
+ }
}
void exhalbtc_update_min_bt_rssi(char bt_rssi)
@@ -970,8 +1349,29 @@ void exhalbtc_set_ant_num(u8 type, u8 ant_num)
if (BT_COEX_ANT_TYPE_PG == type) {
gl_bt_coexist.board_info.pg_ant_num = ant_num;
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+ /* The antenna position:
+ * Main (default) or Aux for pgAntNum =2 && btdmAntNum =1.
+ * The antenna position should be determined by
+ * auto-detect mechanism.
+ * The following is assumed to main,
+ * and those must be modified
+ * if y auto-detect mechanism is ready
+ */
+ if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
+ (gl_bt_coexist.board_info.btdm_ant_num == 1))
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
+ else
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
} else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
+ } else if (BT_COEX_ANT_TYPE_DETECTED == type) {
+ gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
}
}
@@ -979,9 +1379,26 @@ void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_display_coex_info(btcoexist);
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8723b1ant_display_coex_info(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8821a2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8821a1ant_display_coex_info(btcoexist);
+ } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_halbtc8812a2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_halbtc8812a1ant_display_coex_info(btcoexist);
+ }
}
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
index 8c64acf..5bf7060 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -88,6 +88,7 @@ enum btc_chip_type {
enum btc_msg_type {
BTC_MSG_INTERFACE = 0x0,
BTC_MSG_ALGORITHM = 0x1,
+ BTC_MSG_SOCKET = 0x2,
BTC_MSG_MAX
};
@@ -97,6 +98,11 @@ extern u32 btc_dbg_type[];
#define INTF_INIT BIT0
#define INTF_NOTIFY BIT2
+/* following is for BTC_MSG_SOCKET */
+#define SOCKET_INIT BIT0
+#define SOCKET_CRITICAL BIT1
+#define SOCKET_NORMAL BIT2
+
/* following is for BTC_ALGORITHM */
#define ALGO_BT_RSSI_STATE BIT0
#define ALGO_WIFI_RSSI_STATE BIT1
@@ -508,4 +514,22 @@ void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
void exhalbtc_lps_leave(struct btc_coexist *btcoexist);
void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist);
+/**************for 8812AE BTCOEX**************/
+#define bt_sendeventextbtcoexcontrol(adap, needdbgrsp, datalen, data) \
+ rtl_btcoex_sendeventextbtcoexcontrol(adap, needdbgrsp, datalen, data)
+#define bt_sendeventextbtinfocontrol(adapter, datalen, pdata) \
+ rtl_btcoex_sendeventextbtinfocontrol(adapter, datalen, pdata)
+void rtl_btcoex_sendeventextbtcoexcontrol(struct rtl_priv *rtlpriv,
+ u8 needdbgrsp, u8 datalen,
+ void *pdata);
+void rtl_btcoex_sendeventextbtinfocontrol(struct rtl_priv *rtlpriv, u8 datalen,
+ void *pdata);
+
+void rtl_btcoex_dump_tx_msg(u8 *tx_msg, u8 len, u8 *msg_name);
+u8 rtl_btcoex_sendmsgbysocket(struct rtl_priv *rtlpriv, u8 *msg, u8 msg_size,
+ bool force);
+void rtl_btcoex_sendscannotify(struct rtl_priv *rtlpriv, u8 scantype);
+void rtl_btcoex_init_socket(struct rtl_priv *rtlpriv);
+void rtl_btcoex_close_socket(struct rtl_priv *rtlpriv);
+
#endif
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c
index b9b0cb7..a75b663 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c
@@ -45,8 +45,23 @@ static struct rtl_btc_ops rtl_btc_operation = {
.btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
.btc_is_bt_disabled = rtl_btc_is_bt_disabled,
.btc_special_packet_notify = rtl_btc_special_packet_notify,
+ .btc_set_hci_version = rtl_btc_set_hci_version,
+ .btc_set_bt_patch_version = rtl_btc_set_bt_patch_version,
+ .btc_stack_update_profile_info = rtl_btc_stack_update_profile_info,
+ .btc_init_socket = rtl_btc_init_socket,
+ .btc_close_socket = rtl_btc_close_socket,
};
+void rtl_btc_init_socket(struct rtl_priv *rtlpriv)
+{
+ rtl_btcoex_init_socket(rtlpriv);
+}
+
+void rtl_btc_close_socket(struct rtl_priv *rtlpriv)
+{
+ rtl_btcoex_close_socket(rtlpriv);
+}
+
void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
{
exhalbtc_initlize_variables(rtlpriv);
@@ -75,6 +90,21 @@ void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num);
}
+void rtl_btc_stack_update_profile_info(void)
+{
+ exhalbtc_stack_update_profile_info();
+}
+
+void rtl_btc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version)
+{
+ exhalbtc_set_bt_patch_version(bt_hci_version, bt_patch_version);
+}
+
+void rtl_btc_set_hci_version(u16 hci_version)
+{
+ exhalbtc_set_hci_version(hci_version);
+}
+
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
{
exhalbtc_init_hw_config(&gl_bt_coexist);
@@ -93,6 +123,13 @@ void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
{
+ /*for 8812AE+8761AU*/
+ struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
+ struct bt_mgnt *btmgnt = &pcoex_info->btmgnt;
+
+ if (btmgnt->ext_config.enable_wifi_scan_notify)
+ rtl_btcoex_sendscannotify(rtlpriv, scantype);
+
exhalbtc_scan_notify(&gl_bt_coexist, scantype);
}
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h
index ccd5a0f..47b9837 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h
@@ -43,7 +43,11 @@ bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv);
bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv);
bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv);
void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type);
-
+void rtl_btc_set_hci_version(u16 hci_version);
+void rtl_btc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version);
+void rtl_btc_stack_update_profile_info(void);
+void rtl_btc_init_socket(struct rtl_priv *rtlpriv);
+void rtl_btc_close_socket(struct rtl_priv *rtlpriv);
struct rtl_btc_ops *rtl_btc_get_ops_pointer(void);
u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv);
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 3c8d504..9d72911 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -164,8 +164,17 @@ static int rtl_op_start(struct ieee80211_hw *hw)
return 0;
mutex_lock(&rtlpriv->locks.conf_mutex);
err = rtlpriv->intf_ops->adapter_start(hw);
- if (!err)
+ if (!err) {
+ /*add troy for 8812AE bt coex*/
+ if (1 == rtlpriv->btcoexist.btc_info.btcoexist &&
+ rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ pr_info("now that bt exists, init socket for 8812AE");
+ rtlpriv->btcoexist.btc_ops->btc_init_socket(rtlpriv);
+ rtlpriv->coex_info.btmgnt.ext_config.hci_ext_ver = 0x04;
+ rtlpriv->btcoexist.btc_ops->btc_set_hci_version(0x04);
+ }
rtl_watch_dog_timer_callback((unsigned long)hw);
+ }
mutex_unlock(&rtlpriv->locks.conf_mutex);
return err;
}
@@ -205,6 +214,12 @@ static void rtl_op_stop(struct ieee80211_hw *hw)
}
rtlpriv->intf_ops->adapter_stop(hw);
+ if (1 == rtlpriv->btcoexist.btc_info.btcoexist &&
+ rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ pr_info("close socket for 8812AE + 8761AU\n");
+ /*troy add for 8812 btcoex*/
+ rtlpriv->btcoexist.btc_ops->btc_close_socket(rtlpriv);
+ }
mutex_unlock(&rtlpriv->locks.conf_mutex);
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
index 3723d74..56936da 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
@@ -70,20 +70,6 @@
#define C2H_EVT_HOST_CLOSE 0x00
#define C2H_EVT_FW_CLOSE 0xFF
-enum bt_traffic_mode {
- BT_MOTOR_EXT_BE = 0x00,
- BT_MOTOR_EXT_GUL = 0x01,
- BT_MOTOR_EXT_GUB = 0x02,
- BT_MOTOR_EXT_GULB = 0x03
-};
-
-enum bt_traffic_mode_profile {
- BT_PROFILE_NONE,
- BT_PROFILE_A2DP,
- BT_PROFILE_PAN,
- BT_PROFILE_HID,
- BT_PROFILE_SCO
-};
/*
enum hci_ext_bt_operation {
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 413c2ab..8d1a02c 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -36,7 +36,7 @@
#include <net/mac80211.h>
#include <linux/completion.h>
#include "debug.h"
-
+#include "btcoexist/halbtc8812a_ext.h"
#define MASKBYTE0 0xff
#define MASKBYTE1 0xff00
#define MASKBYTE2 0xff0000
@@ -2311,6 +2311,7 @@ struct rtl_works {
struct workqueue_struct *rtl_wq;
struct delayed_work watchdog_wq;
struct delayed_work ips_nic_off_wq;
+ struct delayed_work socket_wq;
/* For SW LPS */
struct delayed_work ps_work;
@@ -2516,6 +2517,12 @@ struct rtl_btc_ops {
bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv);
void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv,
u8 pkt_type);
+ void (*btc_set_hci_version)(u16 hci_version);
+ void (*btc_set_bt_patch_version)(u16 bt_hci_version,
+ u16 bt_patch_version);
+ void (*btc_stack_update_profile_info)(void);
+ void (*btc_init_socket)(struct rtl_priv *rtlpriv);
+ void (*btc_close_socket)(struct rtl_priv *rtlpriv);
};
struct proxim {
@@ -2547,6 +2554,9 @@ struct rtl_priv {
struct rtl_security sec;
struct rtl_efuse efuse;
+ /*troy add for 8812AE+8761AU coex*/
+ struct bt_coex_info coex_info;
+
struct rtl_ps_ctl psc;
struct rate_adaptive ra;
struct dynamic_primary_cca primarycca;
--
2.1.2
^ permalink raw reply related
* Re: [PATCH net-next] sunvnet: improve error handling when a remote crashes
From: David L Stevens @ 2015-01-26 20:53 UTC (permalink / raw)
To: sowmini.varadhan; +Cc: David Miller, netdev
In-Reply-To: <54C6A3BA.3060004@oracle.com>
On 01/26/2015 03:29 PM, Sowmini Varadhan wrote:
>> It should only happen if there is active traffic when a remote
>> crashes, but if a remote is giving us garbage in other cases, I think an
>> admin would want to check that out.
>
> This allows one DomU to spam up everyone else's log file by crashing
> periodically.
>
> In any case, the contents of the message do not in any way suggest
> that an admin (of the DomU, who probably has no control over
> other DomU's anyway) should go and baby-sit some other DomU that
> just crashed.
I demoted it to a notice and we can change it to a counter when we add
stats. This way it's clear that it's an unexpected state and it's easy
to see them when we want them.
+-DLS
^ permalink raw reply
* [PATCH 0/2 net-next] sunvnet: fix null pointer deref and crash recovery
From: David L Stevens @ 2015-01-26 20:54 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Sowmini Varadhan
These patches fix an incorrect ordering in releasing ring data, clear pending
tx buffers on a reset, and make the sunvnet driver more reliable when remote
systems crash during active transmits.
David L Stevens (2):
sunvnet: free pending tx buffers before clearing ring data
sunvnet: improve error handling when a remote crashes
drivers/net/ethernet/sun/sunvnet.c | 83 +++++++++++++++++++----------------
1 files changed, 45 insertions(+), 38 deletions(-)
^ permalink raw reply
* [PATCH 2/2 net-next] sunvnet: improve error handling when a remote crashes
From: David L Stevens @ 2015-01-26 20:54 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Sowmini Varadhan
If a remote machine crashes while there are pending transmit buffers, the
sunvnet driver reallocates the ring descriptors giving us enries that have
state VIO_DESC_FREE but also an allocated skb. This results in a BUG_ON()
call when the remote reboots and we reach that point in the ring.
This patch:
1) clears pending tx packets in the ring on port reset
2) changes a BUG_ON() to a pr_warn() when a remote host has given us an invalid
descriptor state
3) collapses multiple active buffer frees in a ring to a single message per
ring and adds the device name and remote MAC address
This fixes the particular problem of not cleaning up pending buffers on a
reset, but also prevents us from crashing if the remote handles descriptors
out of order or sets an unexpected state for a descriptor.
Signed-off-by: David L Stevens <david.stevens@oracle.com>
---
drivers/net/ethernet/sun/sunvnet.c | 62 +++++++++++++++++++----------------
1 files changed, 34 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index fe044f3..2b719cc 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -50,6 +50,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
#define VNET_MAX_RETRIES 10
static int __vnet_tx_trigger(struct vnet_port *port, u32 start);
+static void vnet_port_reset(struct vnet_port *port);
/* Ordered from largest major to lowest */
static struct vio_version vnet_versions[] = {
@@ -736,9 +737,7 @@ ldc_ctrl:
vio_link_state_change(vio, event);
if (event == LDC_EVENT_RESET) {
- port->rmtu = 0;
- port->tso = true;
- port->tsolen = 0;
+ vnet_port_reset(port);
vio_port_up(vio);
}
port->rx_event = 0;
@@ -934,36 +933,36 @@ static struct sk_buff *vnet_clean_tx_ring(struct vnet_port *port,
*pending = 0;
- txi = dr->prod-1;
- if (txi < 0)
- txi = VNET_TX_RING_SIZE-1;
-
+ txi = dr->prod;
for (i = 0; i < VNET_TX_RING_SIZE; ++i) {
struct vio_net_desc *d;
- d = vio_dring_entry(dr, txi);
-
- if (d->hdr.state == VIO_DESC_DONE) {
- if (port->tx_bufs[txi].skb) {
- BUG_ON(port->tx_bufs[txi].skb->next);
+ --txi;
+ if (txi < 0)
+ txi = VNET_TX_RING_SIZE-1;
- port->tx_bufs[txi].skb->next = skb;
- skb = port->tx_bufs[txi].skb;
- port->tx_bufs[txi].skb = NULL;
+ d = vio_dring_entry(dr, txi);
- ldc_unmap(port->vio.lp,
- port->tx_bufs[txi].cookies,
- port->tx_bufs[txi].ncookies);
- }
- d->hdr.state = VIO_DESC_FREE;
- } else if (d->hdr.state == VIO_DESC_READY) {
+ if (d->hdr.state == VIO_DESC_READY) {
(*pending)++;
- } else if (d->hdr.state == VIO_DESC_FREE) {
- break;
+ continue;
}
- --txi;
- if (txi < 0)
- txi = VNET_TX_RING_SIZE-1;
+ if (port->tx_bufs[txi].skb) {
+ if (d->hdr.state != VIO_DESC_DONE)
+ pr_notice("invalid ring buffer state %d\n",
+ d->hdr.state);
+ BUG_ON(port->tx_bufs[txi].skb->next);
+
+ port->tx_bufs[txi].skb->next = skb;
+ skb = port->tx_bufs[txi].skb;
+ port->tx_bufs[txi].skb = NULL;
+
+ ldc_unmap(port->vio.lp,
+ port->tx_bufs[txi].cookies,
+ port->tx_bufs[txi].ncookies);
+ } else if (d->hdr.state == VIO_DESC_FREE)
+ break;
+ d->hdr.state = VIO_DESC_FREE;
}
return skb;
}
@@ -1649,8 +1648,6 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
continue;
d = vio_dring_entry(dr, i);
- if (d->hdr.state == VIO_DESC_READY)
- pr_warn("active transmit buffers freed\n");
ldc_unmap(port->vio.lp,
port->tx_bufs[i].cookies,
@@ -1669,6 +1666,15 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
dr->ncookies = 0;
}
+static void vnet_port_reset(struct vnet_port *port)
+{
+ del_timer(&port->clean_timer);
+ vnet_port_free_tx_bufs(port);
+ port->rmtu = 0;
+ port->tso = true;
+ port->tsolen = 0;
+}
+
static int vnet_port_alloc_tx_ring(struct vnet_port *port)
{
struct vio_dring_state *dr;
--
1.7.1
^ permalink raw reply related
* [PATCH 1/2 net-next] sunvnet: free pending tx buffers before clearing ring data
From: David L Stevens @ 2015-01-26 20:54 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Sowmini Varadhan
This patch moves the clearing of ring data in vnet_port_free_tx_bufs to after
the freeing of pending buffers in the ring. Otherwise, this can result in
dereferencing a NULL pointer.
Reported-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David L Stevens <david.stevens@oracle.com>
---
drivers/net/ethernet/sun/sunvnet.c | 21 +++++++++++----------
1 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index b5a1d3d..fe044f3 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -1637,16 +1637,9 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
int i;
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
- if (dr->base) {
- ldc_free_exp_dring(port->vio.lp, dr->base,
- (dr->entry_size * dr->num_entries),
- dr->cookies, dr->ncookies);
- dr->base = NULL;
- dr->entry_size = 0;
- dr->num_entries = 0;
- dr->pending = 0;
- dr->ncookies = 0;
- }
+
+ if (dr->base == NULL)
+ return;
for (i = 0; i < VNET_TX_RING_SIZE; i++) {
struct vio_net_desc *d;
@@ -1666,6 +1659,14 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
port->tx_bufs[i].skb = NULL;
d->hdr.state = VIO_DESC_FREE;
}
+ ldc_free_exp_dring(port->vio.lp, dr->base,
+ (dr->entry_size * dr->num_entries),
+ dr->cookies, dr->ncookies);
+ dr->base = NULL;
+ dr->entry_size = 0;
+ dr->num_entries = 0;
+ dr->pending = 0;
+ dr->ncookies = 0;
}
static int vnet_port_alloc_tx_ring(struct vnet_port *port)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] drivers: net: xgene: fix: Out of order descriptor bytes read
From: Iyappan Subramanian @ 2015-01-26 21:12 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, netdev, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, mlangsdo, patches,
Keyur Chudgar
In-Reply-To: <1421967050.3471.14.camel@edumazet-glaptop2.roam.corp.google.com>
On Thu, Jan 22, 2015 at 2:50 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Thu, 2015-01-22 at 12:03 -0800, Iyappan Subramanian wrote:
>> This patch fixes the following kernel crash,
>>
>> WARNING: CPU: 2 PID: 0 at net/ipv4/tcp_input.c:3079 tcp_clean_rtx_queue+0x658/0x80c()
>> Call trace:
>
>>
>> Software writes poison data into the descriptor bytes[15:8] and upon
>> receiving the interrupt, if those bytes are overwritten by the hardware with
>> the valid data, software also reads bytes[7:0] and executes receive/tx
>> completion logic.
>>
>> If the CPU executes the above two reads in out of order fashion, then the
>> bytes[7:0] will have older data and causing the kernel panic. We have to
>> force the order of the reads and thus this patch introduces read memory
>> barrier between these reads.
>>
>> Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
>> Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
>> Tested-by: Mark Langsdorf <mlangsdo@redhat.com>
>> ---
>> drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
>> index 83a5028..3622cdb 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
>> @@ -369,6 +369,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
>> if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
>> break;
>>
>> + /* read fpqnum field after dataaddr field */
>> + smp_rmb();
>> if (is_rx_desc(raw_desc))
>> ret = xgene_enet_rx_frame(ring, raw_desc);
>> else
>
> Reading your changelog, it looks like you need a plain rmb() here.
rmb() translates into dsb, which in arm64 serializes everything
including instructions and thus expensive compared to dmb.
Do you see any issue with smp_rmb() (which translates into dmb) ?
>
>
>
^ permalink raw reply
* Re: [PATCH] drivers: net: xgene: fix: Out of order descriptor bytes read
From: Eric Dumazet @ 2015-01-26 21:27 UTC (permalink / raw)
To: Iyappan Subramanian
Cc: David Miller, netdev, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, mlangsdo, patches,
Keyur Chudgar
In-Reply-To: <CAKh23FmxvV82mVrHq5jv-FE+e6u6CkW+xL_a2_ULAQgP_mM2VA@mail.gmail.com>
On Mon, 2015-01-26 at 13:12 -0800, Iyappan Subramanian wrote:
> On Thu, Jan 22, 2015 at 2:50 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > On Thu, 2015-01-22 at 12:03 -0800, Iyappan Subramanian wrote:
> >> This patch fixes the following kernel crash,
> >>
> >> WARNING: CPU: 2 PID: 0 at net/ipv4/tcp_input.c:3079 tcp_clean_rtx_queue+0x658/0x80c()
> >> Call trace:
> >
> >>
> >> Software writes poison data into the descriptor bytes[15:8] and upon
> >> receiving the interrupt, if those bytes are overwritten by the hardware with
> >> the valid data, software also reads bytes[7:0] and executes receive/tx
> >> completion logic.
> >>
> >> If the CPU executes the above two reads in out of order fashion, then the
> >> bytes[7:0] will have older data and causing the kernel panic. We have to
> >> force the order of the reads and thus this patch introduces read memory
> >> barrier between these reads.
> >>
> >> Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
> >> Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
> >> Tested-by: Mark Langsdorf <mlangsdo@redhat.com>
> >> ---
> >> drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 2 ++
> >> 1 file changed, 2 insertions(+)
> >>
> >> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> >> index 83a5028..3622cdb 100644
> >> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> >> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> >> @@ -369,6 +369,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
> >> if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
> >> break;
> >>
> >> + /* read fpqnum field after dataaddr field */
> >> + smp_rmb();
> >> if (is_rx_desc(raw_desc))
> >> ret = xgene_enet_rx_frame(ring, raw_desc);
> >> else
> >
> > Reading your changelog, it looks like you need a plain rmb() here.
>
> rmb() translates into dsb, which in arm64 serializes everything
> including instructions and thus expensive compared to dmb.
>
> Do you see any issue with smp_rmb() (which translates into dmb) ?
What happens if you compile a kernel with CONFIG_SMP=n ?
Most drivers in drivers/net use rmb() in this case, not smp_rmb() or
barrier()
^ permalink raw reply
* [PATCH net 1/2] caif: remove wrong dev_net_set() call
From: Nicolas Dichtel @ 2015-01-26 21:28 UTC (permalink / raw)
To: netdev
Cc: davem, dmitry.tarnyagin, arvid.brodin, alex.aring, linux-wpan,
Nicolas Dichtel, Sjur Brændeland
In-Reply-To: <1422307694-10079-1-git-send-email-nicolas.dichtel@6wind.com>
src_net points to the netns where the netlink message has been received. This
netns may be different from the netns where the interface is created (because
the user may add IFLA_NET_NS_[PID|FD]). In this case, src_net is the link netns.
It seems wrong to override the netns in the newlink() handler because if it
was not already src_net, it means that the user explicitly asks to create the
netdevice in another netns.
CC: Sjur Brændeland <sjur.brandeland@stericsson.com>
CC: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
Fixes: 8391c4aab1aa ("caif: Bugfixes in CAIF netdevice for close and flow control")
Fixes: c41254006377 ("caif-hsi: Add rtnl support")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
drivers/net/caif/caif_hsi.c | 1 -
net/caif/chnl_net.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
index 5e40a8b68cbe..b3b922adc0e4 100644
--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@ -1415,7 +1415,6 @@ static int caif_hsi_newlink(struct net *src_net, struct net_device *dev,
cfhsi = netdev_priv(dev);
cfhsi_netlink_parms(data, cfhsi);
- dev_net_set(cfhsi->ndev, src_net);
get_ops = symbol_get(cfhsi_get_ops);
if (!get_ops) {
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 4589ff67bfa9..67a4a36febd1 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -470,7 +470,6 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
ASSERT_RTNL();
caifdev = netdev_priv(dev);
caif_netlink_parms(data, &caifdev->conn_req);
- dev_net_set(caifdev->netdev, src_net);
ret = register_netdevice(dev);
if (ret)
--
2.2.2
^ permalink raw reply related
* [PATCH net 0/2] netns: audit netdevice creation with IFLA_NET_NS_[PID|FD]
From: Nicolas Dichtel @ 2015-01-26 21:28 UTC (permalink / raw)
To: netdev; +Cc: davem, dmitry.tarnyagin, arvid.brodin, alex.aring, linux-wpan
When one of these attributes is set, the netdevice is created into the netns
pointed by IFLA_NET_NS_[PID|FD] (see the call to rtnl_create_link() in
rtnl_newlink()). Let's call this netns the dest_net. After this creation, if the
newlink handler exists, it is called with a netns argument that points to the
netns where the netlink message has been received (called src_net in the code)
which is the link netns.
Hence, with one of these attributes, it's possible to create a x-netns
netdevice.
Here is the result of my code review:
- all ip tunnels (sit, ipip, ip6_tunnels, gre[tap][v6], ip_vti[6]) does not
really allows to use this feature: the netdevice is created in the dest_net
and the src_net is completely ignored in the newlink handler.
- VLAN properly handles this x-netns creation.
- bridge ignores src_net, which seems fine (NETIF_F_NETNS_LOCAL is set).
- CAIF subsystem is not clear for me (I don't know how it works), but it seems
to wrongly use src_net. Patch #1 tries to fix this, but it was done only by
code review (and only compile-tested), so please carefully review it. I may
miss something.
- HSR subsystem uses src_net to parse IFLA_HSR_SLAVE[1|2], but the netdevice has
the flag NETIF_F_NETNS_LOCAL, so the question is: does this netdevice really
supports x-netns? If not, the newlink handler should use the dest_net instead
of src_net, I can provide the patch.
- ieee802154 uses also src_net and does not have NETIF_F_NETNS_LOCAL. Same
question: does this netdevice really supports x-netns?
- bonding ignores src_net and flag NETIF_F_NETNS_LOCAL is set, ie x-netns is not
supported. Fine.
- CAN does not support rtnl/newlink, ok.
- ipvlan uses src_net and does not have NETIF_F_NETNS_LOCAL. After looking at
the code, it seems that this drivers support x-netns. Am I right?
- macvlan/macvtap uses src_net and seems to have x-netns support.
- team ignores src_net and has the flag NETIF_F_NETNS_LOCAL, ie x-netns is not
supported. Ok.
- veth uses src_net and have x-netns support ;-) Ok.
- VXLAN didn't properly handle this. The link netns (vxlan->net) is the src_net
and not dest_net (see patch #2). Note that it was already possible to create a
x-netns vxlan before the commit f01ec1c017de ("vxlan: add x-netns support")
but the nedevice remains broken.
To summarize:
- CAIF patch must be carefully reviewed
- for HSR, ieee802154, ipvlan: is x-netns supported?
drivers/net/caif/caif_hsi.c | 1 -
drivers/net/vxlan.c | 10 +++++-----
net/caif/chnl_net.c | 1 -
3 files changed, 5 insertions(+), 7 deletions(-)
Regards,
Nicolas
^ permalink raw reply
* [PATCH net 2/2] vxlan: setup the right link netns in newlink hdlr
From: Nicolas Dichtel @ 2015-01-26 21:28 UTC (permalink / raw)
To: netdev
Cc: davem, dmitry.tarnyagin, arvid.brodin, alex.aring, linux-wpan,
Nicolas Dichtel
In-Reply-To: <1422307694-10079-1-git-send-email-nicolas.dichtel@6wind.com>
Rename the netns to src_net to avoid confusion with the netns where the
interface stands. The user may specify IFLA_NET_NS_[PID|FD] to create
a x-netns netndevice: IFLA_NET_NS_[PID|FD] points to the netns where the
netdevice stands and src_net to the link netns.
Note that before commit f01ec1c017de ("vxlan: add x-netns support"), it was
possible to create a x-netns vxlan netdevice, but the netdevice was not
operational.
Fixes: f01ec1c017de ("vxlan: add x-netns support")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
drivers/net/vxlan.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 7fbd89fbe107..a8c755dcab14 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2432,10 +2432,10 @@ static void vxlan_sock_work(struct work_struct *work)
dev_put(vxlan->dev);
}
-static int vxlan_newlink(struct net *net, struct net_device *dev,
+static int vxlan_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
- struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+ struct vxlan_net *vn = net_generic(src_net, vxlan_net_id);
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
__u32 vni;
@@ -2445,7 +2445,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
if (!data[IFLA_VXLAN_ID])
return -EINVAL;
- vxlan->net = dev_net(dev);
+ vxlan->net = src_net;
vni = nla_get_u32(data[IFLA_VXLAN_ID]);
dst->remote_vni = vni;
@@ -2481,7 +2481,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
if (data[IFLA_VXLAN_LINK] &&
(dst->remote_ifindex = nla_get_u32(data[IFLA_VXLAN_LINK]))) {
struct net_device *lowerdev
- = __dev_get_by_index(net, dst->remote_ifindex);
+ = __dev_get_by_index(src_net, dst->remote_ifindex);
if (!lowerdev) {
pr_info("ifindex %d does not exist\n", dst->remote_ifindex);
@@ -2557,7 +2557,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX;
- if (vxlan_find_vni(net, vni, use_ipv6 ? AF_INET6 : AF_INET,
+ if (vxlan_find_vni(src_net, vni, use_ipv6 ? AF_INET6 : AF_INET,
vxlan->dst_port)) {
pr_info("duplicate VNI %u\n", vni);
return -EEXIST;
--
2.2.2
^ permalink raw reply related
* Re: [PATCH v3 net-next] net: ipv6: Add sysctl entry to disable MTU updates from RA
From: Dan Williams @ 2015-01-26 21:32 UTC (permalink / raw)
To: Harout Hedeshian; +Cc: 'David Miller', netdev, 'Vadim Kochan'
In-Reply-To: <028401d03983$6ed4e750$4c7eb5f0$@codeaurora.org>
On Mon, 2015-01-26 at 09:16 -0700, Harout Hedeshian wrote:
>
> > -----Original Message-----
> > From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> > On Behalf Of Dan Williams
> > Sent: Monday, January 26, 2015 8:04 AM
> > To: Harout Hedeshian
> > Cc: David Miller; netdev@vger.kernel.org; Vadim Kochan
> > Subject: Re: [PATCH v3 net-next] net: ipv6: Add sysctl entry to disable
> > MTU updates from RA
> >
> > On Sun, 2015-01-25 at 09:28 -0700, Harout Hedeshian wrote:
> > > On 01/25/2015 12:21 AM, Vadim Kochan wrote:
> > > > On Sat, Jan 24, 2015 at 11:14:32PM -0800, David Miller wrote:
> > > >> From: Harout Hedeshian <harouth@codeaurora.org>
> > > >> Date: Tue, 20 Jan 2015 10:06:05 -0700
> > > >>
> > > >>> The kernel forcefully applies MTU values received in router
> > > >>> advertisements provided the new MTU is less than the current. This
> > > >>> behavior is undesirable when the user space is managing the MTU.
> > > > Instead
> > > >>> a sysctl flag 'accept_ra_mtu' is introduced such that the user
> > > >>> space can control whether or not RA provided MTU updates should be
> > applied.
> > > > The
> > > >>> default behavior is unchanged; user space must explicitly set this
> > > > flag
> > > >>> to 0 for RA MTUs to be ignored.
> > > >>>
> > > >>> Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
> > > >> Under what circumstances would userland ignore a router advertized
> > > >> MTU, and are the RFCs ok with this?
> > > >> --
> > > >> To unsubscribe from this list: send the line "unsubscribe netdev"
> > > >> in the body of a message to majordomo@vger.kernel.org More
> > > >> majordomo info at http://vger.kernel.org/majordomo-info.html
> > > > Hi,
> > > >
> > > > I don't know if it make sense but I had the same use case when was
> > > > working on supporting IPv6 infrastructure for home gateway.
> > > > One of the provider had requirements to have ability set force IPv6
> > > > MTU value via TR parameters and disable update it via RA.
> > > Hi David,
> > >
> > > We are optionally allowing the kernel shift this responsibility to the
> > > userland. The idea would be that the kernel would ignore it, not so
> > > much the userland. Just like Vadim, we may not want to use the MTU
> > > value which comes from the network. Instead, we get an MTU value from
> > > the cellular modem via configuration message, and that is the MTU we
> > use.
> >
> > Are you talking about an ethernet interface exposed by the modem, or a
> > separate network interface connected to a normal LAN? In the modem
> > case, why would the network-provided RA's MTU be incorrect, but the
> > modem's MTU be correct? If the normal LAN case, why would the modem's
> > MTU be correct for a different network that is broadcasting its own RAs?
> > Just curious...
> >
> > Dan
>
> Hi Dan,
>
> This is a really good question. In the case of a normal LAN, we will allow the kernel to handle the MTU values as they have been today (basically, keep the accept_ra_mtu=1). The issue is not really about the correctness of the RA MTU value (we assume this value is correct, otherwise we are in serious trouble).The issue is on the modem interfaces. To the modem, each protocol family is its own interface. This analogy breaks down for us in Linux because v4 and v6 are fundamentally the same net_device interface. From what I can tell, there is no /proc/sys/net/ipv4/conf/<dev>/mtu which means that IPv4 will take the MTU value from dev->mtu (see ipv4_mtu() ). In contrast, IPv6 maintains a separate MTU and will apply the RA MTUs such that they are less than the device's MTU (dev->mtu). For consi
stency, we have been asked to always pick the minimum value of the IPv4 and IPv6 MTU, and that will become the overall interface MTU. If the kernel goes and changes the V6 MTU without us kn!
ow!
> ing, the userland daemon which maintains the MTU parity will be out of sync. We *could* theoretically let the kernel apply RA MTU updates and we listen for netlink events, but that is unnecessarily complicated as we are already listening in multiple places for these MTU updates. Additionally, we have a problem where the default dev->mtu is 1500 bytes. If we have an IPv6-only network, then it is possible that the network will want to use an MTU > 1500 (esp. multimedia optimized carrier networks). Currently, ndisc.c compares the new MTU value with dev->mtu, if bigger, the RA is ignored. I don't see a good alternative to this because there is no way for ndisc.c to know what the device's maximum physical capabilities are (or that we even want to use such a large MTU). Because of that, we ha
ve to have an out-of-band mechanism to adjust the interface MTU since we know that the hardware is capable of transmitting packets greater than 1500 bytes. Thus, instead of letting the kern!
el!
I believe the IPv4 MTU is taken from the device MTU, eg 'ip link set dev
wwp0s26f7u2i8 mtu XXXX'. I believe that's also where the IPv6 MTU is
taken from, unless it's set via /proc.
But thanks for the explanation, it makes sense.
Dan
> handle RA MTUs in some special circumstances, it is safer and!
> cleaner to disable RA MTUs on the modem interface altogether and let userland pick the correct MTU.
>
> One way to clean up this mess would be to make some changes in the way the kernel handles MTUs.
> 1. Make dev->mtu actually be the MTU the device is capable. For example, jumbo frame capable devices would set this to 9000 upon enumeration instead of 1500. This value would not be editable from userland. There would no longer be a need for driver to implement the MTU adjustment ndo.
> 2. *ALL* protocols must maintain their own MTU values. This would mean a new per-device proc entry for IPv4 at a minimum. The defaults of these values can remain 1500.
>
> If we did this, then the kernel can apply RA MTUs > 1500, and we would get it for free (no changes in IPv6 code). IPv4 would be parity with IPv6 in terms of decoupling MTU from dev->mtu. This means userland can completely not care about the IPv6 MTU, and we can push back on the MTU consistency requirement. Of course, this is a pretty drastic change in interpretation of dev->mtu and would break a lot of userland utilities. Or maybe we leave #1 editable in userland so the utilities and IOCTLs still work, however, userland will now have to additionally adjust IPv4 MTU...
>
> If the kernel community likes this approach, I would be happy to upload some patches which creates a new definition for IPv4 MTU. I think #1 will need more discussion.
>
> If v4 and v6 were truly decoupled, then we could get rid of this minimum selection mess and special case handling for large IPv6 MTUs and this patch could go away.
>
>
> Thanks,
> Harout
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] drivers: net: xgene: fix: Out of order descriptor bytes read
From: Eric Dumazet @ 2015-01-26 21:32 UTC (permalink / raw)
To: Iyappan Subramanian
Cc: David Miller, netdev, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, mlangsdo, patches,
Keyur Chudgar
In-Reply-To: <1422307652.29618.30.camel@edumazet-glaptop2.roam.corp.google.com>
On Mon, 2015-01-26 at 13:27 -0800, Eric Dumazet wrote:
> What happens if you compile a kernel with CONFIG_SMP=n ?
>
>
> Most drivers in drivers/net use rmb() in this case, not smp_rmb() or
> barrier()
Note that dma_rmb() was recently added as well.
^ permalink raw reply
* Re: make allyesconfig i386 build failure with next-20150122 (caused by fb_agm1264k-fl driver)
From: Guenter Roeck @ 2015-01-26 21:59 UTC (permalink / raw)
To: Jim Davis
Cc: Stephen Rothwell, linux-next, linux-kernel, Greg Kroah-Hartman,
devel, isdn, netdev, Thomas Petazzoni
In-Reply-To: <CA+r1ZhhXF+hicy7JKo3jAbgSbO4KOLm6BwPosTKNb+E_Cb4yPQ@mail.gmail.com>
On Thu, Jan 22, 2015 at 12:10:33PM -0700, Jim Davis wrote:
> make ARCH=i386 allyesconfig fails with
>
> drivers/staging/built-in.o: In function `reset':
> (.text+0x2ae89d): multiple definition of `reset'
> drivers/isdn/built-in.o:(.text+0x185dc2): first defined here
> make[1]: *** [drivers/built-in.o] Error 1
Culprit:
commit b2ebd4be6fa1d2329b63531b044f9e25474981cb
Author: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Date: Wed Dec 31 10:11:10 2014 +0100
staging: fbtft: add fb_agm1264k-fl driver
A global function named 'reset' isn't really a good idea.
Not that the global function with the same name in the isdn code
is better ;-).
Guenter
^ permalink raw reply
* [PATCH iproute2] ss: group DCTCP socket statistics
From: Hagen Paul Pfeifer @ 2015-01-26 22:17 UTC (permalink / raw)
To: netdev; +Cc: Hagen Paul Pfeifer, Stephen Hemminger
Keep ss output consistent and format DCTCP socket statistics similar to skmen
and timer where a group of logical values are grouped by brackets. This makes
parser scripts *and* humans more happy.
Current output of 'ss -inetm dst :80':
ESTAB 0 0 192.168.11.14:55511 173.194.66.189:443
timer:(keepalive,14sec,0) uid:1000 ino:428768
sk:ffff88020ceb5b00 <-> skmem:(r0,rb372480,t0,tb87040,f0,w0,o0,bl0)
ts sack wscale:7,7 rto:250 rtt:49.225/20.837 ato:40 mss:1408 cwnd:10
ce_state 23 alpha 23 ab_ecn 23 ab_tot 23 send 2.3Mbps
lastsnd:121026 lastrcv:121026 lastack:30850 pacing_rate 4.6Mbps
retrans:0/2 rcv_rtt:40.416 rcv_space:2920
New grouped output:
ESTAB 0 0 192.168.11.14:55511 173.194.66.189:443
timer:(keepalive,14sec,0) uid:1000 ino:428768
sk:ffff88020ceb5b00 <-> skmem:(r0,rb372480,t0,tb87040,f0,w0,o0,bl0)
ts sack wscale:7,7 rto:250 rtt:49.225/20.837 ato:40 mss:1408 cwnd:10
dctcp(ce_state:23,alpha:23,ab_ecn:23,ab_tot:23) send 2.3Mbps
lastsnd:121026 lastrcv:121026 lastack:30850 pacing_rate 4.6Mbps
retrans:0/2 rcv_rtt:40.416 rcv_space:2920
Cc: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
---
misc/ss.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index f434f57..7d02650 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -1713,11 +1713,11 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
= RTA_DATA(tb[INET_DIAG_DCTCPINFO]);
if (dinfo->dctcp_enabled) {
- printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u",
+ printf("dctcp:(ce_state:%u,alpha:%u,ab_ecn:%u,ab_tot:%u)",
dinfo->dctcp_ce_state, dinfo->dctcp_alpha,
dinfo->dctcp_ab_ecn, dinfo->dctcp_ab_tot);
} else {
- printf(" fallback_mode");
+ printf("dctcp:fallback_mode");
}
}
--
2.2.2
^ permalink raw reply related
* Re: [PATCH 1/2] rhashtable: Introduce rhashtable_walk_*
From: Herbert Xu @ 2015-01-26 22:21 UTC (permalink / raw)
To: Thomas Graf; +Cc: Ying Xue, davem, kaber, paulmck, netdev, netfilter-devel
In-Reply-To: <20150126082000.GA22262@casper.infradead.org>
On Mon, Jan 26, 2015 at 08:20:00AM +0000, Thomas Graf wrote:
> On 01/26/15 at 10:21am, Herbert Xu wrote:
> > +int rhashtable_walk_start(struct rhashtable_iter *iter)
> > +{
> > + struct rhashtable *ht = iter->ht;
> > + int err;
> > +
> > + err = mutex_lock_interruptible(&ht->mutex);
> > + rcu_read_lock();
> > +
> > + if (!err)
> > + mutex_unlock(&ht->mutex);
> > +
> > + return err;
> > +}
> > +EXPORT_SYMBOL_GPL(rhashtable_walk_start);
>
> This doesn't seem to work for Netlink dumps as it would define
> a RCU read side section across user read()s.
No it does not. The start call roughly corresponds to the start
call in seq_file which does not span across reads.
> I assume you relying on RCU to defer the initial table relinking
> in the resizing to be postponed. Wouldn't it be better to hold
> the mutex instead, we could sleep during the dump.
Note that this is not the final solution but just the first step.
So right now it does not prevent/postpone resizes completely. It's
only meant to be a strict improvement over what we currently have.
So indeed resizes will be stopped within a single read but not
across reads for seq_file. Similarly for netlink dump resizes
will only be stopped for a single skb.
I will do the rest of what we discussed once I implement rehashing
since there will be dependencies on it.
> Same here, we leave the iterator with the bucket lock held.
This is intentional, it is what udp_diag does. We'll have to do
this if you ever want to convert UDP sockets over to rhashtable
so we might as well do it now.
If you don't hold the bucket lock then anyone that recycles objects
like UDP will end up walking into the ether.
As before this is not held across reads but only within a read.
Please see patch #2.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH 1/2] rhashtable: Introduce rhashtable_walk_*
From: Herbert Xu @ 2015-01-26 22:23 UTC (permalink / raw)
To: David Laight
Cc: Thomas Graf, Ying Xue, davem@davemloft.net, kaber@trash.net,
paulmck@linux.vnet.ibm.com, netdev@vger.kernel.org,
netfilter-devel@vger.kernel.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1CAD2C12@AcuExch.aculab.com>
On Mon, Jan 26, 2015 at 10:09:24AM +0000, David Laight wrote:
>
> That doesn't look right to me.
> Surely you shouldn't be calling rcu_read_lock() when the mutex
> request is interrupted.
>
> So maybe:
> err = mutex_lock_interruptible(&ht->mutex);
> if (err)
> return err;
> rcu_read_lock();
No, we need to grab the RCU read lock while holding the mutex
in order to prevent future resizes from happening once we release
the mutex.
We don't want to hold the mutex which would stop other walks from
starting.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH] net: Linn Ethernet Packet Sniffer driver
From: Florian Fainelli @ 2015-01-26 22:30 UTC (permalink / raw)
To: Stathis Voukelatos, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: Stathis Voukelatos, abrestic-F7+t8E8rja9g9hUCZPvPmw
In-Reply-To: <1422007621-13567-1-git-send-email-stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
On 23/01/15 02:07, Stathis Voukelatos wrote:
> This patch adds support the Ethernet Packet Sniffer H/W module
> developed by Linn Products Ltd and found in the IMG Pistachio SoC.
> The module allows Ethernet packets to be parsed, matched against
> a user-defined pattern and timestamped. It sits between a 100M
> Ethernet MAC and PHY and is completely passive with respect to
> Ethernet frames.
Is there any latency penalty involved in capturing (or not) packets as
opposed to having this capture HW unused?
>
> Matched packet bytes and timestamp values are returned through a
> FIFO. Timestamps are provided to the module through an externally
> generated Gray-encoded counter.
>
> The command pattern for packet matching is stored in module RAM
> and consists of a sequence of 16-bit entries. Each entry includes
> an 8-bit command code and and 8-bit data value. Valid command
> codes are:
> 0 - Don't care
> 1 - Match: packet data must match command string byte
> 2 - Copy: packet data will be copied to FIFO
> 3 - Match/Stamp: if packet data matches string byte, a timestamp
> is copied into the FIFO
> 4 - Copy/Done: packet data will be copied into the FIFO.
> This command terminates the command string.
>
> The driver consists of two modules:
> - Core: it provides an API to user space using the Generic Netlink
> framework. Specific backend implementations, like the
> Ethernet Packet Sniffer, register one or more channels
> with the Core. For each channel a Genl family is created.
> User space can access a channel by sending Genl messages
> to the Genl family associated with the channel. Packet
> matching events are multicast.
Instead of having this new generic netlink family to control sniffing,
could we imagine registering a netdevice which does not nothing but
still allows for tools like tcpdump, af_packet and other capture tools
to work transparently and just leverage the HW capture?
>
> - Ethernet Packet Sniffer backend: provides the driver for the
> Linn Ethernet Packet Sniffer H/W modules.
>
> The split between a core and backend modules allows software-only
> implementations to be added for platforms where no H/W support
> is available.
>
> Based on 3.19-rc5
>
> Signed-off-by: Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> ---
> .../bindings/net/linn-ether-packet-sniffer.txt | 27 ++
> .../devicetree/bindings/vendor-prefixes.txt | 1 +
> MAINTAINERS | 7 +
> drivers/net/Kconfig | 2 +
> drivers/net/Makefile | 1 +
> drivers/net/pkt-sniffer/Kconfig | 23 ++
> drivers/net/pkt-sniffer/Makefile | 8 +
> drivers/net/pkt-sniffer/backends/ether/channel.c | 366 ++++++++++++++++++
> drivers/net/pkt-sniffer/backends/ether/channel.h | 76 ++++
> drivers/net/pkt-sniffer/backends/ether/hw.h | 46 +++
> drivers/net/pkt-sniffer/backends/ether/platform.c | 231 +++++++++++
> drivers/net/pkt-sniffer/core/dev_table.c | 124 ++++++
> drivers/net/pkt-sniffer/core/module.c | 37 ++
> drivers/net/pkt-sniffer/core/nl.c | 427 +++++++++++++++++++++
> drivers/net/pkt-sniffer/core/nl.h | 34 ++
> drivers/net/pkt-sniffer/core/snf_core.h | 64 +++
> include/linux/pkt_sniffer.h | 89 +++++
> 17 files changed, 1563 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
> create mode 100644 drivers/net/pkt-sniffer/Kconfig
> create mode 100644 drivers/net/pkt-sniffer/Makefile
> create mode 100644 drivers/net/pkt-sniffer/backends/ether/channel.c
> create mode 100644 drivers/net/pkt-sniffer/backends/ether/channel.h
> create mode 100644 drivers/net/pkt-sniffer/backends/ether/hw.h
> create mode 100644 drivers/net/pkt-sniffer/backends/ether/platform.c
> create mode 100644 drivers/net/pkt-sniffer/core/dev_table.c
> create mode 100644 drivers/net/pkt-sniffer/core/module.c
> create mode 100644 drivers/net/pkt-sniffer/core/nl.c
> create mode 100644 drivers/net/pkt-sniffer/core/nl.h
> create mode 100644 drivers/net/pkt-sniffer/core/snf_core.h
> create mode 100644 include/linux/pkt_sniffer.h
>
> diff --git a/Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt b/Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
> new file mode 100644
> index 0000000..6b6e105
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
> @@ -0,0 +1,27 @@
> +* Linn Products Ethernet Packet Sniffer
> +
> +Required properties:
> +- compatible : must be "linn,eth-sniffer"
> +- reg : physical addresses and sizes of registers. Must contain 3 entries:
> + first entry: registers memory space
> + second entry: TX command memory
> + third entry: RX command memory
> +- reg-names : must contain the following 3 entries:
> + "regs", "tx-ram", "rx-ram"
> +- interrupts : sniffer interrupt specifier
> +- clocks : specify the system clock for the peripheral
> +- clock-names : must contain the "sys" entry
> +- fifo-block-words : number of words in one data FIFO entry
> +
> +Example:
> +
> +sniffer@1814a000 {
> + compatible = "linn,eth-sniffer";
> + reg = <0x1814a000 0x100>, <0x1814a400 0x400>, <0x1814a800 0x400>;
> + reg-names = "regs", "tx-ram", "rx-ram";
> + interrupts = <GIC_SHARED 58 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "eth-sniffer-irq";
> + clocks = <&system_clk>;
> + clock-names = "sys";
> + fifo-block-words = <4>;
> + };
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index b1df0ad..2c96f35 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -90,6 +90,7 @@ lacie LaCie
> lantiq Lantiq Semiconductor
> lenovo Lenovo Group Ltd.
> lg LG Corporation
> +linn Linn Products Ltd.
> linux Linux-specific binding
> lsi LSI Corp. (LSI Logic)
> lltc Linear Technology Corporation
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2fa3853..7dbc6e7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5708,6 +5708,13 @@ M: Sasha Levin <sasha.levin-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
> S: Maintained
> F: tools/lib/lockdep/
>
> +LINN PACKET SNIFFER DRIVER
> +M: Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> +S: Maintained
> +F: include/linux/pkt_sniffer.h
> +F: drivers/net/pkt-sniffer/
> +F: Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
> +
> LINUX FOR IBM pSERIES (RS/6000)
> M: Paul Mackerras <paulus-hXjcm30GF6XQT0dZR+AlfA@public.gmane.org>
> W: http://www.ibm.com/linux/ltc/projects/ppc
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index d6607ee..219c786 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -380,4 +380,6 @@ config VMXNET3
>
> source "drivers/net/hyperv/Kconfig"
>
> +source "drivers/net/pkt-sniffer/Kconfig"
> +
> endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index e25fdd7..441111b 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -66,3 +66,4 @@ obj-$(CONFIG_USB_NET_DRIVERS) += usb/
>
> obj-$(CONFIG_HYPERV_NET) += hyperv/
> obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
> +obj-$(CONFIG_PKT_SNIFFER) += pkt-sniffer/
> diff --git a/drivers/net/pkt-sniffer/Kconfig b/drivers/net/pkt-sniffer/Kconfig
> new file mode 100644
> index 0000000..26b4f98
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/Kconfig
> @@ -0,0 +1,23 @@
> +menuconfig PKT_SNIFFER
> + tristate "Linn packet sniffer support"
> + ---help---
> + Say Y to add support for Linn packet sniffer drivers.
> +
> + The core driver can also be built as a module. If so, the module
> + will be called snf_core.
> +
> +if PKT_SNIFFER
> +
> +config PKT_SNIFFER_ETHER
> + tristate "Ethernet packet sniffer"
> + depends on MIPS
> + default n
> + help
> + Say Y here if you want to use the Linn Ethernet packet sniffer
> + module. It can be found in the upcoming Pistachio SoC by
> + Imagination Technologies.
> +
> + The driver can also be built as a module. If so, the module
> + will be called snf_ether.
> +
> +endif # PKT_SNIFFER
> diff --git a/drivers/net/pkt-sniffer/Makefile b/drivers/net/pkt-sniffer/Makefile
> new file mode 100644
> index 0000000..07e7339
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/Makefile
> @@ -0,0 +1,8 @@
> +snf_core-y += core/nl.o
> +snf_core-y += core/dev_table.o
> +snf_core-y += core/module.o
> +obj-$(CONFIG_PKT_SNIFFER) += snf_core.o
> +
> +snf_ether-y += backends/ether/platform.o
> +snf_ether-y += backends/ether/channel.o
> +obj-$(CONFIG_PKT_SNIFFER_ETHER) += snf_ether.o
> diff --git a/drivers/net/pkt-sniffer/backends/ether/channel.c b/drivers/net/pkt-sniffer/backends/ether/channel.c
> new file mode 100644
> index 0000000..d483b58
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/backends/ether/channel.c
> @@ -0,0 +1,366 @@
> +/*
> + * Ethernet Mii packet sniffer driver
> + * - channel functions
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/pkt_sniffer.h>
> +#include "../../core/snf_core.h"
> +#include "hw.h"
> +#include "channel.h"
> +
> +#define to_ether_snf_chan(dev) container_of(dev, struct ether_snf_chan, chan)
> +
> +static int esnf_start(struct snf_chan *dev);
> +static int esnf_stop(struct snf_chan *dev);
> +static int esnf_set_pattern(struct snf_chan *dev, const u8 *pattern, int count);
> +static int esnf_num_recs_avail(struct snf_chan *dev);
> +static int esnf_max_ptn_entries(struct snf_chan *dev);
> +static int esnf_max_match_bytes(struct snf_chan *dev);
> +static int validate_pattern(
> + struct ether_snf_chan *ch,
> + const u8 *buf,
> + int count);
> +static void read_fifo_data(struct ether_snf_chan *ch);
> +static u32 gray_decode(u32 gray);
> +
> +/* Initialises a sniffer channel */
> +int channel_init(
> + struct ether_snf_chan *ch,
> + struct platform_device *pdev,
> + void *regs,
> + int fifo_blk_words,
> + int tx)
> +{
> + struct resource *res;
> + u32 *ptr;
> + int i;
> +
> + ch->regs = regs;
> + ch->dev = &pdev->dev;
> + ch->data_irq_bit = tx ? TX_DATA_IRQ_BIT : RX_DATA_IRQ_BIT;
> + ch->full_irq_bit = tx ? TX_FULL_IRQ_BIT : RX_FULL_IRQ_BIT;
> + ch->reg_enable = ch->regs +
> + (tx ? TX_SNIFFER_ENABLE : RX_SNIFFER_ENABLE);
> + ch->reg_occ = ch->regs + (tx ? TX_FIFO_OCC : RX_FIFO_OCC);
> + ch->reg_fifo = ch->regs + (tx ? TX_FIFO_DAT : RX_FIFO_DAT);
> +
> + /* Retrieve and remap the address space for the command memory */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> + tx ? "tx-ram" : "rx-ram");
> + if (!res)
> + return -ENOSYS;
> + ch->cmd_ram = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(ch->cmd_ram))
> + return PTR_ERR(ch->cmd_ram);
> +
> + /* It is 2 bytes/command, hence divide by 2 */
> + ch->max_cmds = resource_size(res) / 2;
> +
> + /* Initialise the command pattern RAM */
> + for (i = 0, ptr = ch->cmd_ram; i < resource_size(res); i += 4)
> + iowrite32((PTN_CMD_DONTCARE << 24) | (PTN_CMD_DONTCARE << 8),
> + ptr++);
> +
> + ch->fifo_blk_words = fifo_blk_words;
> + ch->started = 0;
> +
> + /* Register the channel methods */
> + ch->chan.start = esnf_start;
> + ch->chan.stop = esnf_stop;
> + ch->chan.set_pattern = esnf_set_pattern;
> + ch->chan.num_recs_avail = esnf_num_recs_avail;
> + ch->chan.max_ptn_entries = esnf_max_ptn_entries;
> + ch->chan.max_match_bytes = esnf_max_match_bytes;
> +
> + strncpy(ch->name, tx ? "TX" : "RX", MAX_CHAN_NAME_SIZE - 1);
> +
> + dev_dbg(ch->dev, "%s channel initialized\n", ch->name);
> +
> + return 0;
> +}
> +
> +/* Registers the channel with the sniffer core module */
> +int channel_register(struct ether_snf_chan *ch, const char *name)
> +{
> + int id;
> +
> + id = snf_channel_add(&ch->chan, name);
> + if (id < 0)
> + return id;
> +
> + ch->id = id;
> + dev_info(ch->dev, "%s channel added\n", ch->name);
> + return 0;
> +}
> +
> +/* Unregisters the channel */
> +int channel_unregister(struct ether_snf_chan *ch)
> +{
> + int ret;
> +
> + ch->chan.stop(&ch->chan);
> + ret = snf_channel_remove(ch->id);
> + if (!ret)
> + dev_info(ch->dev, "%s channel removed\n", ch->name);
> + return ret;
> +}
> +
> +/* Process match event data */
> +void channel_data_available(struct ether_snf_chan *ch)
> +{
> + int ret;
> +
> + dev_dbg(ch->dev, "%s match event\n", ch->name);
> +
> + read_fifo_data(ch);
> + ret = snf_channel_notify_match(&ch->chan, &ch->evt);
> + if (ret < 0)
> + dev_err(ch->dev, "%s: event notification failed\n", ch->name);
> +}
> +
> +/* Channel methods */
> +
> +/* Enables the channel */
> +static int esnf_start(struct snf_chan *dev)
> +{
> + struct ether_snf_chan *ch = to_ether_snf_chan(dev);
> +
> + if (!ch->started) {
> + /* Enable interrupts */
> + iowrite32(ch->data_irq_bit | ch->full_irq_bit,
> + ch->regs + SET_INTERRUPT_ENABLE);
> + /* Enable the packet matching logic */
> + iowrite32(ENABLE_BIT, ch->reg_enable);
> +
> + ch->started = 1;
> + dev_info(ch->dev, "%s channel started\n", ch->name);
> + } else {
> + dev_dbg(ch->dev, "%s channel already running\n", ch->name);
> + }
> +
> + return 0;
> +}
> +
> +/* Disables the channel */
> +static int esnf_stop(struct snf_chan *dev)
> +{
> + struct ether_snf_chan *ch = to_ether_snf_chan(dev);
> +
> + if (ch->started) {
> + /* Disable interrupts */
> + iowrite32(ch->data_irq_bit | ch->full_irq_bit,
> + ch->regs + CLEAR_INTERRUPT_ENABLE);
> + /* Stop the sniffer channel */
> + iowrite32(0, ch->reg_enable);
> + /* Clear any pending interrupts */
> + iowrite32(ch->data_irq_bit | ch->full_irq_bit,
> + ch->regs + INTERRUPT_STATUS);
> +
> + ch->started = 0;
> + dev_info(ch->dev, "%s channel stopped\n", ch->name);
> + } else {
> + dev_dbg(ch->dev, "%s channel already stopped\n", ch->name);
> + }
> +
> + return 0;
> +}
> +
> +/* Sets the command string (pattern) for the channel
> + * The bytes in the pattern buffer are in the following order:
> + */
> +static int esnf_set_pattern(struct snf_chan *dev, const u8 *pattern, int count)
> +{
> + struct ether_snf_chan *ch = to_ether_snf_chan(dev);
> + int i, shift = 0;
> + u32 val = 0, *ptr;
> +
> + if (ch->started) {
> + dev_err(ch->dev,
> + "cannot apply cmd pattern. %s channel is active\n",
> + ch->name);
> + return -EBUSY;
> + }
> +
> + if (!validate_pattern(ch, pattern, count)) {
> + dev_err(ch->dev,
> + "invalid cmd pattern for %s channel\n",
> + ch->name);
> + return -EINVAL;
> + }
> +
> + for (ptr = ch->cmd_ram, i = 0, shift = 24; i < (2*count); i++) {
> + val |= ((u32)pattern[i]) << shift;
> + if (!shift) {
> + iowrite32(val, ptr++);
> + val = 0;
> + shift = 24;
> + } else {
> + shift -= 8;
> + }
> + }
> + if (shift)
> + iowrite32(val, ptr);
> +
> + return 0;
> +}
> +
> +/* Returns the number of pending match events that are
> + * available to retrieve
> + */
> +static int esnf_num_recs_avail(struct snf_chan *dev)
> +{
> + struct ether_snf_chan *ch = to_ether_snf_chan(dev);
> +
> + return ioread32(ch->reg_occ);
> +}
> +
> +/* Returns max number of commands supported by the channel */
> +static int esnf_max_ptn_entries(struct snf_chan *dev)
> +{
> + struct ether_snf_chan *ch = to_ether_snf_chan(dev);
> +
> + return ch->max_cmds;
> +}
> +
> +/* Returns max number of bytes that can be returned by a match */
> +static int esnf_max_match_bytes(struct snf_chan *dev)
> +{
> + struct ether_snf_chan *ch = to_ether_snf_chan(dev);
> +
> + /* Subtract the word that may be used for the timestamp */
> + return (ch->fifo_blk_words - 1) * 4;
> +}
> +
> +/* Checks if the supplied command string is compatible with the
> + * capabilities of the H/W
> + */
> +static int validate_pattern(struct ether_snf_chan *ch, const u8 *buf, int count)
> +{
> + int i, complete, max_copy_bytes;
> + int ts = 0;
> + int copy_before = 0;
> + int copy_after = 0;
> +
> + if (count > ch->max_cmds)
> + return 0;
> +
> + /* Iterate through the commands in the string */
> + for (i = 0, complete = 0; (i < count) && !complete; i++) {
> + u8 cmd = buf[2*i];
> +
> + switch (cmd) {
> + case PTN_CMD_DONTCARE:
> + case PTN_CMD_MATCH:
> + break;
> +
> + case PTN_CMD_MATCHSTAMP:
> + /* The timestamp needs to be word-aligned in the FIFO
> + * therefore, the number of 'copy' commands before it
> + * needs to be a multiple of 4
> + */
> + if (copy_before & 3)
> + return 0;
> + /* Signal that a timestamp will be present */
> + ts = 1;
> + break;
> +
> + case PTN_CMD_COPY:
> + /* Increment count of bytes that will be returned */
> + if (ts)
> + copy_after++;
> + else
> + copy_before++;
> + break;
> +
> + case PTN_CMD_COPYDONE:
> + /* Increment count of bytes that will be returned
> + * This command terminates the string
> + */
> + if (ts)
> + copy_after++;
> + else
> + copy_before++;
> + complete = 1;
> + break;
> +
> + default:
> + return 0;
> + }
> + }
> +
> + /* Check if the string was properly terminated
> + * and contained valid number of commands
> + */
> + if (complete) {
> + max_copy_bytes = ch->fifo_blk_words * 4;
> + if (ts)
> + max_copy_bytes -= 4;
> + if ((copy_before + copy_after) > max_copy_bytes)
> + return 0;
> + ch->ts_present = ts;
> + ch->nfb_before = copy_before;
> + ch->nfb_after = copy_after;
> + return 1;
> + } else {
> + return 0;
> + }
> +}
> +
> +/* Read a block from the data FIFO */
> +static void read_fifo_data(struct ether_snf_chan *ch)
> +{
> + int i;
> + u32 val, *ptr;
> + int ts = ch->ts_present;
> + int dw = ch->fifo_blk_words;
> + int bytes_before = ch->nfb_before;
> + int bytes_after = ch->nfb_after;
> +
> + ptr = (u32 *)ch->evt.data;
> + for (i = 0; i < dw; i++) {
> + val = ioread32(ch->reg_fifo);
> + if (bytes_before > 0) {
> + /* Bytes before the timestamp */
> + *ptr++ = cpu_to_be32(val);
> + bytes_before -= 4;
> + } else if (ts) {
> + /* Timestamp is Gray encoded */
> + ch->evt.ts = (u64)gray_decode(val);
> + ts = 0;
> + } else if (bytes_after > 0) {
> + /* Bytes after the timestamp */
> + *ptr++ = cpu_to_be32(val);
> + bytes_after -= 4;
> + }
> + }
> +
> + ch->evt.ts_valid = ch->ts_present;
> + ch->evt.len = ch->nfb_before + ch->nfb_after;
> +}
> +
> +/* Gray decoder */
> +static u32 gray_decode(u32 gray)
> +{
> + gray ^= (gray >> 16);
> + gray ^= (gray >> 8);
> + gray ^= (gray >> 4);
> + gray ^= (gray >> 2);
> + gray ^= (gray >> 1);
> + return gray;
> +}
> +
> diff --git a/drivers/net/pkt-sniffer/backends/ether/channel.h b/drivers/net/pkt-sniffer/backends/ether/channel.h
> new file mode 100644
> index 0000000..4f00b33
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/backends/ether/channel.h
> @@ -0,0 +1,76 @@
> +/*
> + * Ethernet Mii packet sniffer driver
> + * - channel interface
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#ifndef _ETHER_SNIFFER_CHANNEL_H_
> +#define _ETHER_SNIFFER_CHANNEL_H_
> +
> +#include <linux/platform_device.h>
> +#include "../../core/snf_core.h"
> +
> +#define MAX_CHAN_NAME_SIZE 5
> +
> +struct ether_snf_chan {
> + /* Sniffer core structure */
> + struct snf_chan chan;
> + /* Pointer to device struct */
> + struct device *dev;
> + /* Registers */
> + u8 __iomem *regs;
> + /* Command string memory */
> + u32 __iomem *cmd_ram;
> + /* Bit number for the data IRQ */
> + int data_irq_bit;
> + /* Bit number for the FIFO full IRQ */
> + int full_irq_bit;
> + /* Channel enable register */
> + u8 __iomem *reg_enable;
> + /* Data FIFO register */
> + u8 __iomem *reg_fifo;
> + /* FIFO occupancy register */
> + u8 __iomem *reg_occ;
> + /* Max number of commands in the string */
> + int max_cmds;
> + /* Max matching bytes that can fit in a FIFO block */
> + int fifo_blk_words;
> + /* Number of bytes in the FIFO before the timestamp */
> + int nfb_before;
> + /* Number of bytes in the FIFO after the timestamp */
> + int nfb_after;
> + /* Timestamp present flag */
> + int ts_present;
> + /* ID assigned to channel by the sniffer core */
> + int id;
> + /* Channel active flag */
> + int started;
> + /* Channel name (only used by debug messages) */
> + char name[MAX_CHAN_NAME_SIZE];
> + /* Struct to hold data from a packet match */
> + struct snf_match_evt evt;
> +};
> +
> +int channel_init(
> + struct ether_snf_chan *ch,
> + struct platform_device *pdev,
> + void *regs,
> + int fifo_blk_words,
> + int tx);
> +int channel_register(struct ether_snf_chan *ch, const char *name);
> +int channel_unregister(struct ether_snf_chan *ch);
> +void channel_data_available(struct ether_snf_chan *ch);
> +
> +#endif
> diff --git a/drivers/net/pkt-sniffer/backends/ether/hw.h b/drivers/net/pkt-sniffer/backends/ether/hw.h
> new file mode 100644
> index 0000000..edb1093
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/backends/ether/hw.h
> @@ -0,0 +1,46 @@
> +/*
> + * Ethernet Mii packet sniffer driver
> + * - register map
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#ifndef _ETHER_SNIFFER_HW_H_
> +#define _ETHER_SNIFFER_HW_H_
> +
> +#include <linux/bitops.h>
> +
> +/* Registers */
> +#define INTERRUPT_ENABLE 0x00
> +#define SET_INTERRUPT_ENABLE 0x04
> +#define CLEAR_INTERRUPT_ENABLE 0x08
> +#define INTERRUPT_STATUS 0x0c
> +#define TX_FIFO_DAT 0x10
> +#define RX_FIFO_DAT 0x14
> +#define TX_FIFO_OCC 0x18
> +#define RX_FIFO_OCC 0x1c
> +#define TX_SNIFFER_ENABLE 0x20
> +#define RX_SNIFFER_ENABLE 0x24
> +
> +/* IRQ register bits */
> +#define TX_DATA_IRQ_BIT BIT(0)
> +#define RX_DATA_IRQ_BIT BIT(1)
> +#define TX_FULL_IRQ_BIT BIT(2)
> +#define RX_FULL_IRQ_BIT BIT(3)
> +
> +/* Enable register bits */
> +#define ENABLE_BIT BIT(0)
> +
> +#endif
> +
> diff --git a/drivers/net/pkt-sniffer/backends/ether/platform.c b/drivers/net/pkt-sniffer/backends/ether/platform.c
> new file mode 100644
> index 0000000..78e7e1c
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/backends/ether/platform.c
> @@ -0,0 +1,231 @@
> +/*
> + * Ethernet Mii packet sniffer driver
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include "../../core/snf_core.h"
> +#include "hw.h"
> +#include "channel.h"
> +
> +static const char esnf_driver_name[] = "eth-sniffer";
> +
> +/* Names for the TX and RX channel.
> + * User space will used these names to access the channels
> + * through the generic netlink interface
> + */
> +static const char tx_channel_name[] = "snf_ether_tx";
> +static const char rx_channel_name[] = "snf_ether_rx";
> +
> +struct ether_snf {
> + u8 __iomem *regs;
> + int irq;
> + struct clk *sys_clk;
> + struct ether_snf_chan txc;
> + struct ether_snf_chan rxc;
> +};
> +
> +/* Interrupt thread function */
> +static irqreturn_t esnf_irq_thread(int irq, void *dev_id)
> +{
> + struct platform_device *pdev = (struct platform_device *)dev_id;
> + struct ether_snf *esnf = (struct ether_snf *)platform_get_drvdata(pdev);
> + u32 irq_status;
> +
> + if (unlikely(esnf->irq != irq))
> + return IRQ_NONE;
> +
> + irq_status = ioread32(esnf->regs + INTERRUPT_STATUS) &
> + ioread32(esnf->regs + INTERRUPT_ENABLE);
> +
> + dev_dbg(&pdev->dev, "irq: 0x%08x\n", irq_status);
> +
> + /* TX FIFO full */
> + if (unlikely(irq_status & TX_FULL_IRQ_BIT))
> + dev_notice(&pdev->dev, "TX FIFO full");
> +
> + /* RX FIFO full */
> + if (unlikely(irq_status & RX_FULL_IRQ_BIT))
> + dev_notice(&pdev->dev, "RX FIFO full");
> +
> + /* TX match data available */
> + if (irq_status & TX_DATA_IRQ_BIT) {
> + dev_dbg(&pdev->dev, "TX data");
> + channel_data_available(&esnf->txc);
> + }
> +
> + /* RX match data available */
> + if (irq_status & RX_DATA_IRQ_BIT) {
> + dev_dbg(&pdev->dev, "RX data");
> + channel_data_available(&esnf->rxc);
> + }
> +
> + /* Clear interrupts */
> + iowrite32(irq_status, esnf->regs + INTERRUPT_STATUS);
> +
> + return IRQ_HANDLED;
> +}
> +
> +/* Called when the packet sniffer device is bound with the driver */
> +static int esnf_driver_probe(struct platform_device *pdev)
> +{
> + struct ether_snf *esnf;
> + struct resource *res;
> + int ret, irq;
> + u32 fifo_blk_words;
> + void __iomem *regs;
> + struct device_node *ofn = pdev->dev.of_node;
> +
> + /* Allocate the device data structure */
> + esnf = devm_kzalloc(&pdev->dev, sizeof(*esnf), GFP_KERNEL);
> + if (!esnf)
> + return -ENOMEM;
> +
> + /* Retrieve and remap register memory space */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
> + if (!res)
> + return -ENODEV;
> +
> + regs = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + esnf->regs = regs;
> +
> + /* Read the FIFO block size from the DT */
> + if (!ofn)
> + return -ENODEV;
> +
> + ret = of_property_read_u32(
> + ofn,
> + "fifo-block-words",
> + &fifo_blk_words);
> + if (ret < 0)
> + return ret;
> +
> + if (((fifo_blk_words - 1)*4) > MAX_MATCH_BYTES) {
> + dev_err(&pdev->dev,
> + "Invalid FIFO block size entry in device tree\n");
> + return -EINVAL;
> + }
> +
> + esnf->sys_clk = devm_clk_get(&pdev->dev, "sys");
> + if (IS_ERR(esnf->sys_clk)) {
> + ret = PTR_ERR(esnf->sys_clk);
> + return ret;
> + }
> + ret = clk_prepare_enable(esnf->sys_clk);
> + if (ret < 0)
> + return ret;
> +
> + /* Initialise the TX and RX channels */
> + ret = channel_init(&esnf->txc, pdev, regs, fifo_blk_words, 1);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to init TX channel (%d)\n", ret);
> + goto fail1;
> + }
> + ret = channel_init(&esnf->rxc, pdev, regs, fifo_blk_words, 0);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to init RX channel (%d)\n", ret);
> + goto fail1;
> + }
> +
> + /* Register the channels with the sniffer core module */
> + ret = channel_register(&esnf->txc, tx_channel_name);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to register TX chan (%d)\n", ret);
> + goto fail1;
> + }
> + ret = channel_register(&esnf->rxc, rx_channel_name);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to register RX chan (%d)\n", ret);
> + goto fail2;
> + }
> +
> + platform_set_drvdata(pdev, esnf);
> +
> + /* Register the interrupt handler */
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + goto fail3;
> + esnf->irq = irq;
> + ret = devm_request_threaded_irq(
> + &pdev->dev,
> + irq,
> + NULL,
> + esnf_irq_thread,
> + IRQF_ONESHOT,
> + esnf_driver_name,
> + pdev);
> + if (ret < 0)
> + goto fail3;
> +
> + return 0;
> +
> +fail3:
> + channel_unregister(&esnf->rxc);
> +fail2:
> + channel_unregister(&esnf->txc);
> +fail1:
> + clk_disable_unprepare(esnf->sys_clk);
> + return ret;
> +}
> +
> +/* Called when the packet sniffer device unregisters with the driver */
> +static int esnf_driver_remove(struct platform_device *pdev)
> +{
> + struct ether_snf *esnf = (struct ether_snf *)platform_get_drvdata(pdev);
> + int ret;
> +
> + ret = channel_unregister(&esnf->txc);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to unregister TX chan (%d)\n", ret);
> + return ret;
> + }
> + ret = channel_unregister(&esnf->rxc);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to unregister RX chan (%d)\n", ret);
> + return ret;
> + }
> + clk_disable_unprepare(esnf->sys_clk);
> + return 0;
> +}
> +
> +static const struct of_device_id esnf_of_match_table[] = {
> + { .compatible = "linn,eth-sniffer", .data = NULL },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, esnf_of_match_table);
> +
> +static struct platform_driver esnf_platform_driver = {
> + .driver = {
> + .name = esnf_driver_name,
> + .of_match_table = esnf_of_match_table,
> + },
> + .probe = esnf_driver_probe,
> + .remove = esnf_driver_remove,
> +};
> +
> +module_platform_driver(esnf_platform_driver);
> +
> +MODULE_DESCRIPTION("Linn Ethernet Packet Sniffer");
> +MODULE_AUTHOR("Linn Products Ltd");
> +MODULE_LICENSE("GPL v2");
> +
> diff --git a/drivers/net/pkt-sniffer/core/dev_table.c b/drivers/net/pkt-sniffer/core/dev_table.c
> new file mode 100644
> index 0000000..3a07838
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/core/dev_table.c
> @@ -0,0 +1,124 @@
> +/*
> + * Packet sniffer core driver: channel management
> + *
> + * Copyright (C) 2014 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include "snf_core.h"
> +#include "nl.h"
> +
> +#define MAX_CHANNELS 256
> +
> +static DEFINE_MUTEX(tlock);
> +
> +static struct snf_chan *dev_tab[MAX_CHANNELS];
> +static unsigned int ref_count[MAX_CHANNELS];
> +
> +static inline int verify_args(int id)
> +{
> + return (id < MAX_CHANNELS);
> +}
> +
> +/* Registers a sniffer channel and returns and id for it */
> +int snf_channel_add(struct snf_chan *dev, const char *name)
> +{
> + int i;
> + int ret = -EEXIST;
> +
> + mutex_lock(&tlock);
> +
> + for (i = 0; i < MAX_CHANNELS; i++) {
> + if (!dev_tab[i]) {
> + /* Initialise the netlink interface for the channel */
> + ret = snf_netlink_init(i, dev, name);
> + if (ret < 0)
> + goto fail;
> +
> + dev_tab[i] = dev;
> + ref_count[i] = 0;
> + mutex_unlock(&tlock);
> + return i;
> + }
> + }
> +
> +fail:
> + mutex_unlock(&tlock);
> + return ret;
> +}
> +EXPORT_SYMBOL(snf_channel_add);
> +
> +/* Removes a sniffer channel */
> +int snf_channel_remove(int id)
> +{
> + int ret = 0;
> + struct snf_chan *dev;
> +
> + if (!verify_args(id))
> + return -EINVAL;
> +
> + mutex_lock(&tlock);
> +
> + dev = dev_tab[id];
> +
> + if (!dev) {
> + ret = -ENODEV;
> + goto fail;
> + }
> +
> + if (ref_count[id] > 0) {
> + ret = -EBUSY;
> + goto fail;
> + }
> +
> + dev_tab[id] = NULL;
> +
> + /* Release netlink API resources */
> + snf_netlink_release(dev);
> +
> +fail:
> + mutex_unlock(&tlock);
> + return ret;
> +}
> +EXPORT_SYMBOL(snf_channel_remove);
> +
> +/* Returns a pointer to the specified sniffer channel
> + * and increments its reference counter
> + */
> +struct snf_chan *snf_channel_get(int id)
> +{
> + struct snf_chan *dev;
> +
> + if (!verify_args(id))
> + return NULL;
> +
> + mutex_lock(&tlock);
> + dev = dev_tab[id];
> + if (dev)
> + ref_count[id]++;
> + mutex_unlock(&tlock);
> +
> + return dev;
> +}
> +
> +/* Decrements the reference counter for the channel */
> +void snf_channel_put(int id)
> +{
> + mutex_lock(&tlock);
> + if (ref_count[id] > 0)
> + ref_count[id]--;
> + mutex_unlock(&tlock);
> +}
> +
> diff --git a/drivers/net/pkt-sniffer/core/module.c b/drivers/net/pkt-sniffer/core/module.c
> new file mode 100644
> index 0000000..af6a1aa
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/core/module.c
> @@ -0,0 +1,37 @@
> +/*
> + * Packet sniffer core driver:
> + * - backend channel management
> + * - interface to userland via generic netlink
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#include <linux/module.h>
> +#include <linux/init.h>
> +
> +static int __init snf_core_init(void)
> +{
> + return 0;
> +}
> +
> +static void __exit snf_core_cleanup(void)
> +{
> +}
> +
> +module_init(snf_core_init);
> +module_exit(snf_core_cleanup);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Core packet sniffer driver");
> +MODULE_AUTHOR("Linn Products Ltd");
> diff --git a/drivers/net/pkt-sniffer/core/nl.c b/drivers/net/pkt-sniffer/core/nl.c
> new file mode 100644
> index 0000000..6839147
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/core/nl.c
> @@ -0,0 +1,427 @@
> +/*
> + * Packet sniffer core driver: generic netlink interface
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#include <linux/version.h>
> +#include <net/netlink.h>
> +#include <net/genetlink.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/pkt_sniffer.h>
> +#include "snf_core.h"
> +#include "nl.h"
> +
> +/* Netlink API data for a sniffer channel */
> +struct snf_netlink {
> + /* genl family */
> + struct genl_family fml;
> + /* genl operations */
> + struct genl_ops *ops;
> + /* genl mcast group, where sniffer match
> + * events will be sent
> + */
> + struct genl_multicast_group grp;
> +};
> +
> +/* Attribute policies */
> +static struct nla_policy snf_policy[SNF_ATTR_MAX + 1] = {
> + [SNF_ATTR_PATTERN] = { .type = NLA_NESTED },
> +};
> +
> +static struct nla_policy snf_ptn_policy[SNF_ATTR_PTN_MAX + 1] = {
> + [SNF_ATTR_PTN_ENTRY] = { .type = NLA_U16 },
> +};
> +
> +/* Generic Netlink family template definition */
> +static int pre_doit_func(const struct genl_ops *ops,
> + struct sk_buff *skb,
> + struct genl_info *info);
> +
> +static void post_doit_func(const struct genl_ops *ops,
> + struct sk_buff *skb,
> + struct genl_info *info);
> +
> +static struct genl_family snf_family_tmpl = {
> + .id = GENL_ID_GENERATE,
> + .hdrsize = 0,
> + .version = SNF_GNL_VERSION,
> + .maxattr = SNF_ATTR_MAX,
> + .pre_doit = pre_doit_func,
> + .post_doit = post_doit_func
> +};
> +
> +static int send_reply_uint32(
> + struct genl_info *info,
> + int cmd,
> + int attr,
> + u32 val);
> +
> +/* Generic Netlink operations template definition */
> +
> +static int do_it_start(struct sk_buff *skb, struct genl_info *info);
> +static int do_it_stop(struct sk_buff *skb, struct genl_info *info);
> +static int do_it_set_pattern(struct sk_buff *skb, struct genl_info *info);
> +static int do_it_num_rec_avail(struct sk_buff *skb, struct genl_info *info);
> +static int do_it_ptn_max_cmds(struct sk_buff *skb, struct genl_info *info);
> +static int do_it_max_match_bytes(struct sk_buff *skb, struct genl_info *info);
> +
> +#define SNF_GENL_OP(_cmd, _func) \
> + { \
> + .cmd = _cmd, \
> + .policy = snf_policy, \
> + .doit = _func, \
> + .dumpit = NULL, \
> + .flags = 0, \
> + .internal_flags = 0 \
> + }
> +
> +#define SNF_CHAN_OPS \
> + { \
> + SNF_GENL_OP(SNF_CMD_START, do_it_start), \
> + SNF_GENL_OP(SNF_CMD_STOP, do_it_stop), \
> + SNF_GENL_OP(SNF_CMD_SETPATTERN, do_it_set_pattern), \
> + SNF_GENL_OP(SNF_CMD_NUMRECAVAIL, do_it_num_rec_avail), \
> + SNF_GENL_OP(SNF_CMD_PTNMAXCMDS, do_it_ptn_max_cmds), \
> + SNF_GENL_OP(SNF_CMD_MAXMATCHBYTES, do_it_max_match_bytes) \
> + }
> +
> +static struct genl_ops snf_ops_tmpl[] = SNF_CHAN_OPS;
> +
> +#define NUM_GENL_OPS ARRAY_SIZE(snf_ops_tmpl)
> +
> +/* Multicast a netlink event containing data from a sniffer match event.
> + * Data are included in the netlink message as a nested attribute
> + * containing the timestamp (optional) and matching packet bytes
> +*/
> +int snf_channel_notify_match(struct snf_chan *dev, struct snf_match_evt *mt)
> +{
> + int i, ret = 0;
> + struct sk_buff *msg = NULL;
> + void *msg_hdr, *nest_hdr;
> + struct snf_netlink *nl = (struct snf_netlink *)dev->cstate;
> +
> + if (!nl) {
> + ret = -EINVAL;
> + goto fail;
> + }
> +
> + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
> + if (!msg) {
> + ret = -ENOMEM;
> + goto fail;
> + }
> +
> + msg_hdr = genlmsg_put(msg,
> + 0,
> + 0,
> + &nl->fml,
> + 0,
> + SNF_CMD_MATCHEVENT);
> + if (!msg_hdr) {
> + ret = -EMSGSIZE;
> + goto fail;
> + }
> +
> + /* Add the nested attribute with the data */
> + if ((mt->ts_valid) || (mt->len > 0)) {
> + nest_hdr = nla_nest_start(msg, SNF_ATTR_MATCHEVENT);
> + if (!nest_hdr) {
> + ret = -EMSGSIZE;
> + goto fail;
> + }
> + if (mt->ts_valid) {
> + ret = nla_put_u64(msg, SNF_ATTR_MATCH_TS, mt->ts);
> + if (ret < 0)
> + goto fail;
> + }
> + for (i = 0; i < mt->len; i++) {
> + ret = nla_put_u8(msg,
> + SNF_ATTR_MATCH_PKTBYTE,
> + mt->data[i]);
> + if (ret < 0)
> + goto fail;
> + }
> + nla_nest_end(msg, nest_hdr);
> + }
> +
> + ret = genlmsg_end(msg, msg_hdr);
> + if (ret < 0)
> + goto fail;
> + ret = genlmsg_multicast(&nl->fml, msg, 0, 0, GFP_ATOMIC);
> +
> + /* The ESRCH code is returned when there is no socket listening on the
> + * multicast group, so we do not really treat is as an error
> + */
> + if (ret == -ESRCH)
> + ret = 0;
> + return ret;
> +
> +fail:
> + if (msg)
> + nlmsg_free(msg);
> + return ret;
> +}
> +EXPORT_SYMBOL(snf_channel_notify_match);
> +
> +/* Initialise the generic netlink API for a sniffer channel
> + * Registers family, ops and multicast group for events
> + */
> +int snf_netlink_init(int id, struct snf_chan *dev, const char *name)
> +{
> + int i, ret;
> + struct snf_netlink *nl = NULL;
> +
> + nl = kmalloc(sizeof(*nl), GFP_KERNEL);
> + if (!nl) {
> + ret = -ENOMEM;
> + goto fail1;
> + }
> +
> + nl->fml = snf_family_tmpl;
> +
> + /* Set the family name */
> + strncpy(nl->fml.name, name, GENL_NAMSIZ-1);
> +
> + /* Allocate ops array and copy template data */
> + nl->ops = kmalloc(sizeof(snf_ops_tmpl), GFP_KERNEL);
> + if (!nl->ops) {
> + ret = -ENOMEM;
> + goto fail2;
> + }
> + memcpy(nl->ops, snf_ops_tmpl, sizeof(snf_ops_tmpl));
> +
> + /* In the internal_flags field we store the id
> + * of the device the ops belong to
> + */
> + for (i = 0; i < NUM_GENL_OPS; i++)
> + nl->ops[i].internal_flags = id;
> +
> + snprintf(nl->grp.name, GENL_NAMSIZ-1, SNF_EVENT_GRP);
> +
> + ret = _genl_register_family_with_ops_grps(
> + &nl->fml,
> + nl->ops,
> + NUM_GENL_OPS,
> + &nl->grp,
> + 1);
> + if (ret < 0) {
> + pr_err("%s: failed to register family %s (%d)\n",
> + KBUILD_MODNAME, name, ret);
> + goto fail3;
> + }
> +
> + pr_info("%s: registered genl family for channel %d: %s\n",
> + KBUILD_MODNAME, id, name);
> + dev->cstate = nl;
> +
> + return 0;
> +
> +fail3:
> + kfree(nl->ops);
> +fail2:
> + kfree(nl);
> +fail1:
> + return ret;
> +}
> +
> +/* Shuts down the netlink API for a sniffer channel
> + * and frees resources
> + */
> +void snf_netlink_release(struct snf_chan *dev)
> +{
> + struct snf_netlink *nl = (struct snf_netlink *)dev->cstate;
> + /* Unregister family and free ops
> + * NOTE: this will also unregister the ops and the mcast group
> + */
> + genl_unregister_family(&nl->fml);
> + pr_info("%s: unregistered genl family: %s\n",
> + KBUILD_MODNAME, nl->fml.name);
> +
> + kfree(nl->ops);
> + kfree(nl);
> + dev->cstate = NULL;
> +}
> +
> +/* pre_doit function that retrieves a pointer to the sniffer channel device
> + * from the instance and channel number stored in the ops internal_flag field
> + */
> +static int pre_doit_func(const struct genl_ops *ops,
> + struct sk_buff *skb,
> + struct genl_info *info)
> +{
> + info->user_ptr[0] = snf_channel_get(ops->internal_flags);
> + return info->user_ptr[0] ? 0 : -ENODEV;
> +}
> +
> +/* post_doit function that releases a sniffer channel device */
> +static void post_doit_func(const struct genl_ops *ops,
> + struct sk_buff *skb,
> + struct genl_info *info)
> +{
> + snf_channel_put(ops->internal_flags);
> +}
> +
> +/* doit command handlers */
> +
> +/* Start the sniffer channel */
> +static int do_it_start(struct sk_buff *skb, struct genl_info *info)
> +{
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> +
> + return dev->start(dev);
> +}
> +
> +/* Stop the sniffer channel */
> +static int do_it_stop(struct sk_buff *skb, struct genl_info *info)
> +{
> + int ret;
> + struct snf_match_evt mt;
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> +
> + ret = dev->stop(dev);
> + if (ret < 0)
> + return ret;
> +
> + /* Multicast an empty match event to notify any user-space
> + * listeners that the sniffer is stopping
> + */
> + memset(&mt, 0, sizeof(mt));
> + return snf_channel_notify_match(dev, &mt);
> +}
> +
> +/* Set the command pattern. The string is received in a nested
> + * attribute containing a sequence of 16-bit valued.
> + * Each value consists of a command (8 bits) and data (8 bits)
> +*/
> +static int do_it_set_pattern(struct sk_buff *skb, struct genl_info *info)
> +{
> + int ret = 0;
> + int rem, count;
> + struct nlattr *nla;
> + u16 entry;
> + u8 *buf = NULL;
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> + int max_entries = dev->max_ptn_entries(dev);
> +
> + if (!info->attrs[SNF_ATTR_PATTERN]) {
> + ret = -EINVAL;
> + goto fail;
> + }
> +
> + ret = nla_validate_nested(info->attrs[SNF_ATTR_PATTERN],
> + SNF_ATTR_PTN_ENTRY, snf_ptn_policy);
> + if (ret < 0)
> + goto fail;
> +
> + buf = kmalloc(max_entries*2, GFP_KERNEL);
> + if (!buf) {
> + ret = -ENOMEM;
> + goto fail;
> + }
> +
> + /* Iterate over the contents of the nested attribute
> + * and extract into the buffer
> + */
> + count = 0;
> + nla_for_each_nested(nla, info->attrs[SNF_ATTR_PATTERN], rem) {
> + if (count >= max_entries) {
> + ret = -EINVAL;
> + goto fail;
> + }
> + entry = nla_get_u16(nla);
> + buf[2*count] = PTNENTRY_CMD(entry);
> + buf[2*count + 1] = PTNENTRY_DATA(entry);
> + count++;
> + }
> +
> + ret = dev->set_pattern(dev, buf, count);
> +
> +fail:
> + kfree(buf);
> + return ret;
> +}
> +
> +/* Number of pending match events */
> +static int do_it_num_rec_avail(struct sk_buff *skb, struct genl_info *info)
> +{
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> +
> + return send_reply_uint32(
> + info,
> + SNF_CMD_NUMRECAVAIL,
> + SNF_ATTR_NUMRECAVAIL,
> + dev->num_recs_avail(dev));
> +}
> +
> +/* Max number of commands that are supported in the command pattern */
> +static int do_it_ptn_max_cmds(struct sk_buff *skb, struct genl_info *info)
> +{
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> +
> + return send_reply_uint32(
> + info,
> + SNF_CMD_PTNMAXCMDS,
> + SNF_ATTR_PTNMAXCMDS,
> + dev->max_ptn_entries(dev));
> +}
> +
> +/* Max bytes that can be returned by a packet match event */
> +static int do_it_max_match_bytes(struct sk_buff *skb, struct genl_info *info)
> +{
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> +
> + return send_reply_uint32(
> + info,
> + SNF_CMD_MAXMATCHBYTES,
> + SNF_ATTR_MAXMATCHBYTES,
> + dev->max_match_bytes(dev));
> +}
> +
> +/* Helper function for sending a reply containing a single u32 attribute */
> +static int send_reply_uint32(struct genl_info *info, int cmd, int attr, u32 val)
> +{
> + void *hdr;
> + int ret = 0;
> + struct sk_buff *msg;
> + struct snf_chan *dev = (struct snf_chan *)info->user_ptr[0];
> + struct snf_netlink *nl = (struct snf_netlink *)dev->cstate;
> +
> + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
> + if (!msg) {
> + ret = -ENOMEM;
> + goto fail;
> + }
> +
> + hdr = genlmsg_put_reply(msg, info, &nl->fml, 0, cmd);
> + if (!hdr) {
> + ret = -EMSGSIZE;
> + goto fail;
> + }
> + ret = nla_put_u32(msg, attr, val);
> + if (ret < 0)
> + goto fail;
> + ret = genlmsg_end(msg, hdr);
> + if (ret < 0)
> + goto fail;
> +
> + return genlmsg_reply(msg, info);
> +
> +fail:
> + if (msg)
> + nlmsg_free(msg);
> + return ret;
> +}
> +
> diff --git a/drivers/net/pkt-sniffer/core/nl.h b/drivers/net/pkt-sniffer/core/nl.h
> new file mode 100644
> index 0000000..f7bf579
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/core/nl.h
> @@ -0,0 +1,34 @@
> +/*
> + * Packet sniffer core driver: generic netlink interface
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#ifndef __SNF_NL_H
> +#define __SNF_NL_H
> +
> +#include <net/genetlink.h>
> +#include "snf_core.h"
> +
> +/* Initialise netlink interface for a sniffer channel,
> + * register netlink families etc.
> + */
> +int snf_netlink_init(int id, struct snf_chan *dev, const char *name);
> +
> +/* Shutdown netlink interface, unregister
> + * families etc.
> + */
> +void snf_netlink_release(struct snf_chan *dev);
> +
> +#endif
> diff --git a/drivers/net/pkt-sniffer/core/snf_core.h b/drivers/net/pkt-sniffer/core/snf_core.h
> new file mode 100644
> index 0000000..062de70
> --- /dev/null
> +++ b/drivers/net/pkt-sniffer/core/snf_core.h
> @@ -0,0 +1,64 @@
> +/*
> + * Packet sniffer core driver
> + * - this header provides the interface to specific backend packet
> + * sniffer implementations
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#ifndef __SNF_CORE_H
> +#define __SNF_CORE_H
> +
> +#include <linux/types.h>
> +
> +/* This is a global maximum. Each backend will have its own limit */
> +#define MAX_MATCH_BYTES 512
> +
> +/* Sniffer channel data structure */
> +struct snf_chan {
> + int (*start)(struct snf_chan *dev);
> + int (*stop)(struct snf_chan *dev);
> + int (*set_pattern)(struct snf_chan *dev, const u8 *pattern, int count);
> + int (*num_recs_avail)(struct snf_chan *dev);
> + int (*max_ptn_entries)(struct snf_chan *dev);
> + int (*max_match_bytes)(struct snf_chan *dev);
> +
> + void *cstate;
> +};
> +
> +/* Data from a sniffer match event */
> +struct snf_match_evt {
> + int ts_valid; /* flag indicating if timestamp is present */
> + u64 ts; /* timestamp value */
> + u8 data[MAX_MATCH_BYTES]; /* packet data bytes matched by sniffer */
> + int len; /* number of valid bytes in the 'data' buffer */
> +};
> +
> +/* Adds a sniffer channel to the registry */
> +int snf_channel_add(struct snf_chan *dev, const char *name);
> +
> +/* Removes the channel with the specified id from the registry */
> +int snf_channel_remove(int id);
> +
> +/* Returns handle to a channel and increments reference count */
> +struct snf_chan *snf_channel_get(int id);
> +
> +/* Decrements reference count for the specified channel */
> +void snf_channel_put(int id);
> +
> +/* Multicast a notification to user space for a sniffer match event */
> +int snf_channel_notify_match(struct snf_chan *dev, struct snf_match_evt *mt);
> +
> +#endif
> +
> diff --git a/include/linux/pkt_sniffer.h b/include/linux/pkt_sniffer.h
> new file mode 100644
> index 0000000..3e73d14
> --- /dev/null
> +++ b/include/linux/pkt_sniffer.h
> @@ -0,0 +1,89 @@
> +/*
> + * Linn packet sniffer driver interface
> + *
> + * Copyright (C) 2015 Linn Products Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Written by:
> + * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
> + */
> +#ifndef __PKT_SNIFFER_H
> +#define __PKT_SNIFFER_H
> +
> +/* Commands for the pattern string */
> +#define PTN_CMD_DONTCARE 0
> +#define PTN_CMD_MATCH 1
> +#define PTN_CMD_COPY 2
> +#define PTN_CMD_MATCHSTAMP 3
> +#define PTN_CMD_COPYDONE 4
> +
> +/* Creates an entry for the pattern string.
> + * An entry consists of a command byte and a data byte
> +*/
> +#define MAKE_PTN_ENTRY(cmd, data) (((((int)cmd) & 0xff) << 8) | (data & 0xff))
> +/* Gets the cmd and data portion of a pattern string entry */
> +#define PTNENTRY_CMD(val) (((val) >> 8) & 0xff)
> +#define PTNENTRY_DATA(val) ((val) & 0xff)
> +
> +/* Generic Netlink commands */
> +enum {
> + SNF_CMD_UNSPEC,
> + SNF_CMD_START, /* start the sniffer */
> + SNF_CMD_STOP, /* stop the sniffer */
> + SNF_CMD_SETPATTERN, /* set the command pattern */
> + SNF_CMD_NUMRECAVAIL, /* number of pending match events */
> + SNF_CMD_MATCHEVENT, /* match event notification */
> + SNF_CMD_PTNMAXCMDS, /* max number of commands supported */
> + SNF_CMD_MAXMATCHBYTES, /* max number of bytes in match event */
> + __SNF_CMD_MAX
> +};
> +#define SNF_CMD_MAX (__SNF_CMD_MAX - 1)
> +
> +/* Generic Netlink attributes */
> +enum {
> + SNF_ATTR_UNSPEC,
> + SNF_ATTR_PTNMAXCMDS, /* max number of commands supported */
> + SNF_ATTR_PATTERN, /* nested attribute containing commands */
> + SNF_ATTR_NUMRECAVAIL, /* number of pending match events */
> + SNF_ATTR_MATCHEVENT, /* nested attribute for a match event */
> + SNF_ATTR_MAXMATCHBYTES, /* max bytes in a match event */
> + __SNF_ATTR_MAX
> +};
> +#define SNF_ATTR_MAX (__SNF_ATTR_MAX - 1)
> +
> +/* Attributes that are included in the nested attribute
> + * for the command string
> + */
> +enum {
> + SNF_ATTR_PTN_UNSPEC,
> + SNF_ATTR_PTN_ENTRY, /* command entry containing a command id */
> + __SNF_ATTR_PTN_MAX /* and data byte */
> +};
> +#define SNF_ATTR_PTN_MAX (__SNF_ATTR_PTN_MAX - 1)
> +
> +/* Attributes included in the nested attribute
> + * of a match event notification
> + */
> +enum {
> + SNF_ATTR_MATCH_UNSPEC,
> + SNF_ATTR_MATCH_TS, /* timestamp (returned with a match event) */
> + SNF_ATTR_MATCH_PKTBYTE, /* packet data (returned with a match event) */
> + __SNF_ATTR_MATCH_MAX
> +};
> +#define SNF_ATTR_MATCH_MAX (__SNF_ATTR_MATCH_MAX - 1)
> +
> +/* Family version */
> +#define SNF_GNL_VERSION 1
> +
> +/* Multicast group name */
> +#define SNF_EVENT_GRP "snf_evt_grp"
> +
> +#endif
>
--
Florian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] drivers: net: xgene: fix: Out of order descriptor bytes read
From: David Miller @ 2015-01-26 22:34 UTC (permalink / raw)
To: isubramanian
Cc: eric.dumazet, netdev, linux-kernel, linux-arm-kernel, mlangsdo,
patches, kchudgar
In-Reply-To: <CAKh23FmxvV82mVrHq5jv-FE+e6u6CkW+xL_a2_ULAQgP_mM2VA@mail.gmail.com>
From: Iyappan Subramanian <isubramanian@apm.com>
Date: Mon, 26 Jan 2015 13:12:23 -0800
>>> @@ -369,6 +369,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
>>> if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
>>> break;
>>>
>>> + /* read fpqnum field after dataaddr field */
>>> + smp_rmb();
>>> if (is_rx_desc(raw_desc))
>>> ret = xgene_enet_rx_frame(ring, raw_desc);
>>> else
>>
>> Reading your changelog, it looks like you need a plain rmb() here.
>
> rmb() translates into dsb, which in arm64 serializes everything
> including instructions and thus expensive compared to dmb.
>
> Do you see any issue with smp_rmb() (which translates into dmb) ?
smp_rmb() is not appropriate. You're not serializing accesses between
two cpus, you're serializing the cpu with the device.
^ permalink raw reply
* Re: [PATCH 1/2] rhashtable: Introduce rhashtable_walk_*
From: David Miller @ 2015-01-26 22:36 UTC (permalink / raw)
To: herbert
Cc: David.Laight, tgraf, ying.xue, kaber, paulmck, netdev,
netfilter-devel
In-Reply-To: <20150126222259.GC30116@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue, 27 Jan 2015 09:23:00 +1100
> On Mon, Jan 26, 2015 at 10:09:24AM +0000, David Laight wrote:
>>
>> That doesn't look right to me.
>> Surely you shouldn't be calling rcu_read_lock() when the mutex
>> request is interrupted.
>>
>> So maybe:
>> err = mutex_lock_interruptible(&ht->mutex);
>> if (err)
>> return err;
>> rcu_read_lock();
>
> No, we need to grab the RCU read lock while holding the mutex
> in order to prevent future resizes from happening once we release
> the mutex.
>
> We don't want to hold the mutex which would stop other walks from
> starting.
I really think the amount of time and effort being put into making
the walker function properly is excessive.
Let's just say that if you want to use rhashtable, you have to use a
linked list, or similar separate mechanism, to have stable walks of
the entire set of objects.
^ permalink raw reply
* RE: [PATCH] i40e: don't enable and init FCOE by default when do PF reset
From: Dev, Vasu @ 2015-01-26 22:38 UTC (permalink / raw)
To: ethan zhao
Cc: Kirsher, Jeffrey T, Ethan Zhao, Ronciak, John, Brandeburg, Jesse,
Allan, Bruce W, Wyborny, Carolyn, Skidmore, Donald C,
Rose, Gregory V, Vick, Matthew, Williams, Mitch A, Parikh, Neerav,
Linux NICS, e1000-devel@lists.sourceforge.net,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
brian.maly@oracle.com
In-Reply-To: <54BDB7F3.2020400@oracle.com>
> -----Original Message-----
> From: ethan zhao [mailto:ethan.zhao@oracle.com]
> Sent: Monday, January 19, 2015 6:06 PM
> To: Dev, Vasu
> Cc: Kirsher, Jeffrey T; Ethan Zhao; Ronciak, John; Brandeburg, Jesse; Allan,
> Bruce W; Wyborny, Carolyn; Skidmore, Donald C; Rose, Gregory V; Vick,
> Matthew; Williams, Mitch A; Parikh, Neerav; Linux NICS; e1000-
> devel@lists.sourceforge.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; brian.maly@oracle.com
> Subject: Re: [PATCH] i40e: don't enable and init FCOE by default when do PF
> reset
>
>
> On 2015/1/20 5:10, Dev, Vasu wrote:
> >> -----Original Message-----
> >> From: ethan zhao [mailto:ethan.zhao@oracle.com]
> >> Sent: Friday, January 16, 2015 7:01 PM
> >> To: Kirsher, Jeffrey T
> >> Cc: Dev, Vasu; Ethan Zhao; Ronciak, John; Brandeburg, Jesse; Allan,
> >> Bruce W; Wyborny, Carolyn; Skidmore, Donald C; Rose, Gregory V; Vick,
> >> Matthew; Williams, Mitch A; Parikh, Neerav; Linux NICS; e1000-
> >> devel@lists.sourceforge.net; netdev@vger.kernel.org; linux-
> >> kernel@vger.kernel.org; brian.maly@oracle.com
> >> Subject: Re: [PATCH] i40e: don't enable and init FCOE by default when
> >> do PF reset
> >>
> >> Vasu,
> >>
> >> What' your idea about the v2, any suggestion ? Jeff is looking
> >> forward to see it.
> >>
> > Jeff was asking for v2 in response to your last comment as "disable FCOE as
> default configuration as a temporary step" but I think that is the fix and user
> should n't enable FCoE until they have FCoE enabled X710 FCoE with either
> fabric or VN2VN mode FCoE setup.
> As a Linux distro, we don't know users have FCoE capable X710 or not, so
> we couldn't disable the FCoE configuration
> by default in the released kernel except FCoE is officially not supported yet
> with X710, but if yes, fix those bugs I
> mentioned is the only choice.
>
Yes must be fixed but I don't see your VLAN issue in my XL710 setup having engineering FW 4.33 with FCoE enabled, I could create VLANs and bring them up or down.
As for the patch under discussion, it won't help any way whether fcoe enabled or not as I explained before. So I guess my setup differs in XL710 FW version, so upgrading FW should fix the issue and then you could keep FCoE configuration enabled in your distro w/o any concern to XL710 FCoE capable or not in XL710. We can take any FW related further discussion off list.
Thanks,
Vasu
>
> Thanks,
> Ethan
>
>
> >
> > Thanks,
> > Vasu
> >
> >> Thanks,
> >> Ethan
> >>
> >>
> >> On 2015/1/16 22:47, Jeff Kirsher wrote:
> >>> On Fri, 2015-01-16 at 09:48 +0800, ethan zhao wrote:
> >>>> Vasu,
> >>>>
> >>>> OK, disable FCOE as default configuration as a temporary step
> >>>> to make it work.
> >>> Sounds like I should expect a v2 coming, correct?
> >>>
> >>>> Thanks,
> >>>> Ethan
> >>>>
> >>>> On 2015/1/16 7:45, Dev, Vasu wrote:
> >>>>>> -----Original Message-----
> >>>>>> From: ethan zhao [mailto:ethan.zhao@oracle.com]
> >>>>>> Sent: Tuesday, January 13, 2015 6:41 PM
> >>>>>> To: Dev, Vasu
> >>>>>> Cc: Ethan Zhao; Ronciak, John; Kirsher, Jeffrey T; Brandeburg,
> >>>>>> Jesse; Allan, Bruce W; Wyborny, Carolyn; Skidmore, Donald C;
> >>>>>> Rose, Gregory V; Vick, Matthew; Williams, Mitch A; Parikh,
> >>>>>> Neerav; Linux NICS; e1000- devel@lists.sourceforge.net;
> >>>>>> netdev@vger.kernel.org;
> >>>>>> linux- kernel@vger.kernel.org; brian.maly@oracle.com
> >>>>>> Subject: Re: [PATCH] i40e: don't enable and init FCOE by default
> >>>>>> when do PF reset
> >>>>>>
> >>>>>> Vasu,
> >>>>>>
> >>>>>> On 2015/1/14 3:38, Dev, Vasu wrote:
> >>>>>>>> -----Original Message-----
> >>>>>>>>>>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c
> >>>>>>>>>>> b/drivers/net/ethernet/intel/i40e/i40e_main.c
> >>>>>>>>>>> index a5f2660..a2572cc 100644
> >>>>>>>>>>> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> >>>>>>>>>>> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> >>>>>>>>>>> @@ -6180,9 +6180,12 @@ static void
> >>>>>>>>>>> i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
> >>>>>>>>>>> }
> >>>>>>>>>>> #endif /* CONFIG_I40E_DCB */
> >>>>>>>>>>> #ifdef I40E_FCOE
> >>>>>>>>>>> - ret = i40e_init_pf_fcoe(pf);
> >>>>>>>>>>> - if (ret)
> >>>>>>>>>>> - dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n",
> ret);
> >>>>>>>>>>> + if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
> >>>>>>>>>>> + ret = i40e_init_pf_fcoe(pf);
> >>>>>>>>> Calling i40e_init_pf_fcoe() here conflicts with its
> >>>>>>>> I40E_FLAG_FCOE_ENABLED pre-condition since
> >>>>>> I40E_FLAG_FCOE_ENABLED is
> >>>>>>>> set by very same i40e_init_pf_fcoe(), in turn
> >>>>>>>> i40e_init_pf_fcoe() will never get called.
> >>>>>>>>
> >>>>>>>> I don't think so, here ,i40e_reset_and_rebuild() is not the
> >>>>>>>> only and the first place that i40e_init_pf_fcoe() is called,
> >>>>>>>> see i40e_probe(), that is the first chance.
> >>>>>>>>
> >>>>>>>> i40e_probe()
> >>>>>>>> -->i40e_sw_init()
> >>>>>>>> -->i40e_init_pf_fcoe()
> >>>>>>>>
> >>>>>>>> And the I40E_FLAG_FCOE_ENABLED is possible be set by
> >>>>>>>> i40e_fcoe_enable() or i40e_fcoe_disable() interface before the
> >>>>>>>> reset action is to be done.
> >>>>>>>>
> >>>>>>> It is set by i40e_init_pf_fcoe() and you are right that the
> >>>>>>> modified call flow
> >>>>>> by your patch won't impact setting of I40E_FLAG_FCOE_ENABLED
> >> anyway
> >>>>>> which could have prevented calling i40e_init_pf_fcoe() as I
> >>>>>> described above, so this is not an issue with the patch.
> >>>>>>>> BTW, the reason I post this patch is that we hit a bug, after
> >>>>>>>> setup vlan, the PF is enabled to FCOE.
> >>>>>>>>
> >>>>>>> Then that BUG would still remain un-fixed and calling
> >>>>>>> i40e_init_pf_fcoe()
> >>>>>> under I40E_FLAG_FCOE_ENABLED flag really won't affect call flow
> >>>>>> to fix anything. I mean I40E_FLAG_FCOE_ENABLED condition will be
> >>>>>> true with "pf-
> >>>>>>> hw.func_caps.fcoe == true" and otherwise calling
> >>>>>>> i40e_init_pf_fcoe() simply
> >>>>>> returns back early on after checking "pf->hw.func_caps.fcoe ==
> >>>>>> false", so how that bug is fixed here by added
> >> I40E_FLAG_FCOE_ENABLED condition ?
> >>>>>> What is the bug ?
> >>>>>> The func_caps.fcoe is assigned by following call path, under
> >>>>>> our test environment,
> >>>>>>
> >>>>>> i40e_probe()
> >>>>>> ->i40e_get_capabilities()
> >>>>>> ->i40e_aq_discover_capabilities()
> >>>>>> ->i40e_parse_discover_capabilities()
> >>>>>>
> >>>>>> Or
> >>>>>>
> >>>>>> i40e_reset_and_rebuild()
> >>>>>> ->i40e_get_capabilities()
> >>>>>> ->i40e_aq_discover_capabilities()
> >>>>>> ->i40e_parse_discover_capabilities()
> >>>>>>
> >>>>>> Under our test environment, the "pf->hw.func_caps.fcoe" is
> >>>>>> true. so if
> >>>>>> i40e_reset_and_rebuild() is called for VLAN setup, ethtool
> >>>>>> diagnostic
> >> test.
> >>>>>> And then i40e_init_pf_fcoe() is to be called,
> >>>>>>
> >>>>>> While if (!pf->hw.func_caps.fcoe) wouldn't return,
> >>>>>>
> >>>>> I said it would return with "pf->hw.func_caps.fcoe == false" in my
> >>>>> last
> >> response, more details below.
> >>>>>> So pf->flags is set to I40E_FLAG_FCOE_ENABLED.
> >>>>>>
> >>>>>> With my patch, i40e_init_pf_fcoe() is only called after
> >>>>>> I40E_FLAG_FCOE_ENABLED is set before reset.
> >>>>>>
> >>>>>> Enable FCOE in i40e_probe() or not is another issue.
> >>>>>>
> >>>>> Nope since both cases we should do i40e_init_pf_fcoe() or don't
> >>>>> based
> >> on fcoe cap true or false.
> >>>>> I don't have much to add as I described before with the your patch
> >>>>> that
> >> "calling i40e_init_pf_fcoe() under I40E_FLAG_FCOE_ENABLED flag
> >> really won't affect call flow to fix anything. I mean
> >> I40E_FLAG_FCOE_ENABLED condition will be true with
> >> "pf->hw.func_caps.fcoe == true" and otherwise calling
> >> i40e_init_pf_fcoe() simply returns back early on after checking "pf-
> >>> hw.func_caps.fcoe == false".
> >>>>> May be I'm missing something, I guess next either go with
> >> CONFIG_I40E_FCOE disable as I suggested before and now it in upstream
> >> kernel or we can have further off list discussion to fix the issue
> >> you are trying to fix with the patch.
> >>>>> Thanks,
> >>>>> Vasu
> >>>>>
> >>>>>> Thanks,
> >>>>>> Ethan
> >>>>>>
> >>>>>>
> >>>>>>>>> Jeff Kirsher should be getting out a patch queued by me which
> >>>>>>>>> adds
> >>>>>>>> I40E_FCoE Kbuild option, in that FCoE is disabled by default
> >>>>>>>> and user could enable FCoE only if needed, that patch would do
> >>>>>>>> same of skipping
> >>>>>>>> i40e_init_pf_fcoe() whether FCoE capability in device enabled
> >>>>>>>> or not in default config.
> >>>>>>>> The following patch will not fix the above issue --
> >>>>>>>> configuration of PF will be changed via reset.
> >>>>>>>> How about the FCOE is configured and disabled by
> >>>>>>>> i40e_fcoe_disable() , then reset happens ?
> >>>>>>>>
> >>>>>>> May be but if the BUG is due to FCoE being enabled then having
> >>>>>>> it disabled
> >>>>>> in config will avoid the bug for non FCoE config option and once
> >>>>>> bug is understood then that has to be fixed for FCoE enabled
> >>>>>> config also as I asked above.
> >>>>>>> Thanks Ethan for detailed response.
> >>>>>>> Vasu
> >>>>>>>
> >>>>>>>>> From patchwork Wed Oct 2 23:26:08 2013
> >>>>>>>>> Content-Type: text/plain; charset="utf-8"
> >>>>>>>>> MIME-Version: 1.0
> >>>>>>>>> Content-Transfer-Encoding: 7bit
> >>>>>>>>> Subject: [net] i40e: adds FCoE configure option
> >>>>>>>>> Date: Thu, 03 Oct 2013 07:26:08 -0000
> >>>>>>>>> From: Vasu Dev <vasu.dev@intel.com>
> >>>>>>>>> X-Patchwork-Id: 11797
> >>>>>>>>>
> >>>>>>>>> Adds FCoE config option I40E_FCOE, so that FCoE can be enabled
> >>>>>>>>> as needed but otherwise have it disabled by default.
> >>>>>>>>>
> >>>>>>>>> This also eliminate multiple FCoE config checks, instead now
> >>>>>>>>> just one config check for CONFIG_I40E_FCOE.
> >>>>>>>>>
> >>>>>>>>> The I40E FCoE was added with 3.17 kernel and therefore this
> >>>>>>>>> patch shall be applied to stable 3.17 kernel also.
> >>>>>>>>>
> >>>>>>>>> CC: <stable@vger.kernel.org>
> >>>>>>>>> Signed-off-by: Vasu Dev <vasu.dev@intel.com>
> >>>>>>>>> Tested-by: Jim Young <jamesx.m.young@intel.com>
> >>>>>>>>>
> >>>>>>>>> ---
> >>>>>>>>> drivers/net/ethernet/intel/Kconfig | 11 +++++++++++
> >>>>>>>>> drivers/net/ethernet/intel/i40e/Makefile | 2 +-
> >>>>>>>>> drivers/net/ethernet/intel/i40e/i40e_osdep.h | 4 ++--
> >>>>>>>>> 3 files changed, 14 insertions(+), 3 deletions(-)
> >>>>>>>>>
> >>>>>>>>> diff --git a/drivers/net/ethernet/intel/Kconfig
> >>>>>>>>> b/drivers/net/ethernet/intel/Kconfig
> >>>>>>>>> index 5b8300a..4d61ef5 100644
> >>>>>>>>> --- a/drivers/net/ethernet/intel/Kconfig
> >>>>>>>>> +++ b/drivers/net/ethernet/intel/Kconfig
> >>>>>>>>> @@ -281,6 +281,17 @@ config I40E_DCB
> >>>>>>>>>
> >>>>>>>>> If unsure, say N.
> >>>>>>>>>
> >>>>>>>>> +config I40E_FCOE
> >>>>>>>>> + bool "Fibre Channel over Ethernet (FCoE)"
> >>>>>>>>> + default n
> >>>>>>>>> + depends on I40E && DCB && FCOE
> >>>>>>>>> + ---help---
> >>>>>>>>> + Say Y here if you want to use Fibre Channel over
> >>>>>>>>> +Ethernet
> >> (FCoE)
> >>>>>>>>> + in the driver. This will create new netdev for exclusive FCoE
> >>>>>>>>> + use with XL710 FCoE offloads enabled.
> >>>>>>>>> +
> >>>>>>>>> + If unsure, say N.
> >>>>>>>>> +
> >>>>>>>>> config I40EVF
> >>>>>>>>> tristate "Intel(R) XL710 X710 Virtual Function
> >>>>>>>>> Ethernet
> >> support"
> >>>>>>>>> depends on PCI_MSI diff --git
> >>>>>>>>> a/drivers/net/ethernet/intel/i40e/Makefile
> >>>>>>>>> b/drivers/net/ethernet/intel/i40e/Makefile
> >>>>>>>>> index 4b94ddb..c405819 100644
> >>>>>>>>> --- a/drivers/net/ethernet/intel/i40e/Makefile
> >>>>>>>>> +++ b/drivers/net/ethernet/intel/i40e/Makefile
> >>>>>>>>> @@ -44,4 +44,4 @@ i40e-objs := i40e_main.o \
> >>>>>>>>> i40e_virtchnl_pf.o
> >>>>>>>>>
> >>>>>>>>> i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o
> >>>>>>>>> -i40e-$(CONFIG_FCOE:m=y) += i40e_fcoe.o
> >>>>>>>>> +i40e-$(CONFIG_I40E_FCOE) += i40e_fcoe.o
> >>>>>>>>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h
> >>>>>>>>> b/drivers/net/ethernet/intel/i40e/i40e_osdep.h
> >>>>>>>>> index 045b5c4..ad802dd 100644
> >>>>>>>>> --- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h
> >>>>>>>>> +++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h
> >>>>>>>>> @@ -78,7 +78,7 @@ do { \
> >>>>>>>>> } while (0)
> >>>>>>>>>
> >>>>>>>>> typedef enum i40e_status_code i40e_status; -#if
> >>>>>>>>> defined(CONFIG_FCOE)
> >>>>>>>>> || defined(CONFIG_FCOE_MODULE)
> >>>>>>>>> +#ifdef CONFIG_I40E_FCOE
> >>>>>>>>> #define I40E_FCOE
> >>>>>>>>> -#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
> >>>>>>>>> +#endif
> >>>>>>>>> #endif /* _I40E_OSDEP_H_ */
> >>>>>>>>>
> >>>>>>>>>>> + if (ret)
> >>>>>>>>>>> + dev_info(&pf->pdev->dev,
> >>>>>>>>>>> + "init_pf_fcoe failed: %d\n", ret);
> >>>>>>>>>>> + }
> >>>>>>>>>>>
> >>>>>>>>>>> #endif
> >>>>>>>>>>> /* do basic switch setup */
> >>>>>>>>>>> --
> >>>>>>>>>>> 1.8.3.1
> >>>>>>>> Thanks,
> >>>>>>>> Ethan
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox