Thread (3 messages) 3 messages, 2 authors, 2019-09-09

Re: [PATCH] rtl8xxxu: add bluetooth co-existence support for single antenna

flat view

From: Jes Sorensen <jes.sorensen@gmail.com>
Date: 2019-09-09 11:13:50
Also in: lkml, netdev

On 9/3/19 1:37 AM, Chris Chiu wrote:
The RTL8723BU suffers the wifi disconnection problem while bluetooth
device connected. While wifi is doing tx/rx, the bluetooth will scan
without results. This is due to the wifi and bluetooth share the same
single antenna for RF communication and they need to have a mechanism
to collaborate.

BT information is provided via the packet sent from co-processor to
host (C2H). It contains the status of BT but the rtl8723bu_handle_c2h
dose not really handle it. And there's no bluetooth coexistence
mechanism to deal with it.

This commit adds a workqueue to set the tdma configurations and
coefficient table per the parsed bluetooth link status and given
wifi connection state. The tdma/coef table comes from the vendor
driver code of the RTL8192EU and RTL8723BU. However, this commit is
only for single antenna scenario which RTL8192EU is default dual
antenna. The rtl8xxxu_parse_rxdesc24 which invokes the handle_c2h
is only for 8723b and 8192e so the mechanism is expected to work
on both chips with single antenna. Note RTL8192EU dual antenna is
not supported.
I am pretty excited to see this! It always bugged me the bluetooth
driver was allowed to be applied breaking the existing wifi driver.

Except for some cosmetic stuff, I am all happy with this.
quoted hunk ↗ jump to hunk
Signed-off-by: Chris Chiu <redacted>
---
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  37 +++
 .../realtek/rtl8xxxu/rtl8xxxu_8723b.c         |   2 -
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 243 +++++++++++++++++-
 3 files changed, 275 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 582c2a346cec..22e95b11bfbb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
quoted hunk ↗ jump to hunk
+
+struct rtl8xxxu_btcoex {
+	u8      bt_status;
+	bool	bt_busy;
+	bool	has_sco;
+	bool	has_a2dp;
+	bool    has_hid;
+	bool    has_pan;
+	bool	hid_only;
+	bool	a2dp_only;
+	bool    c2h_bt_inquiry;
+};
bool is large, maybe just use flags or u8's for this? Not a big deal though.
quoted hunk ↗ jump to hunk
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index a6f358b9e447..4f72c2d14d44 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
quoted hunk ↗ jump to hunk
+	if (!btcoex->has_a2dp &&
+	    !btcoex->has_sco &&
+	    !btcoex->has_pan &&
+	    btcoex->has_hid)
This should all fit in one line - 80 characters
quoted hunk ↗ jump to hunk
+		btcoex->hid_only = true;
+	else
+		btcoex->hid_only = false;
+
+	if (!btcoex->has_sco &&
+	    !btcoex->has_pan &&
+	    !btcoex->has_hid &&
+	    btcoex->has_a2dp)
Ditto
quoted hunk ↗ jump to hunk
+static void rtl8xxxu_c2hcmd_callback(struct work_struct *work)
+{
+	struct rtl8xxxu_priv *priv;
+	struct rtl8723bu_c2h *c2h;
+	struct ieee80211_vif *vif;
+	struct device *dev;
+	struct sk_buff *skb = NULL;
+	unsigned long flags;
+	int len;
+	u8 bt_info = 0;
+	struct rtl8xxxu_btcoex *btcoex;
+
+	priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work);
+	vif = priv->vif;
+	btcoex = &priv->bt_coex;
+	dev = &priv->udev->dev;
+
+	if (priv->rf_paths > 1)
+		goto out;
+
+	while (!skb_queue_empty(&priv->c2hcmd_queue)) {
+		spin_lock_irqsave(&priv->c2hcmd_lock, flags);
+		skb = __skb_dequeue(&priv->c2hcmd_queue);
+		spin_unlock_irqrestore(&priv->c2hcmd_lock, flags);
+
+		c2h = (struct rtl8723bu_c2h *)skb->data;
+		len = skb->len - 2;
+
+		switch (c2h->id) {
+		case C2H_8723B_BT_INFO:
+			bt_info = c2h->bt_info.bt_info;
+
+			rtl8723bu_update_bt_link_info(priv, bt_info);
+
+			if (btcoex->c2h_bt_inquiry) {
+				if (vif && !vif->bss_conf.assoc) {
+					rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
+					rtl8723bu_set_coex_with_type(priv, 0);
+				} else if (btcoex->has_sco ||
+					   btcoex->has_hid ||
+					   btcoex->has_a2dp) {
+					rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, 0x3, 0x11, 0x11);
+					rtl8723bu_set_coex_with_type(priv, 4);
+				} else if (btcoex->has_pan) {
+					rtl8723bu_set_ps_tdma(priv, 0x61, 0x3f, 0x3, 0x11, 0x11);
+					rtl8723bu_set_coex_with_type(priv, 4);
+				} else {
+					rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
+					rtl8723bu_set_coex_with_type(priv, 7);
+				}
+
+				return;
+			}
Kernel code is 80 characters wide - maybe create a btcoex helper
function for this?
quoted hunk ↗ jump to hunk
+
+			if (vif && vif->bss_conf.assoc) {
+				u32 val32 = 0;
+				u32 high_prio_tx = 0, high_prio_rx = 0;
+
+				val32 = rtl8xxxu_read32(priv, 0x770);
+				high_prio_tx = val32 & 0x0000ffff;
+				high_prio_rx = (val32  & 0xffff0000) >> 16;
+
+				if (btcoex->bt_busy) {
+					if (btcoex->hid_only) {
+						rtl8723bu_set_ps_tdma(priv, 0x61, 0x20, 0x3, 0x11, 0x11);
+						rtl8723bu_set_coex_with_type(priv, 5);
+					} else if (btcoex->a2dp_only) {
+						rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, 0x3, 0x11, 0x11);
+						rtl8723bu_set_coex_with_type(priv, 4);
+					} else if ((btcoex->has_a2dp &&
+						    btcoex->has_pan) ||
+						   (btcoex->has_hid &&
+						    btcoex->has_a2dp &&
+						    btcoex->has_pan)) {
+						rtl8723bu_set_ps_tdma(priv, 0x51, 0x21, 0x3, 0x10, 0x10);
+						rtl8723bu_set_coex_with_type(priv, 4);
+					} else if (btcoex->has_hid &&
+						 btcoex->has_a2dp) {
+						rtl8723bu_set_ps_tdma(priv, 0x51, 0x21, 0x3, 0x10, 0x10);
+						rtl8723bu_set_coex_with_type(priv, 3);
+					} else {
+						rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, 0x3, 0x11, 0x11);
+						rtl8723bu_set_coex_with_type(priv, 4);
+					}
Same here

Otherwise, thanks for digging into this, it's really great to see!

Cheers,
Jes
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help