Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net] ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too
From: Lubomir Rintel @ 2015-01-26 15:36 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: netdev
In-Reply-To: <131075b1c8770c414675094c292d394316e8cd17.1422281427.git.hannes@stressinduktion.org>

On Mon, 2015-01-26 at 15:11 +0100, Hannes Frederic Sowa wrote:
> Lubomir Rintel reported that during replacing a route the interface
> reference counter isn't correctly decremented.
> 
> To quote bug <https://bugzilla.kernel.org/show_bug.cgi?id=91941>:
> | [root@rhel7-5 lkundrak]# sh -x lal
> | + ip link add dev0 type dummy
> | + ip link set dev0 up
> | + ip link add dev1 type dummy
> | + ip link set dev1 up
> | + ip addr add 2001:db8:8086::2/64 dev dev0
> | + ip route add 2001:db8:8086::/48 dev dev0 proto static metric 20
> | + ip route add 2001:db8:8088::/48 dev dev1 proto static metric 10
> | + ip route replace 2001:db8:8086::/48 dev dev1 proto static metric 20
> | + ip link del dev0 type dummy
> | Message from syslogd@rhel7-5 at Jan 23 10:54:41 ...
> |  kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
> |
> | Message from syslogd@rhel7-5 at Jan 23 10:54:51 ...
> |  kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
> 
> During replacement of a rt6_info we must walk all parent nodes and check
> if the to be replaced rt6_info got propagated. If so, replace it with
> an alive one.
> 
> Reported-by: Lubomir Rintel <lkundrak@v3.sk>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---
>  net/ipv6/ip6_fib.c | 45 ++++++++++++++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 19 deletions(-)

Tested-by: Lubomir Rintel <lkundrak@v3.sk>

Thank you!
Lubo

^ permalink raw reply

* Re: [PATCH net] ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too
From: Eric Dumazet @ 2015-01-26 16:02 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: netdev, lkundrak
In-Reply-To: <131075b1c8770c414675094c292d394316e8cd17.1422281427.git.hannes@stressinduktion.org>

On Mon, 2015-01-26 at 15:11 +0100, Hannes Frederic Sowa wrote:
> Lubomir Rintel reported that during replacing a route the interface
> reference counter isn't correctly decremented.
> 
> To quote bug <https://bugzilla.kernel.org/show_bug.cgi?id=91941>:
> | [root@rhel7-5 lkundrak]# sh -x lal
> | + ip link add dev0 type dummy
> | + ip link set dev0 up
> | + ip link add dev1 type dummy
> | + ip link set dev1 up
> | + ip addr add 2001:db8:8086::2/64 dev dev0
> | + ip route add 2001:db8:8086::/48 dev dev0 proto static metric 20
> | + ip route add 2001:db8:8088::/48 dev dev1 proto static metric 10
> | + ip route replace 2001:db8:8086::/48 dev dev1 proto static metric 20
> | + ip link del dev0 type dummy
> | Message from syslogd@rhel7-5 at Jan 23 10:54:41 ...
> |  kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
> |
> | Message from syslogd@rhel7-5 at Jan 23 10:54:51 ...
> |  kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
> 
> During replacement of a rt6_info we must walk all parent nodes and check
> if the to be replaced rt6_info got propagated. If so, replace it with
> an alive one.
> 
> Reported-by: Lubomir Rintel <lkundrak@v3.sk>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>

Hi Hannes

Was this bug added in commit 4a287eba2de395713d8b2b2aeaa69fa086832d34
("IPv6 routing, NLM_F_* flag support: REPLACE and EXCL flags support,
warn about missing CREATE flag") ?

Thanks !

^ permalink raw reply

* Re: [PATCH net] ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too
From: Hannes Frederic Sowa @ 2015-01-26 16:08 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, lkundrak
In-Reply-To: <1422288129.29618.26.camel@edumazet-glaptop2.roam.corp.google.com>

On Mo, 2015-01-26 at 08:02 -0800, Eric Dumazet wrote:
> On Mon, 2015-01-26 at 15:11 +0100, Hannes Frederic Sowa wrote:
> > Lubomir Rintel reported that during replacing a route the interface
> > reference counter isn't correctly decremented.
> > 
> > To quote bug <https://bugzilla.kernel.org/show_bug.cgi?id=91941>:
> > | [root@rhel7-5 lkundrak]# sh -x lal
> > | + ip link add dev0 type dummy
> > | + ip link set dev0 up
> > | + ip link add dev1 type dummy
> > | + ip link set dev1 up
> > | + ip addr add 2001:db8:8086::2/64 dev dev0
> > | + ip route add 2001:db8:8086::/48 dev dev0 proto static metric 20
> > | + ip route add 2001:db8:8088::/48 dev dev1 proto static metric 10
> > | + ip route replace 2001:db8:8086::/48 dev dev1 proto static metric 20
> > | + ip link del dev0 type dummy
> > | Message from syslogd@rhel7-5 at Jan 23 10:54:41 ...
> > |  kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
> > |
> > | Message from syslogd@rhel7-5 at Jan 23 10:54:51 ...
> > |  kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
> > 
> > During replacement of a rt6_info we must walk all parent nodes and check
> > if the to be replaced rt6_info got propagated. If so, replace it with
> > an alive one.
> > 
> > Reported-by: Lubomir Rintel <lkundrak@v3.sk>
> > Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> 
> Hi Hannes
> 
> Was this bug added in commit 4a287eba2de395713d8b2b2aeaa69fa086832d34
> ("IPv6 routing, NLM_F_* flag support: REPLACE and EXCL flags support,
> warn about missing CREATE flag") ?

Yes, this patch added the hunk which introduced this problem. Sorry, I
didn't bother to look into git history which patch was responsible,
because I thought it might well be there from the beginning of the
stack.

Fixes: 4a287eba2de3957 ("IPv6 routing, NLM_F_* flag support: REPLACE and EXCL flags support, warn about missing CREATE flag")

^ permalink raw reply

* Re: [PATCH] net: macb: allow deffered probe of the driver
From: Nicolas Ferre @ 2015-01-26 16:08 UTC (permalink / raw)
  To: Nicolae Rosia, Boris BREZILLON
  Cc: netdev@vger.kernel.org, michal.simek@xilinx.com
In-Reply-To: <1422285264.2658.2.camel@uti.ro>

Le 26/01/2015 16:21, Nicolae Rosia a écrit :
> On Mon, 2015-01-26 at 15:37 +0100, Nicolas Ferre wrote:
>> Do you have a use case for this need?
> On my setup (Zynq Platform), the required clocks are
> provided by a module which is loaded after this driver,
> hence, the clock is not available at initialization time.

That's what I (actually Boris who I've consulted regarding this) felt.
Thanks for having confirmed this.

>> But anyway, it's not harmful:
>> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> Thank you.
> 
> Best regards,
> Nicolae Rosia
> 

Bye,
-- 
Nicolas Ferre

^ permalink raw reply

* RE: [PATCH v3 net-next] net: ipv6: Add sysctl entry to disable MTU updates from RA
From: Harout Hedeshian @ 2015-01-26 16:16 UTC (permalink / raw)
  To: 'Dan Williams'
  Cc: 'David Miller', netdev, 'Vadim Kochan'
In-Reply-To: <1422284628.2393.4.camel@dcbw.local>



> -----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 consist
 ency, 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 knowing, 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 goo
 d 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 have 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 kernel 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

^ permalink raw reply

* Re: [PATCH v3 net-next] net: ipv6: Add sysctl entry to disable MTU updates from RA
From: Hannes Frederic Sowa @ 2015-01-26 16:19 UTC (permalink / raw)
  To: David Miller; +Cc: harouth, netdev
In-Reply-To: <20150124.231432.1788575004982971514.davem@davemloft.net>

On Sa, 2015-01-24 at 23:14 -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?

Sometimes those advertised MTUs are used to perform DoS attacks /
performance-degrading attacks (force generation of fragments e.g.) on
hosts. In larger, maybe non-controlled networks, it would be desirable
if one could disable acceptance of the MTU option.

Of course, there are similar issues with other options in RAs, too, but
mostly they result in more catastrophic connection failures. ;)

Bye,
Hannes

^ permalink raw reply

* [PATCH] net/9p: fix format string in p9_mount_tag_show()
From: Andrey Ryabinin @ 2015-01-26 16:48 UTC (permalink / raw)
  To: linux-kernel
  Cc: Aneesh Kumar K.V, Eric Van Hensbergen, Ron Minnich,
	Latchesar Ionkov, David S. Miller, v9fs-developer, netdev,
	Andrey Ryabinin

Using "%s" for non-NULL terminated string is quite
dangerous, since this causes reading out of bounds.
chan->tag is non-NULL terminated, so precision
must be specified for printing it.

Fixes: 86c8437383ac ("net/9p: Add sysfs mount_tag file for virtio 9P device")
Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com>
---
 net/9p/trans_virtio.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index daa749c..f0d5f90 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -504,7 +504,8 @@ static ssize_t p9_mount_tag_show(struct device *dev,
 	vdev = dev_to_virtio(dev);
 	chan = vdev->priv;
 
-	return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
+	return snprintf(buf, chan->tag_len + 1, "%.*s",
+			chan->tag_len, chan->tag);
 }
 
 static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);
-- 
2.2.2

^ permalink raw reply related

* Re: [RFC PATCH] net: ipv6: Make address flushing on ifdown optional
From: Hannes Frederic Sowa @ 2015-01-26 16:49 UTC (permalink / raw)
  To: Brian Haley; +Cc: David Ahern, netdev
In-Reply-To: <54C2BA50.6080208@hp.com>

On Fr, 2015-01-23 at 16:17 -0500, Brian Haley wrote:
> On 01/23/2015 01:23 PM, David Ahern wrote:
> 
> >>> Add a new sysctl to make this behavior optional. Setting defaults to flush
> >>> addresses to maintain backwards compatibility. When reset flushing is bypassed:
> >>>
> >>> [root@f20 ~]# echo 0 > /proc/sys/net/ipv6/conf/eth1/flush_addr_on_down
> >>> [root@f20 ~]# ip -6 addr add dev eth1 2000:11:1:1::1/64
> >>> [root@f20 ~]# ip addr show dev eth1
> >>> 3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN group
> >>> default qlen 1000
> >>>      link/ether 02:04:11:22:33:01 brd ff:ff:ff:ff:ff:ff
> >>>      inet6 2000:11:1:1::1/64 scope global tentative
> >>>         valid_lft forever preferred_lft forever
> >>> [root@f20 ~]#  ip link set dev eth1 up
> >>> [root@f20 ~]#  ip link set dev eth1 down
> >>> [root@f20 ~]# ip addr show dev eth1
> >>> 3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN group
> >>> default qlen 1000
> >>>      link/ether 02:04:11:22:33:01 brd ff:ff:ff:ff:ff:ff
> >>>      inet6 2000:11:1:1::1/64 scope global
> >>>         valid_lft forever preferred_lft forever
> >>>      inet6 fe80::4:11ff:fe22:3301/64 scope link
> >>>         valid_lft forever preferred_lft forever
> >>
> >> I think this was brought up in a previous thread on this, but don't you have to
> >> do DAD on these addresses once the interface comes back up?  Some other system
> >> could have come along, done DAD, succeeded, and is now using it.  Or does the
> >> use of this flag assume the user is Ok without doing DAD, and will deal with the
> >> fallout?
> > 
> > You have the same problem today, don't you? Current code allows an IPv6 address
> > to be configured on interface in the down state. The intent of this sysctl is to
> > allow that address to stay on an up-down cycle.
> 
> Yes, looks like ndisc_send_skb() never returns any lower-level error back up to
> the caller, so it's assumed the Neighbour Advertisement is always sent.
> Although the address will be marked "tentative" until IFF_UP is set.
> 
> > I don't have a strong IPv6 background so the first email thread and this RFC
> > patch are both asking first and foremost if there is any harm in this behavior.
> > None has been raised - so far. To maintain backwards compatibility this is a new
> > option which when reset allows the addresses to be retained (not flushed).
> 
> Seems as though you're in an RFC grey area then.  Personally, I'd do DAD, even
> though the possibility of a collision is always very small.  But that's just my
> opinion.

I agree. If the interface is in a state where it doesn't listen for
other hosts doing DAD, we must initiate DAD for that address during
bringing the interface up.

I am even not so sure if this is a grey area. Anyway, the current
behavior is not best and we should change that if the kernel does not do
DAD on addresses added during ifdown. Hopefully people don't use this
trick. :)

Bye,
Hannes

^ permalink raw reply

* Re: [PATCH] ethernet: fm10k: Actually drop 4 bits
From: Vick, Matthew @ 2015-01-26 16:58 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Alexander Duyck, Kirsher, Jeffrey T,
	e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <87twzhknnl.fsf@rasmusvillemoes.dk>

On 1/23/15, 4:50 PM, "Rasmus Villemoes" <linux@rasmusvillemoes.dk> wrote:

>On Sat, Jan 24 2015, "Vick, Matthew" <matthew.vick@intel.com> wrote:
>
>> Good catch! I noticed this too and was getting a patch together to
>>address
>> this.
>>
>> The difference is that I was planning on not silently accepting an
>>invalid
>> VLAN ID to begin with and returning FM10K_ERR_PARAM if the VLAN was
>> invalid, which I think is a better approach for this situation. If it's
>> alright with you, I'll generate the patch shortly and credit you via
>>your
>> Reported-by.
>
>Sure, do what you think is best.
>
>Rasmus

Sounds good. I'll get the patch created and validated through Jeff's tree.

Cheers,
Matthew

^ permalink raw reply

* [PATCH 1/5] PCI: Add defines for max read request sizes
From: Rafał Miłecki @ 2015-01-26 17:05 UTC (permalink / raw)
  To: Bjorn Helgaas, linux-pci
  Cc: Matt Porter, Alexandre Bounine, Chris Metcalf, Bradley Grove,
	linux-scsi, Realtek linux nic maintainers, netdev,
	Rafał Miłecki

There are few drivers using magic numbers when operating with PCIe
capabilities and PCI_EXP_DEVCTL_READRQ. Define known values to allow
cleaning their code a bit.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 include/uapi/linux/pci_regs.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 4a1d0cc..efe3443 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -451,6 +451,10 @@
 #define  PCI_EXP_DEVCTL_AUX_PME	0x0400	/* Auxiliary Power PM Enable */
 #define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
 #define  PCI_EXP_DEVCTL_READRQ	0x7000	/* Max_Read_Request_Size */
+#define  PCI_EXP_DEVCTL_READRQ_128B  0x0000 /* 128 Bytes */
+#define  PCI_EXP_DEVCTL_READRQ_256B  0x1000 /* 256 Bytes */
+#define  PCI_EXP_DEVCTL_READRQ_512B  0x2000 /* 512 Bytes */
+#define  PCI_EXP_DEVCTL_READRQ_1024B 0x3000 /* 1024 Bytes */
 #define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
 #define PCI_EXP_DEVSTA		10	/* Device Status */
 #define  PCI_EXP_DEVSTA_CED	0x0001	/* Correctable Error Detected */
-- 
1.8.4.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" 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 related

* [PATCH 5/5] r8169: use PCI define for max read request size
From: Rafał Miłecki @ 2015-01-26 17:06 UTC (permalink / raw)
  To: Bjorn Helgaas, linux-pci
  Cc: Realtek linux nic maintainers, netdev, Rafał Miłecki
In-Reply-To: <1422291922-12324-1-git-send-email-zajec5@gmail.com>

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/net/ethernet/realtek/r8169.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 14a1c5c..fa274e0 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -4915,7 +4915,7 @@ static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
 
 	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
 	RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
-	rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
+	rtl_tx_performance_tweak(tp->pci_dev, PCI_EXP_DEVCTL_READRQ_512B);
 }
 
 static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
@@ -4948,7 +4948,7 @@ static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
 	RTL_W8(MaxTxPacketSize, 0x3f);
 	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
 	RTL_W8(Config4, RTL_R8(Config4) | 0x01);
-	rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
+	rtl_tx_performance_tweak(tp->pci_dev, PCI_EXP_DEVCTL_READRQ_512B);
 }
 
 static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
@@ -4964,7 +4964,7 @@ static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
 static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
 {
 	rtl_tx_performance_tweak(tp->pci_dev,
-		(0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+		PCI_EXP_DEVCTL_READRQ_512B | PCI_EXP_DEVCTL_NOSNOOP_EN);
 }
 
 static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
-- 
1.8.4.5

^ permalink raw reply related

* Re: [PATCH net-next 1/1] net: phy: unbind phy device from generic and specifical driver
From: Florian Fainelli @ 2015-01-26 17:14 UTC (permalink / raw)
  To: Fugang Duan, davem; +Cc: netdev, s.hauer, bhutchings, stephen
In-Reply-To: <1422260045-22527-1-git-send-email-b38611@freescale.com>

On 26/01/15 00:14, Fugang Duan wrote:
> The current .phy_detach() function only unbind generic phy driver, which causes
> specifical driver suspend/resume function still work like Atheros AT803X PHYs.
> 
> For example:
> ifconfig eth0 down
> echo mem > /sys/power/status
> 
> After eth0 interface down, driver call phy_detach to unbind phy driver, and then
> do suspend/resume operation, at803x_suspend()/at803x_resume() functions still get
> called that call mdio bus read/write function. When eth0 interface down, MAC driver
> may close all clocks and mdio bus cannot work. So the issue happens.

I was just hitting this problem on Friday evening and was about to
submit a similar change. Thanks!

> 
> The patch can unbind generic and specifical driver.
> 
> Signed-off-by: Fugang Duan <B38611@freescale.com>

Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>


> ---
>  drivers/net/phy/phy_device.c |   15 ++-------------
>  1 files changed, 2 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 3fc91e8..8adbc5d 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -672,8 +672,6 @@ EXPORT_SYMBOL(phy_attach);
>   */
>  void phy_detach(struct phy_device *phydev)
>  {
> -	int i;
> -
>  	if (phydev->bus->dev.driver)
>  		module_put(phydev->bus->dev.driver->owner);
>  
> @@ -681,17 +679,8 @@ void phy_detach(struct phy_device *phydev)
>  	phydev->attached_dev = NULL;
>  	phy_suspend(phydev);
>  
> -	/* If the device had no specific driver before (i.e. - it
> -	 * was using the generic driver), we unbind the device
> -	 * from the generic driver so that there's a chance a
> -	 * real driver could be loaded
> -	 */
> -	for (i = 0; i < ARRAY_SIZE(genphy_driver); i++) {
> -		if (phydev->dev.driver == &genphy_driver[i].driver) {
> -			device_release_driver(&phydev->dev);
> -			break;
> -		}
> -	}
> +	if (phydev->dev.driver)
> +		device_release_driver(&phydev->dev);
>  }
>  EXPORT_SYMBOL(phy_detach);
>  
> 


-- 
Florian

^ permalink raw reply

* Re: [PATCH v3 net-next] net: ipv6: Add sysctl entry to disable MTU updates from RA
From: Bjørn Mork @ 2015-01-26 17:27 UTC (permalink / raw)
  To: David Miller; +Cc: harouth, netdev
In-Reply-To: <20150124.231432.1788575004982971514.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> Under what circumstances would userland ignore a router advertized
> MTU, and are the RFCs ok with this?

RFC 4861 ( https://tools.ietf.org/html/rfc4861#page-54 ) says:

  "If the MTU option is present, hosts SHOULD copy the option's value
   into LinkMTU so long as the value is greater than or equal to the
   minimum link MTU [IPv6] and does not exceed the maximum LinkMTU value
   specified in the link-type-specific document (e.g., [IPv6-ETHER])."

So the RFC acknowledge that there may exist valid reasons in particular
circumstances to ignore the MTU option.  As others have stated: This
might be necessary for DoS prevention, working around bugs in other
equipment, etc.


Bjørn

^ permalink raw reply

* Re: [PATCH] net/9p: fix format string in p9_mount_tag_show()
From: Andrey Ryabinin @ 2015-01-26 17:28 UTC (permalink / raw)
  To: David Laight, linux-kernel@vger.kernel.org
  Cc: Aneesh Kumar K.V, Eric Van Hensbergen, Ron Minnich,
	Latchesar Ionkov, David S. Miller,
	v9fs-developer@lists.sourceforge.net, netdev@vger.kernel.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1CAD302F@AcuExch.aculab.com>

On 01/26/2015 08:04 PM, David Laight wrote:
> From: Andrey Ryabinin
>> Using "%s" for non-NULL terminated string is quite
>> dangerous, since this causes reading out of bounds.
>> chan->tag is non-NULL terminated, so precision
>> must be specified for printing it.
>>
>> Fixes: 86c8437383ac ("net/9p: Add sysfs mount_tag file for virtio 9P device")
>> Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com>
>> ---
>>  net/9p/trans_virtio.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
>> index daa749c..f0d5f90 100644
>> --- a/net/9p/trans_virtio.c
>> +++ b/net/9p/trans_virtio.c
>> @@ -504,7 +504,8 @@ static ssize_t p9_mount_tag_show(struct device *dev,
>>  	vdev = dev_to_virtio(dev);
>>  	chan = vdev->priv;
>>
>> -	return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
> 
> Note the 'buffer length' passed to snprintf().

Yes, but 'buffer length' is length of buf, not chan->tag.
The problem with "%s" is that vsnprintf expects to chan->tag to be NULL-terminated,
so it calls strnlen(chan->tag, -1).
Thus we read beyond of allocated memory range:

==================================================================
BUG: AddressSanitizer: out of bounds access in strnlen+0xa7/0xb0 at addr ffff88006b882d79
Read of size 1 by task cat/669
=============================================================================
BUG kmalloc-16 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------

Disabling lock debugging due to kernel taint
INFO: Allocated in p9_virtio_probe+0x523/0x11d0 age=7711 cpu=1 pid=1
        __slab_alloc.constprop.16+0x765/0x1220
        __kmalloc+0x380/0x630
        p9_virtio_probe+0x523/0x11d0
        virtio_dev_probe+0x739/0x11e0
        really_probe+0x204/0xd10
        __driver_attach+0x2c1/0x470
        bus_for_each_dev+0x16c/0x280
        driver_attach+0x48/0x80
        bus_add_driver+0x490/0x970
        driver_register+0x274/0x620
        register_virtio_driver+0x97/0x140
        p9_virtio_init+0x31/0x33
        do_one_initcall+0x1fb/0x3a0
        kernel_init_freeable+0x40d/0x4b1
        kernel_init+0xe/0xf0
        ret_from_fork+0x7c/0xb0
INFO: Slab 0xffffea0001ae2080 objects=23 used=23 fp=0x          (null) flags=0x4000000000004080
INFO: Object 0xffff88006b882d70 @offset=3440 fp=0xffff88006b882ec8

Bytes b4 ffff88006b882d60: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a  ........ZZZZZZZZ
Object ffff88006b882d70: 2f 64 65 76 2f 72 6f 6f 74 6b 6b 6b 6b 6b 6b a5  /dev/rootkkkkkk.
Redzone ffff88006b882d80: cc cc cc cc cc cc cc cc                          ........
Padding ffff88006b882ec0: 5a 5a 5a 5a 5a 5a 5a 5a                          ZZZZZZZZ
CPU: 3 PID: 669 Comm: cat Tainted: G    B          3.19.0-rc5+ #168
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
 ffff88006b882d70 ffff880069b8f6e8 ffffffff82101090 0000000000000053
 ffff88006c807a80 ffff880069b8f748 ffffffff8152b231 ffff880069b8f758
 ffff880069b8f708 ffff880069b8f738 ffff88006d19dd60 ffffffff8237bac4
Call Trace:
 [<ffffffff82101090>] dump_stack+0x45/0x57
 [<ffffffff8152b231>] print_trailer+0x221/0x4b0
 [<ffffffff8153b30a>] object_err+0x3a/0x50
 [<ffffffff8153fee2>] kasan_report_error+0x3a2/0x9c0
 [<ffffffff812ce570>] ? get_ksymbol+0x1b80/0x1b80
 [<ffffffff8153efb6>] ? kasan_unpoison_shadow+0x36/0x70
 [<ffffffff8153efb6>] ? kasan_unpoison_shadow+0x36/0x70
 [<ffffffff81540561>] __asan_report_load1_noabort+0x61/0x80
 [<ffffffff81878657>] ? strnlen+0xa7/0xb0
 [<ffffffff81878657>] strnlen+0xa7/0xb0
 [<ffffffff81197824>] ? __kernel_text_address+0x94/0xc0
 [<ffffffff8188197f>] string.isra.2+0x3f/0x2f0
 [<ffffffff81888dc2>] vsnprintf+0x392/0x23b0
 [<ffffffff814221f0>] ? __rmqueue+0x24c0/0x24c0
 [<ffffffff81888a30>] ? pointer.isra.17+0xd80/0xd80
 [<ffffffff8152b537>] ? check_bytes_and_report+0x77/0x290
 [<ffffffff81531d91>] ? deactivate_slab+0x4d1/0x1f00
 [<ffffffff820e1f00>] ? p9_virtio_close+0xd0/0xd0
 [<ffffffff8188af95>] snprintf+0x85/0xa0
 [<ffffffff8188af10>] ? vsprintf+0x20/0x20
 [<ffffffff81534970>] ? alloc_debug_processing+0x1e0/0x4a0
 [<ffffffff820e1fe8>] p9_mount_tag_show+0xe8/0x180
 [<ffffffff81b49295>] dev_attr_show+0x75/0x170
 [<ffffffff8153f20c>] ? memset+0x2c/0x40
 [<ffffffff817157de>] sysfs_kf_seq_show+0x3fe/0xe80
 [<ffffffff810144d0>] ? dump_trace+0x230/0x920
 [<ffffffff817153e0>] ? sysfs_remove_files+0xd0/0xd0
 [<ffffffff8153efb6>] ? kasan_unpoison_shadow+0x36/0x70
 [<ffffffff8153f063>] ? kasan_kmalloc+0x73/0x90
 [<ffffffff8170d849>] kernfs_seq_show+0x1b9/0x330
 [<ffffffff815ff75e>] seq_read+0x3be/0x1f30
 [<ffffffff814c3656>] ? handle_mm_fault+0xe86/0x2340
 [<ffffffff815ff3a0>] ? traverse+0x1000/0x1000
 [<ffffffff814cdeb1>] ? find_vma+0x21/0x210
 [<ffffffff810f582b>] ? __do_page_fault+0x2bb/0xea0
 [<ffffffff817109ae>] kernfs_fop_read+0x38e/0x6f0
 [<ffffffff810f5570>] ? mm_fault_error+0x410/0x410
 [<ffffffff81710620>] ? kernfs_vma_page_mkwrite+0x390/0x390
 [<ffffffff8156441b>] __vfs_read+0xbb/0x320
 [<ffffffff815647a3>] vfs_read+0x123/0x320
 [<ffffffff81564aa9>] SyS_read+0x109/0x270
 [<ffffffff815649a0>] ? vfs_read+0x320/0x320
 [<ffffffff810e9a39>] ? do_async_page_fault+0x19/0x80
 [<ffffffff82113be9>] system_call_fastpath+0x12/0x17
Memory state around the buggy address:
 ffff88006b882c00: fc fc fc 00 00 fc fc fc fc fc fc fc fc fc fc fc
 ffff88006b882c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88006b882d00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc 00 01
                                                                ^
 ffff88006b882d80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88006b882e00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================




> 
>> +	return snprintf(buf, chan->tag_len + 1, "%.*s",
>> +			chan->tag_len, chan->tag);
> 
> Both these are equivalent to:
> 	buf[chan->tag_len]= 0;
> 	memcpy(buf, chan->tag, chan->tag_len);
> 
> using snprintf() is rather extreme.
> 

Indeed, memcpy is much better here.

^ permalink raw reply

* Re: [PATCH net-next 1/1] net: phy: unbind phy device from generic and specifical driver
From: Florian Fainelli @ 2015-01-26 17:47 UTC (permalink / raw)
  To: Fugang Duan, davem; +Cc: netdev, s.hauer, bhutchings, stephen
In-Reply-To: <54C675F1.9080803@gmail.com>

On 26/01/15 09:14, Florian Fainelli wrote:
> On 26/01/15 00:14, Fugang Duan wrote:
>> The current .phy_detach() function only unbind generic phy driver, which causes
>> specifical driver suspend/resume function still work like Atheros AT803X PHYs.
>>
>> For example:
>> ifconfig eth0 down
>> echo mem > /sys/power/status
>>
>> After eth0 interface down, driver call phy_detach to unbind phy driver, and then
>> do suspend/resume operation, at803x_suspend()/at803x_resume() functions still get
>> called that call mdio bus read/write function. When eth0 interface down, MAC driver
>> may close all clocks and mdio bus cannot work. So the issue happens.
> 
> I was just hitting this problem on Friday evening and was about to
> submit a similar change. Thanks!
> 
>>
>> The patch can unbind generic and specifical driver.
>>
>> Signed-off-by: Fugang Duan <B38611@freescale.com>
> 
> Acked-by: Florian Fainelli <f.fainelli@gmail.com>
> Tested-by: Florian Fainelli <f.fainelli@gmail.com>

Humm, this breaks a sequence of ifconfig down then up, the driver is
removed, and we never get to probe it again, does this work for you
using the FEC driver?

Another way to solve this double suspend problem is to make sure that we
track whether the PHY has already been suspended.
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next v3 2/2] iproute2: bridge vlan show new option to print ranges
From: roopa @ 2015-01-26 18:57 UTC (permalink / raw)
  To: Scott Feldman; +Cc: Netdev, shemminger, vyasevic@redhat.com, Wilson Kok
In-Reply-To: <54C5DA02.30502@cumulusnetworks.com>

On 1/25/15, 10:09 PM, roopa wrote:
> On 1/25/15, 9:57 PM, Scott Feldman wrote:
>> On Sun, Jan 25, 2015 at 9:18 PM, roopa <roopa@cumulusnetworks.com> 
>> wrote:
>>> On 1/25/15, 8:35 PM, Scott Feldman wrote:
>>>>> diff --git a/bridge/bridge.c b/bridge/bridge.c
>>>>> index 5fcc552..88469ca 100644
>>>>> --- a/bridge/bridge.c
>>>>> +++ b/bridge/bridge.c
>>>>> @@ -21,6 +21,7 @@ int resolve_hosts;
>>>>>    int oneline = 0;
>>>>>    int show_stats;
>>>>>    int show_details;
>>>>> +int compress_vlans;
>>>>>    int timestamp;
>>>>>    char * _SL_ = NULL;
>>>>>
>>>>> @@ -32,7 +33,8 @@ static void usage(void)
>>>>>    "Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
>>>>>    "where  OBJECT := { link | fdb | mdb | vlan | monitor }\n"
>>>>>    "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
>>>>> -"                    -o[neline] | -t[imestamp] | -n[etns] name 
>>>>> }\n");
>>>>> +"                    -o[neline] | -t[imestamp] | -n[etns] name |\n"
>>>>> +"                    -c[ompressvlans] }\n");
>>>> This option is awkward at this level since it's specific to bridge 
>>>> vlan
>>>> cmd.
>>>>
>>>> Is it even necessary?  The real user of compressed vlans isn't the
>>>> "bridge show" cmd; just keep "bridge show" simple, listing each vlan
>>>> per line.
>>> without ranges it does get a bit difficult (or rather long) to read 
>>> if there
>>> are many vlans (it was also a comment I received on v2).
>>>
>>> All the available options whether they apply to the immediate 
>>> sub-command or
>>> not are at the toplevel command today.
>>> Hence the position (Not a big fan of the current name. suggestions 
>>> welcome).
>>>
>>> I would have loved to have the default output print ranges, If that is
>>> acceptable. But, that can break new iproute2 on older kernels (If 
>>> that is
>>> something we should care about).
>>>
>>> other option is keyword argument like maybe 'bridge vlan show 
>>> compressed' or
>>> 'bridge vlan show ranges'
>> How about try RTEXT_FILTER_BRVLAN_COMPRESSED first, and if that fails,
>> try RTEXT_FILTER_BRVLAN, and don't add -c option?
>>
>>
> That would have been nice, except that  it will not fail. It will pass 
> but not return any vlans.
>
> Better would be to send both flags. I think that will work. New kernel 
> looks at RTEXT_FILTER_BRVLAN_COMPRESSED first.
> v4  soon ....after some testing ...  ;)
This still means i will end up changing the default/current output into 
vlan ranges on newer kernels. If that is acceptable then i will resubmit 
with v4.
If not, v3 looks ok to me so far.

thanks,
Roopa

^ permalink raw reply

* [PATCH net-next] sunvnet: improve error handling when a remote crashes
From: David L Stevens @ 2015-01-26 19:10 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 |   68 +++++++++++++++++++++---------------
 1 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index fe044f3..3733ae6 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_warn("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;
 }
@@ -1633,7 +1632,9 @@ static const struct ethtool_ops vnet_ethtool_ops = {
 
 static void vnet_port_free_tx_bufs(struct vnet_port *port)
 {
+	struct net_device *dev = port->vp->dev;
 	struct vio_dring_state *dr;
+	bool active_freed = false;
 	int i;
 
 	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
@@ -1649,8 +1650,7 @@ 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");
+		active_freed |= d->hdr.state == VIO_DESC_READY;
 
 		ldc_unmap(port->vio.lp,
 			  port->tx_bufs[i].cookies,
@@ -1662,6 +1662,9 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
 	ldc_free_exp_dring(port->vio.lp, dr->base,
 			   (dr->entry_size * dr->num_entries),
 			   dr->cookies, dr->ncookies);
+	if (active_freed)
+		pr_warn("%s: active transmit buffers freed for remote %pM\n",
+			dev->name, port->raddr);
 	dr->base = NULL;
 	dr->entry_size = 0;
 	dr->num_entries = 0;
@@ -1669,6 +1672,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

* Re: [PATCH] net: Linn Ethernet Packet Sniffer driver
From: Joe Perches @ 2015-01-26 19:39 UTC (permalink / raw)
  To: Stathis Voukelatos; +Cc: netdev, linux-kernel, devicetree, abrestic
In-Reply-To: <54C620CB.3010500@linn.co.uk>

On Mon, 2015-01-26 at 11:11 +0000, Stathis Voukelatos wrote:
> On 24/01/15 21:37, Joe Perches wrote:
> > On Fri, 2015-01-23 at 10:07 +0000, 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.
> > []
> >>   include/linux/pkt_sniffer.h                        |  89 +++++
> > Why should this file be here?
> > Why not in the drivers/net/pkt-sniffer directory?
[]
> This header file is the public API for the driver.
> Should it not live under the 'include' directory?
> Several other drivers seem to follow that convention.

It depends on how public is public.

If it's _really_ public, it should be in uapi.
If it's kinda public, then _maybe_ it should be
in include/linux, but how likely is it another
driver will use it?

^ permalink raw reply

* Re: [PATCH net-next] sunvnet: improve error handling when a remote crashes
From: David L Stevens @ 2015-01-26 19:48 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Sowmini Varadhan
In-Reply-To: <54C6911B.5040501@oracle.com>

This patch has a dependency on another one in my tree, so it won't apply; I'll
resubmit as a set.

							+-DLS

On 01/26/2015 02:10 PM, David L Stevens wrote:
> 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 |   68 +++++++++++++++++++++---------------
>  1 files changed, 40 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
> index fe044f3..3733ae6 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_warn("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;
>  }
> @@ -1633,7 +1632,9 @@ static const struct ethtool_ops vnet_ethtool_ops = {
>  
>  static void vnet_port_free_tx_bufs(struct vnet_port *port)
>  {
> +	struct net_device *dev = port->vp->dev;
>  	struct vio_dring_state *dr;
> +	bool active_freed = false;
>  	int i;
>  
>  	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
> @@ -1649,8 +1650,7 @@ 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");
> +		active_freed |= d->hdr.state == VIO_DESC_READY;
>  
>  		ldc_unmap(port->vio.lp,
>  			  port->tx_bufs[i].cookies,
> @@ -1662,6 +1662,9 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
>  	ldc_free_exp_dring(port->vio.lp, dr->base,
>  			   (dr->entry_size * dr->num_entries),
>  			   dr->cookies, dr->ncookies);
> +	if (active_freed)
> +		pr_warn("%s: active transmit buffers freed for remote %pM\n",
> +			dev->name, port->raddr);
>  	dr->base = NULL;
>  	dr->entry_size = 0;
>  	dr->num_entries = 0;
> @@ -1669,6 +1672,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;
> 

^ permalink raw reply

* Re: [PATCH net-next] sunvnet: improve error handling when a remote crashes
From: Sowmini Varadhan @ 2015-01-26 19:54 UTC (permalink / raw)
  To: David L Stevens; +Cc: David Miller, netdev
In-Reply-To: <54C6911B.5040501@oracle.com>




> @@ -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;

As I understand it, this starts at dr->prod and goes through all
descriptors, cleaning up !READY descriptors as it goes around.

I think you'll have a higher reclaim rate for finding !READY if you
started at dr->cons instead: dr->cons is the one that was last ACK'ed,
and that ack would only have been sent after the peer had marked the 
descriptor as DONE. (consumer would have had a chance to read more
descriptors, by the time the tx-reclaim loop goes around) 

> +		if (port->tx_bufs[txi].skb) {
> +			if (d->hdr.state != VIO_DESC_DONE)
> +				pr_warn("invalid ring buffer state %d\n",
> +					d->hdr.state);

I would even suggest skipping the pr_warn (maybe make it a viodbg
instead) as it might alarm the end-user (who cannot really do 
anything about it other than call us anyway :-)).

>  			   dr->cookies, dr->ncookies);
> +	if (active_freed)
> +		pr_warn("%s: active transmit buffers freed for remote %pM\n",
> +			dev->name, port->raddr);

Same comment as above.

In general, I think we need some sysfs/ethtool  bean-counters/statistics
for sunvnet, to keep track of this sort of thing efficiently in 
a production env without triggering red-herrings calls.

--Sowmini

^ permalink raw reply

* Re: [PATCH net-next v2] rhashtable: rhashtable_remove() must unlink in both tbl and future_tbl
From: David Miller @ 2015-01-26 19:57 UTC (permalink / raw)
  To: tgraf; +Cc: sergei.shtylyov, ying.xue, richard.alpe, netdev, tipc-discussion
In-Reply-To: <20150121115401.GA12570@casper.infradead.org>

From: Thomas Graf <tgraf@suug.ch>
Date: Wed, 21 Jan 2015 11:54:01 +0000

> As removals can occur during resizes, entries may be referred to from
> both tbl and future_tbl when the removal is requested. Therefore
> rhashtable_remove() must unlink the entry in both tables if this is
> the case. The existing code did search both tables but stopped when it
> hit the first match.
> 
> Failing to unlink in both tables resulted in use after free.
> 
> Fixes: 97defe1ecf86 ("rhashtable: Per bucket locks & deferred expansion/shrinking")
> Reported-by: Ying Xue <ying.xue@windriver.com>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
> ---
> v2: 12 digit commit reference, commit msg clarification as pointed
>     out by Sergei.

Applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next] sunvnet: improve error handling when a remote crashes
From: David L Stevens @ 2015-01-26 20:19 UTC (permalink / raw)
  To: Sowmini Varadhan; +Cc: David Miller, netdev
In-Reply-To: <20150126195403.GE6437@oracle.com>



On 01/26/2015 02:54 PM, Sowmini Varadhan wrote:
> 
> 
> 
>> @@ -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;
> 
> As I understand it, this starts at dr->prod and goes through all
> descriptors, cleaning up !READY descriptors as it goes around.
> 
> I think you'll have a higher reclaim rate for finding !READY if you
> started at dr->cons instead: dr->cons is the one that was last ACK'ed,
> and that ack would only have been sent after the peer had marked the 
> descriptor as DONE. (consumer would have had a chance to read more
> descriptors, by the time the tx-reclaim loop goes around) 

	Actually, it starts at dr->prod-1, and it stops as soon as it
gets an already-freed descriptor. It could possibly free something
marked as DONE before we've been acked (ie, faster), but it could look
at stuff it doesn't have to. I wanted to be conservative here, though,
because we don't want to miss any and have unfreed data until we go
around the ring. Any pending (in any state) would begin at dr->prod-1,
so there can't be any races with an ACK there.
	At any rate, the intent for this patch is to check and free
skbs in states other than just VIO_DESC_READY and not requiring that
it be VIO_DESC_DONE when there is an allocated buffer associated with it.
The descriptors indices we look at are unchanged by this patch.

> 
>> +		if (port->tx_bufs[txi].skb) {
>> +			if (d->hdr.state != VIO_DESC_DONE)
>> +				pr_warn("invalid ring buffer state %d\n",
>> +					d->hdr.state);
> 
> I would even suggest skipping the pr_warn (maybe make it a viodbg
> instead) as it might alarm the end-user (who cannot really do 
> anything about it other than call us anyway :-)).

	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.
	A crash based on the behavior of a remote was definitely too much, and
warnings can be turned off too. viodbg() would be useless here-- you wouldn't
turn it on to find these, and if these are occurring without a transmitter
crashing, it'd indicate something more serious.
	So, I think this one should stay (as a warning, which can also be turned
off). The next one is debatable, since it really is an ordinary reset or shutdown
situation and could be removed entirely. I changed the existing warning to at
least be done only once per ring and give some more info, but removing it entirely
seems reasonable to me too.

> 
>>  			   dr->cookies, dr->ncookies);
>> +	if (active_freed)
>> +		pr_warn("%s: active transmit buffers freed for remote %pM\n",
>> +			dev->name, port->raddr);
> 
> Same comment as above.

						+-DLS

^ permalink raw reply

* Re: [PATCH net-next] sunvnet: improve error handling when a remote crashes
From: Sowmini Varadhan @ 2015-01-26 20:29 UTC (permalink / raw)
  To: David L Stevens; +Cc: David Miller, netdev
In-Reply-To: <54C6A154.3090906@oracle.com>

On 01/26/2015 03:19 PM, David L Stevens wrote:

>> I think you'll have a higher reclaim rate for finding !READY if you
>> started at dr->cons instead: dr->cons is the one that was last ACK'ed,
>> and that ack would only have been sent after the peer had marked the
>> descriptor as DONE. (consumer would have had a chance to read more
>> descriptors, by the time the tx-reclaim loop goes around)
   :
> The descriptors indices we look at are unchanged by this patch.

Understood, and what I suggested was an optimization for tx-reclaim.


> 	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.

ymmv.

--Sowmini

^ permalink raw reply

* [PATCH V2 3/6] rtlwifi: btcoexist: Add routines for RTL8812AE with single antenna
From: Larry Finger @ 2015-01-26 20:42 UTC (permalink / raw)
  To: kvalo-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA, Troy Tan,
	netdev-u79uwXL29TY76Z2rM5mHXA, Larry Finger
In-Reply-To: <1422304934-9239-1-git-send-email-Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>

From: Troy Tan <troy_tan-kXabqFNEczNtrwSWzY7KCg@public.gmane.org>

The RTL8812AE needs different BT coexistence routines than does the
RTL8821AE. This patch adds the necessary routines for devices with a
single antenna.

Signed-off-by: Troy Tan <troy_tan-kXabqFNEczNtrwSWzY7KCg@public.gmane.org>
Signed-off-by: Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
---
 .../wireless/rtlwifi/btcoexist/halbtc8812a1ant.c   | 2081 ++++++++++++++++++++
 .../wireless/rtlwifi/btcoexist/halbtc8812a1ant.h   |  175 ++
 2 files changed, 2256 insertions(+)
 create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.c
 create mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.h

diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.c
new file mode 100644
index 0000000..0dcfb6d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.c
@@ -0,0 +1,2081 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
+ *
+ * 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-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
+ *
+ ******************************************************************************/
+
+/*  Description: */
+/*  This file is for 8812a1ant Co-exist mechanism */
+#include "halbt_precomp.h"
+
+/*  Global variables, these are static variables */
+static struct coex_dm_8812a_1ant glcoex_dm_8812a_1ant;
+static struct coex_dm_8812a_1ant *coex_dm = &glcoex_dm_8812a_1ant;
+static struct coex_sta_8812a_1ant glcoex_sta_8812a_1ant;
+static struct coex_sta_8812a_1ant *coex_sta = &glcoex_sta_8812a_1ant;
+
+static const char *const glbt_info_src_8812a_1ant[] = {
+	"BT Info[wifi fw]",
+	"BT Info[bt rsp]",
+	"BT Info[bt auto report]",
+};
+
+static u32 glcoex_ver_date_8812a_1ant = 20130729;
+static u32 glcoex_ver_8812a_1ant = 0x10;
+
+/*  local function proto type if needed */
+/*  local function start with halbtc8812a1ant_ */
+static void halbtc8812a1ant_update_ra_mask(struct btc_coexist *btcoexist,
+					   bool force_exec, u8 type,
+					   u32 rate_mask)
+{
+	if (BTC_RATE_DISABLE == type)
+		coex_dm->cur_ra_mask |= rate_mask;	/*  disable rate */
+	else if (BTC_RATE_ENABLE == type)
+		coex_dm->cur_ra_mask &= ~rate_mask;	/*  enable rate */
+
+	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 halbtc8812a1ant_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 halbtc8812a1ant_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_1ANT_BT_RSP] -
+		     coex_sta->bt_info_query_cnt) > 2) {
+			buf[0] = data_len;
+			buf[1] = 0x1;	/*  polling enable, 1 =enable */
+			buf[2] = 0x2;	/*  polling time in seconds */
+			buf[3] = 0x1;	/*  auto report enable, 1 =enable */
+
+			btcoexist->btc_set(btcoexist, BTC_SET_ACT_CTRL_BT_INFO,
+					   (void *)&buf[0]);
+		}
+	}
+	coex_sta->bt_info_query_cnt++;
+}
+
+static void halbtc8812a1ant_update_bt_link_info(struct btc_coexist *btcoexist)
+{
+	struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+
+	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;
+
+	/*  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 hal8812a1_bt_auto_rep(struct btc_coexist *btcoexist,
+				  bool force_exec,
+				  bool enable_auto_report)
+{
+	BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW,
+		  "[BTCoex], %s BT Auto report = %s\n",
+		  (force_exec ? "force to" : ""),
+		  ((enable_auto_report) ? "Enabled" : "Disabled"));
+	coex_dm->cur_bt_auto_report = enable_auto_report;
+
+	if (!force_exec) {
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+			  "[BTCoex], pre_bt_auto_report =%d, cur_bt_auto_report =%d\n",
+			  coex_dm->pre_bt_auto_report,
+			  coex_dm->cur_bt_auto_report);
+
+		if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report)
+			return;
+	}
+	coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report;
+}
+
+static void halbtc8812a1ant_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 halbtc8812a1ant_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;
+	}
+	halbtc8812a1ant_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 halbtc8812a1ant_coex_table_with_type(struct btc_coexist *btcoexist,
+						 bool force_exec, u8 type)
+{
+	switch (type) {
+	case 0:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0x55555555,
+					   0x55555555, 0xffff, 0x3);
+		break;
+	case 1:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0x55555555,
+					   0x5a5a5a5a, 0xffff, 0x3);
+		break;
+	case 2:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a,
+					   0x5a5a5a5a, 0xffff, 0x3);
+		break;
+	case 3:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa,
+					   0xaaaaaaaa, 0xffff, 0x3);
+		break;
+	case 4:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0xffffffff,
+					   0xffffffff, 0xffff, 0x3);
+		break;
+	case 5:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0x5fff5fff,
+					   0x5fff5fff, 0xffff, 0x3);
+		break;
+	case 6:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0x55ff55ff,
+					   0x5a5a5a5a, 0xffff, 0x3);
+		break;
+	case 7:
+		halbtc8812a1ant_coex_table(btcoexist, force_exec, 0x5afa5afa,
+					   0x5afa5afa, 0xffff, 0x3);
+		break;
+	default:
+		break;
+	}
+}
+
+static void hal8812a1_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 hal8812a1_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;
+	}
+	hal8812a1_set_fw_ignore_wlan_act(btcoexist, enable);
+
+	coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act;
+}
+
+static void halbtc8812a1ant_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 halbtc8812a1ant_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 halbtc8812a1ant_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;
+	}
+	halbtc8812a1ant_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 halbtc8812a1ant_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_1byte(btcoexist, 0xcb3, 0x77);
+
+		btcoexist->btc_write_4byte(btcoexist, 0x900, 0x00000400);
+		btcoexist->btc_write_1byte(btcoexist, 0x76d, 0x1);
+	}
+
+	/*  ext switch setting */
+	switch (ant_pos_type) {
+	case BTC_ANT_PATH_WIFI:
+		u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0xcb7);
+		u1_tmp |= BIT3;
+		u1_tmp &= ~BIT2;
+		btcoexist->btc_write_1byte(btcoexist, 0xcb7, u1_tmp);
+		break;
+	case BTC_ANT_PATH_BT:
+		u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0xcb7);
+		u1_tmp &= ~BIT3;
+		u1_tmp |= BIT2;
+		btcoexist->btc_write_1byte(btcoexist, 0xcb7, u1_tmp);
+		break;
+	case BTC_ANT_PATH_PTA:
+	default:
+		u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0xcb7);
+		u1_tmp |= BIT3;
+		u1_tmp &= ~BIT2;
+		btcoexist->btc_write_1byte(btcoexist, 0xcb7, u1_tmp);
+		break;
+	}
+}
+
+static void halbtc8812a1ant_ps_tdma(struct btc_coexist *btcoexist,
+				    bool force_exec, bool turn_on, u8 type)
+{
+	u8 rssi_adjust_val = 0;
+
+	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;
+	}
+	if (turn_on) {
+		switch (type) {
+		default:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x1a,
+						      0x1a, 0x0, 0x50);
+			break;
+		case 1:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x1a,
+						      0x1a, 0x0, 0x50);
+			rssi_adjust_val = 11;
+			break;
+		case 2:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x12,
+						      0x12, 0x0, 0x50);
+			rssi_adjust_val = 14;
+			break;
+		case 3:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25,
+						      0x3, 0x10, 0x40);
+			break;
+		case 4:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15,
+						      0x3, 0x14, 0x0);
+			rssi_adjust_val = 17;
+			break;
+		case 5:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x61, 0x15,
+						      0x3, 0x31, 0x0);
+			break;
+		case 6:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa,
+						      0x3, 0x0, 0x0);
+			break;
+		case 7:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x13, 0xc,
+						      0x5, 0x0, 0x0);
+			break;
+		case 8:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25,
+						      0x3, 0x10, 0x0);
+			break;
+		case 9:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0xa,
+						      0xa, 0x0, 0x50);
+			rssi_adjust_val = 18;
+			break;
+		case 10:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa,
+						      0xa, 0x0, 0x40);
+			break;
+		case 11:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x5,
+						      0x5, 0x0, 0x50);
+			rssi_adjust_val = 20;
+			break;
+		case 12:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xeb, 0xa,
+						      0x3, 0x31, 0x18);
+			break;
+		case 15:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa,
+						      0x3, 0x8, 0x0);
+			break;
+		case 16:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15,
+						      0x3, 0x10, 0x0);
+			rssi_adjust_val = 18;
+			break;
+		case 18:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25,
+						      0x3, 0x10, 0x0);
+			rssi_adjust_val = 14;
+			break;
+		case 20:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x13, 0x25,
+						      0x25, 0x0, 0x0);
+			break;
+		case 21:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x20,
+						      0x3, 0x10, 0x40);
+			break;
+		case 22:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x13, 0x8,
+						      0x8, 0x0, 0x40);
+			break;
+		case 23:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x25,
+						      0x3, 0x31, 0x18);
+			rssi_adjust_val = 22;
+			break;
+		case 24:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x15,
+						      0x3, 0x31, 0x18);
+			rssi_adjust_val = 22;
+			break;
+		case 25:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xe3, 0xa,
+						      0x3, 0x31, 0x18);
+			rssi_adjust_val = 22;
+			break;
+		case 26:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xe3, 0xa,
+						      0x3, 0x31, 0x18);
+			rssi_adjust_val = 22;
+			break;
+		case 27:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x25,
+						      0x3, 0x31, 0x98);
+			rssi_adjust_val = 22;
+			break;
+		case 28:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x69, 0x25,
+						      0x3, 0x31, 0x0);
+			break;
+		case 29:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xab, 0x1a,
+						      0x1a, 0x1, 0x10);
+			break;
+		case 30:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15,
+						      0x3, 0x14, 0x0);
+			break;
+		case 31:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x1a,
+						      0x1a, 0, 0x58);
+			break;
+		case 32:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xab, 0xa,
+						      0x3, 0x31, 0x90);
+			break;
+		case 33:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xa3, 0x25,
+						      0x3, 0x30, 0x90);
+			break;
+		case 34:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x1a,
+						      0x1a, 0x0, 0x10);
+			break;
+		case 35:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a,
+						      0x1a, 0x0, 0x10);
+			break;
+		case 36:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x12,
+						      0x3, 0x14, 0x50);
+			break;
+		case 37:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x53, 0x25,
+						      0x3, 0x10, 0x50);
+			break;
+		}
+	} else {
+		/*  disable PS tdma */
+		switch (type) {
+		case 8:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x8, 0x0,
+						      0x0, 0x0, 0x0);
+			halbtc8812a1ant_set_ant_path(btcoexist,
+						     BTC_ANT_PATH_PTA,
+						     false, false);
+			break;
+		case 0:
+		default:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0,
+						      0x0, 0x0, 0x0);
+			halbtc8812a1ant_set_ant_path(btcoexist,
+						     BTC_ANT_PATH_BT,
+						     false, false);
+			break;
+		case 9:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0,
+						      0x0, 0x0, 0x0);
+			halbtc8812a1ant_set_ant_path(btcoexist,
+						     BTC_ANT_PATH_WIFI,
+						     false, false);
+			break;
+		case 10:
+			halbtc8812a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0,
+						      0x0, 0x8, 0x0);
+			halbtc8812a1ant_set_ant_path(btcoexist,
+						     BTC_ANT_PATH_BT,
+						     false, false);
+			break;
+		}
+	}
+	rssi_adjust_val = 0;
+	btcoexist->btc_set(btcoexist,
+			   BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE,
+			   &rssi_adjust_val);
+
+	/*  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 halbtc8812a1ant_coex_all_off(struct btc_coexist *btcoexist)
+{
+	/*  hw all off */
+	halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+}
+
+static void hal8812a1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist,
+					      u8 wifi_status)
+{
+	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], TdmaDurationAdjustForAcl()\n");
+
+	if ((BT_8812A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN ==
+	     wifi_status) ||
+	    (BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifi_status) ||
+	    (BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == wifi_status)) {
+		if (coex_dm->cur_ps_tdma != 1 &&
+		    coex_dm->cur_ps_tdma != 2 &&
+		    coex_dm->cur_ps_tdma != 3 &&
+		    coex_dm->cur_ps_tdma != 9) {
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						true, 9);
+			coex_dm->ps_tdma_du_adj_type = 9;
+			up = 0;
+			dn = 0;
+			m = 1;
+			n = 3;
+			result = 0;
+			wait_count = 0;
+		}
+		return;
+	}
+
+	if (coex_dm->reset_tdma_adjust) {
+		coex_dm->reset_tdma_adjust = false;
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
+			  "[BTCoex], first run TdmaDurationAdjust()!!\n");
+
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2);
+		coex_dm->ps_tdma_du_adj_type = 2;
+		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-sec 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 {
+			 /* retry count > 3 */
+			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_1ANT_A2DP_BASIC_RATE(bt_info_ext)) &&
+			    ((coex_dm->cur_ps_tdma == 1) ||
+			     (coex_dm->cur_ps_tdma == 2))) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 9);
+				coex_dm->ps_tdma_du_adj_type = 9;
+			} else if (coex_dm->cur_ps_tdma == 1) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 2);
+				coex_dm->ps_tdma_du_adj_type = 2;
+			} else if (coex_dm->cur_ps_tdma == 2) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 9);
+				coex_dm->ps_tdma_du_adj_type = 9;
+			} else if (coex_dm->cur_ps_tdma == 9) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 11);
+				coex_dm->ps_tdma_du_adj_type = 11;
+			}
+		} else if (result == 1) {
+			if ((BT_INFO_8812A_1ANT_A2DP_BASIC_RATE(bt_info_ext)) &&
+			    ((coex_dm->cur_ps_tdma == 1) ||
+			     (coex_dm->cur_ps_tdma == 2))) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 9);
+				coex_dm->ps_tdma_du_adj_type = 9;
+			} else if (coex_dm->cur_ps_tdma == 11) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 9);
+				coex_dm->ps_tdma_du_adj_type = 9;
+			} else if (coex_dm->cur_ps_tdma == 9) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 2);
+				coex_dm->ps_tdma_du_adj_type = 2;
+			} else if (coex_dm->cur_ps_tdma == 2) {
+				halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+							true, 1);
+				coex_dm->ps_tdma_du_adj_type = 1;
+			}
+		}
+		if (coex_dm->cur_ps_tdma != 1 &&
+		    coex_dm->cur_ps_tdma != 2 &&
+		    coex_dm->cur_ps_tdma != 9 &&
+		    coex_dm->cur_ps_tdma != 11) {
+			/*  recover to previous adjust type */
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+						coex_dm->ps_tdma_du_adj_type);
+		}
+	}
+}
+
+static void hal8812a1_ps_tdma_chk_pwr_save_state(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 */
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						false, 0);
+		}
+	} else {		/*  NO PS state */
+		if (new_ps_state) {
+			/*  will enter LPS state, turn off psTdma first */
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						false, 0);
+		}
+	}
+}
+
+static void halbtc8812a1ant_power_save_state(struct btc_coexist *btcoexist,
+					     u8 ps_type, u8 lps_val,
+					     u8 rpwm_val)
+{
+	bool low_pwr_disable = false;
+
+	switch (ps_type) {
+	case BTC_PS_WIFI_NATIVE:
+		/*  recover to original 32k low power setting */
+		low_pwr_disable = false;
+		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:
+		hal8812a1_ps_tdma_chk_pwr_save_state(btcoexist, true);
+		halbtc8812a1ant_lps_rpwm(btcoexist, NORMAL_EXEC, lps_val,
+					 rpwm_val);
+		/*  when coex force to enter LPS, do not enter 32k low power */
+		low_pwr_disable = true;
+		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;
+	case BTC_PS_LPS_OFF:
+		hal8812a1_ps_tdma_chk_pwr_save_state(btcoexist, false);
+		btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL);
+		break;
+	default:
+		break;
+	}
+}
+
+static void halbtc8812a1ant_coex_under_5g(struct btc_coexist *btcoexist)
+{
+	halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+					 0x0, 0x0);
+	halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 10);
+	halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+}
+
+static void halbtc8812a1ant_action_wifi_only(struct btc_coexist *btcoexist)
+{
+	halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+	halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9);
+}
+
+static void hal8812a1_monitor_bt_en_dis(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;
+
+	/*  only 8812a need to consider if core stack is installed. */
+	if (!stack_info->hci_version)
+		bt_active = false;
+
+	/*  This function check if bt is disabled */
+
+	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 all counters = 0, %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");
+			halbtc8812a1ant_action_wifi_only(btcoexist);
+		}
+	}
+	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;
+		if (bt_disabled) {
+			btcoexist->btc_set(btcoexist,
+					   BTC_SET_ACT_LEAVE_LPS, NULL);
+			btcoexist->btc_set(btcoexist,
+					   BTC_SET_ACT_NORMAL_LPS, NULL);
+		}
+	}
+}
+
+/*Non-Software Coex Mechanism start */
+
+static void halbtc8812a1ant_action_hs(struct btc_coexist *btcoexist)
+{
+	bool hs_connecting = false;
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting);
+
+	BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+		  "[BTCoex], Action for HS, hs_connecting =%d!!!\n",
+		  hs_connecting);
+	halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+
+	if (hs_connecting) {
+		halbtc8812a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 3);
+	} else {
+		if ((coex_sta->high_priority_tx + coex_sta->high_priority_rx +
+		     coex_sta->low_priority_tx +
+		     coex_sta->low_priority_rx) <= 1200)
+			halbtc8812a1ant_coex_table_with_type(btcoexist,
+							     FORCE_EXEC, 3);
+		else
+			halbtc8812a1ant_coex_table_with_type(btcoexist,
+							     FORCE_EXEC, 4);
+	}
+}
+
+static void halbtc8812a1ant_action_bt_inquiry(struct btc_coexist *btcoexist)
+{
+	struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+	bool wifi_connected = false;
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+			   &wifi_connected);
+
+	if (!wifi_connected) {
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+	} else if ((bt_link_info->sco_exist) ||
+		   (bt_link_info->hid_only)) {
+		/*  SCO/HID-only busy */
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+	} else {
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+						 0x50, 0x0);
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30);
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+	}
+}
+
+static void hal8812a1_act_bt_sco_hid_only_bsy(struct btc_coexist *btcoexist,
+					      u8 wifi_status)
+{
+	/*  tdma and coex table */
+	halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+
+	if (BT_8812A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN ==
+	    wifi_status)
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+	else
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+}
+
+static void hal8812a1_act_wifi_con_bt_acl_bsy(struct btc_coexist *btcoexist,
+					      u8 wifi_status)
+{
+	struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+
+	if (bt_link_info->hid_only) {
+		hal8812a1_act_bt_sco_hid_only_bsy(btcoexist, wifi_status);
+		coex_dm->reset_tdma_adjust = true;
+		return;
+	} else if ((bt_link_info->a2dp_only) ||
+		   (bt_link_info->hid_exist && bt_link_info->a2dp_exist)) {
+		hal8812a1ant_tdma_dur_adj_for_acl(btcoexist, wifi_status);
+	} else if ((bt_link_info->pan_only) ||
+		   (bt_link_info->hid_exist && bt_link_info->pan_exist)) {
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3);
+		coex_dm->reset_tdma_adjust = true;
+	} else {
+		if ((BT_8812A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN ==
+		     wifi_status) ||
+		    (BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifi_status) ||
+		    (BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT ==
+		     wifi_status))
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						true, 9);
+		else
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						true, 11);
+		coex_dm->reset_tdma_adjust = true;
+	}
+
+	halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+}
+
+static void hal8812a1_action_wifi_not_conn(struct btc_coexist *btcoexist)
+{
+	/*  power save state */
+	halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+					 0x0, 0x0);
+
+	/*  tdma and coex table */
+	halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+	halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+}
+
+static void hal12a1_act_wifi_no_con_ass_auth_scan(struct btc_coexist *btcoexist)
+{
+	halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+					 0x0, 0x0);
+	/*  tdma and coex table */
+	halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+	halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+}
+
+static void hal8812a1_action_wifi_conn_scan(struct btc_coexist *btcoexist)
+{
+	/*  power save state */
+	if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status &&
+	    !btcoexist->bt_link_info.hid_only)
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+						 0x50, 0x0);
+	else
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+	/*  tdma and coex table */
+	if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
+		hal8812a1_act_wifi_con_bt_acl_bsy(btcoexist,
+			BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SCAN);
+	} else if ((BT_8812A_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
+		   (BT_8812A_1ANT_BT_STATUS_ACL_SCO_BUSY ==
+		    coex_dm->bt_status)) {
+		hal8812a1_act_bt_sco_hid_only_bsy(btcoexist,
+			BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SCAN);
+	} else {
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+	}
+}
+
+static void hal8812a1_action_wifi_conn_sp_pkt(struct btc_coexist *btcoexist)
+{
+	/*  power save state */
+	if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status &&
+	    !btcoexist->bt_link_info.hid_only)
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+						 0x50, 0x0);
+	else
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+	/*  tdma and coex table */
+	if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
+		hal8812a1_act_wifi_con_bt_acl_bsy(btcoexist,
+			BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT);
+	} else {
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+		halbtc8812a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+	}
+}
+
+static void halbtc8812a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
+{
+	bool wifi_connected = false, wifi_busy = false;
+	bool scan = false, link = false, roam = false;
+	bool under_4way = false;
+
+	BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+		  "[BTCoex], CoexForWifiConnect() ===>\n");
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+			   &wifi_connected);
+	if (!wifi_connected) {
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], CoexForWifiConnect(), return for wifi not connected<===\n");
+		return;
+	}
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+			   &under_4way);
+	if (under_4way) {
+		hal8812a1_action_wifi_conn_sp_pkt(btcoexist);
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n");
+		return;
+	}
+	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) {
+		hal8812a1_action_wifi_conn_scan(btcoexist);
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n");
+		return;
+	}
+
+	/*  power save state */
+	if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status &&
+	    !btcoexist->bt_link_info.hid_only)
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+						 0x50, 0x0);
+	else
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+	/*  tdma and coex table */
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+	if (!wifi_busy) {
+		if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
+			hal8812a1_act_wifi_con_bt_acl_bsy(btcoexist,
+				BT_8812A_1ANT_WIFI_STATUS_CONNECTED_IDLE);
+		} else if ((BT_8812A_1ANT_BT_STATUS_SCO_BUSY ==
+			    coex_dm->bt_status) ||
+			   (BT_8812A_1ANT_BT_STATUS_ACL_SCO_BUSY ==
+			    coex_dm->bt_status)) {
+			hal8812a1_act_bt_sco_hid_only_bsy(btcoexist,
+				BT_8812A_1ANT_WIFI_STATUS_CONNECTED_IDLE);
+		} else {
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						false, 8);
+			halbtc8812a1ant_coex_table_with_type(btcoexist,
+							     NORMAL_EXEC, 2);
+		}
+	} else {
+		if (BT_8812A_1ANT_BT_STATUS_NON_CONNECTED_IDLE ==
+		    coex_dm->bt_status) {
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						true, 5);
+			halbtc8812a1ant_coex_table_with_type(btcoexist,
+							     NORMAL_EXEC, 2);
+		} else if (BT_8812A_1ANT_BT_STATUS_CONNECTED_IDLE ==
+			   coex_dm->bt_status) {
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						true, 5);
+			halbtc8812a1ant_coex_table_with_type(btcoexist,
+							     NORMAL_EXEC, 2);
+		} else if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY ==
+			   coex_dm->bt_status) {
+			hal8812a1_act_wifi_con_bt_acl_bsy(btcoexist,
+				BT_8812A_1ANT_WIFI_STATUS_CONNECTED_BUSY);
+		} else if ((BT_8812A_1ANT_BT_STATUS_SCO_BUSY ==
+			    coex_dm->bt_status) ||
+			   (BT_8812A_1ANT_BT_STATUS_ACL_SCO_BUSY ==
+			    coex_dm->bt_status)) {
+			hal8812a1_act_bt_sco_hid_only_bsy(btcoexist,
+				BT_8812A_1ANT_WIFI_STATUS_CONNECTED_BUSY);
+		} else {
+			halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+						false, 8);
+			halbtc8812a1ant_coex_table_with_type(btcoexist,
+							     NORMAL_EXEC, 2);
+		}
+	}
+}
+
+static void halbtc8812a1ant_RunCoexistMechanism(struct btc_coexist *btcoexist)
+{
+	bool wifi_under_5g = false, wifi_connected = false, bt_hs_on = false;
+
+	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 (btcoexist->stop_coex_dm) {
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\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");
+		halbtc8812a1ant_coex_under_5g(btcoexist);
+		return;
+	}
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+	if (coex_sta->c2h_bt_inquiry_page) {
+		halbtc8812a1ant_action_bt_inquiry(btcoexist);
+		return;
+	} else if (bt_hs_on) {
+		halbtc8812a1ant_action_hs(btcoexist);
+		return;
+	}
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+			   &wifi_connected);
+	if (!wifi_connected) {
+		bool scan = false, link = false, roam = false;
+
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], wifi is non connected-idle !!!\n");
+
+		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)
+			hal12a1_act_wifi_no_con_ass_auth_scan(btcoexist);
+		else
+			hal8812a1_action_wifi_not_conn(btcoexist);
+	} else { /*  wifi LPS/Busy */
+		halbtc8812a1ant_action_wifi_connected(btcoexist);
+	}
+}
+
+static void halbtc8812a1ant_init_coex_dm(struct btc_coexist *btcoexist)
+{
+	/*  force to reset coex mechanism */
+	halbtc8812a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+	halbtc8812a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+}
+
+/*  work around function start with wa_halbtc8812a1ant_ */
+/*  extern function start with EXhalbtc8812a1ant_ */
+
+void ex_halbtc8812a1ant_init_hwconfig(struct btc_coexist *btcoexist)
+{
+	u8 u1_tmp = 0;
+
+	BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+		  "[BTCoex], 1Ant Init HW Config!!\n");
+
+	/* ant sw control to BT */
+	halbtc8812a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, 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);
+}
+
+void ex_halbtc8812a1ant_init_coex_dm(struct btc_coexist *btcoexist)
+{
+	BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+		  "[BTCoex], Coex Mechanism Init!!\n");
+
+	btcoexist->stop_coex_dm = false;
+
+	halbtc8812a1ant_init_coex_dm(btcoexist);
+}
+
+void ex_halbtc8812a1ant_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;
+	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]============");
+
+	if (btcoexist->manual_control) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "============[Under Manual Control]============");
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "==========================================");
+	}
+	if (btcoexist->stop_coex_dm) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "============[Coex is STOPPED]============");
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "==========================================");
+	}
+
+	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_1ant, glcoex_ver_8812a_1ant, 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 / HsChnl(HsMode)",
+		 wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on);
+
+	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_1ANT_BT_STATUS_NON_CONNECTED_IDLE ==
+		    coex_dm->bt_status) ? "non-connected idle" :
+		   ((BT_8812A_1ANT_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_1ANT_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_1ant[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)",
+		 "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);
+
+	if (!btcoexist->manual_control) {
+		/*  Sw mechanism */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "============[Sw mechanism]============\n");
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %s/ %s/ %d\n ",
+			 "DelBA/ BtCtrlAgg/ AggSize",
+			 (btcoexist->bt_info.reject_agg_pkt ? "Yes" : "No"),
+			 (btcoexist->bt_info.bt_ctrl_buf_size ? "Yes" : "No"),
+			 btcoexist->bt_info.agg_buf_size);
+
+		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\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);
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x\n",
+			 "Latest error condition(should be 0)",
+			 coex_dm->error_condition);
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d\n",
+			 "IgnWlanAct",
+			 coex_dm->cur_ignore_wlan_act);
+	}
+
+	/*  Hw setting */
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "============[Hw setting]============\n");
+
+	u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x\n", "0x778\n",
+		 u1_tmp[0]);
+
+	u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xcb3);
+	u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xcb7);
+	u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x900);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "%-35s = 0x%x/ 0x%x/ 0x%x\n", "0xcb3/0xcb7/0x900\n",
+		 u1_tmp[0], u1_tmp[1], u4_tmp[0]);
+
+	u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x\n", "0x40",
+		 u1_tmp[0]);
+
+	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);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = 0x%x\n",
+		 "0xc50(dig)", u4_tmp[0]);
+
+	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(hp rx[31:16]/tx[15:0])",
+		 coex_sta->high_priority_rx, coex_sta->high_priority_tx);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%-35s = %d/ %d\n",
+		 "0x774(lp rx[31:16]/tx[15:0])",
+		 coex_sta->low_priority_rx, coex_sta->low_priority_tx);
+}
+
+void ex_halbtc8812a1ant_ips_notify(struct btc_coexist *btcoexist,
+				   u8 type)
+{
+	if (btcoexist->manual_control || btcoexist->stop_coex_dm)
+		return;
+
+	if (BTC_IPS_ENTER == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], IPS ENTER notify\n");
+		coex_sta->under_ips = true;
+		halbtc8812a1ant_coex_all_off(btcoexist);
+		halbtc8812a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+					     false, true);
+	} else if (BTC_IPS_LEAVE == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], IPS LEAVE notify\n");
+		coex_sta->under_ips = false;
+	}
+}
+
+void ex_halbtc8812a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
+{
+	if (btcoexist->manual_control || btcoexist->stop_coex_dm)
+		return;
+
+	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_halbtc8812a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
+{
+	bool wifi_connected = false, bt_hs_on = false;
+
+	if (btcoexist->manual_control ||
+	    btcoexist->stop_coex_dm ||
+	    btcoexist->bt_info.bt_disabled)
+		return;
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+	if (coex_sta->c2h_bt_inquiry_page) {
+		halbtc8812a1ant_action_bt_inquiry(btcoexist);
+		return;
+	} else if (bt_hs_on) {
+		halbtc8812a1ant_action_hs(btcoexist);
+		return;
+	}
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+			   &wifi_connected);
+	if (BTC_SCAN_START == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], SCAN START notify\n");
+		if (!wifi_connected) /*  non-connected scan */
+			hal12a1_act_wifi_no_con_ass_auth_scan(btcoexist);
+		else	/*  wifi is connected */
+			hal8812a1_action_wifi_conn_scan(btcoexist);
+	} else if (BTC_SCAN_FINISH == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], SCAN FINISH notify\n");
+		if (!wifi_connected)	/*  non-connected scan */
+			hal8812a1_action_wifi_not_conn(btcoexist);
+		else
+			halbtc8812a1ant_action_wifi_connected(btcoexist);
+	}
+}
+
+void ex_halbtc8812a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
+{
+	bool wifi_connected = false, bt_hs_on = false;
+
+	if (btcoexist->manual_control ||
+	    btcoexist->stop_coex_dm ||
+	    btcoexist->bt_info.bt_disabled)
+		return;
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+	if (coex_sta->c2h_bt_inquiry_page) {
+		halbtc8812a1ant_action_bt_inquiry(btcoexist);
+		return;
+	} else if (bt_hs_on) {
+		halbtc8812a1ant_action_hs(btcoexist);
+		return;
+	}
+
+	if (BTC_ASSOCIATE_START == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], CONNECT START notify\n");
+		hal12a1_act_wifi_no_con_ass_auth_scan(btcoexist);
+	} else if (BTC_ASSOCIATE_FINISH == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], CONNECT FINISH notify\n");
+
+		btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+				   &wifi_connected);
+		if (!wifi_connected) /*  non-connected scan */
+			hal8812a1_action_wifi_not_conn(btcoexist);
+		else
+			halbtc8812a1ant_action_wifi_connected(btcoexist);
+	}
+}
+
+void ex_btc8812a1ant_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_halbtc8812a1ant_special_packet_notify(struct btc_coexist *btcoexist,
+					      u8 type)
+{
+	bool bt_hs_on = false;
+
+	if (btcoexist->manual_control ||
+	    btcoexist->stop_coex_dm ||
+	    btcoexist->bt_info.bt_disabled)
+		return;
+
+	btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+	if (coex_sta->c2h_bt_inquiry_page) {
+		halbtc8812a1ant_action_bt_inquiry(btcoexist);
+		return;
+	} else if (bt_hs_on) {
+		halbtc8812a1ant_action_hs(btcoexist);
+		return;
+	}
+
+	if (BTC_PACKET_DHCP == type || BTC_PACKET_EAPOL == type) {
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY,
+			  "[BTCoex], special Packet(%d) notify\n", type);
+		hal8812a1_action_wifi_conn_sp_pkt(btcoexist);
+	}
+}
+
+void ex_halbtc8812a1ant_bt_info_notify(struct btc_coexist *btcoexist,
+				       u8 *tmp_buf, u8 length)
+{
+	struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+	u8 bt_info = 0;
+	u8 i, rsp_source = 0;
+	static u32 set_bt_psd_mode;
+	bool bt_busy = false;
+	bool wifi_connected = false;
+	bool b_bt_ctrl_buf_size = false, rej_ap_agg_pkt = false;
+
+	rsp_source = tmp_buf[0]&0xf;
+	if (rsp_source >= BT_INFO_SRC_8812A_1ANT_MAX)
+		rsp_source = BT_INFO_SRC_8812A_1ANT_WIFI_FW;
+	coex_sta->bt_info_c2h_cnt[rsp_source]++;
+
+	if (BT_INFO_SRC_8812A_1ANT_BT_RSP == rsp_source)
+		coex_sta->bt_info_query_cnt =
+		  coex_sta->bt_info_c2h_cnt[BT_INFO_SRC_8812A_1ANT_BT_RSP];
+
+	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 (btcoexist->bt_info.bt_disabled) {
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), return for BT is disabled <===\n");
+		return;
+	}
+
+	if (btcoexist->manual_control) {
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), return for Manual CTRL<===\n");
+		return;
+	}
+	if (btcoexist->stop_coex_dm) {
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), return for Coex STOPPED!!<===\n");
+		return;
+	}
+
+	if (BT_INFO_SRC_8812A_1ANT_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_btc8812a1ant_media_stat_notify(btcoexist,
+						 BTC_MEDIA_CONNECT);
+			else
+				ex_btc8812a1ant_media_stat_notify(btcoexist,
+						 BTC_MEDIA_DISCONNECT);
+			set_bt_psd_mode = 0;
+		}
+
+		/*  test-chip bt patch only rsp the status for BT_RSP, */
+		/*  so temporary we consider the following only under BT_RSP */
+		if (BT_INFO_SRC_8812A_1ANT_BT_RSP == rsp_source) {
+			if ((coex_sta->bt_info_ext & BIT3)) {
+				BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+					  "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
+				hal8812a1_ignore_wlan_act(btcoexist, FORCE_EXEC,
+							  false);
+			}
+
+			if ((coex_sta->bt_info_ext & BIT4)) {
+				/*  BT auto report already enabled, do nothing*/
+			} else {
+				BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+					  "[BTCoex], BT ext info bit4 check, set BT to enable Auto Report!!\n");
+				hal8812a1_bt_auto_rep(btcoexist,
+						      FORCE_EXEC, true);
+			}
+		}
+	}
+
+	/*  check BIT2 first ==> check if bt is under inquiry or page scan */
+	if (bt_info & BT_INFO_8812A_1ANT_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_1ANT_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_1ANT_B_FTP)
+			coex_sta->pan_exist = true;
+		else
+			coex_sta->pan_exist = false;
+		if (bt_info & BT_INFO_8812A_1ANT_B_A2DP)
+			coex_sta->a2dp_exist = true;
+		else
+			coex_sta->a2dp_exist = false;
+		if (bt_info & BT_INFO_8812A_1ANT_B_HID)
+			coex_sta->hid_exist = true;
+		else
+			coex_sta->hid_exist = false;
+		if (bt_info & BT_INFO_8812A_1ANT_B_SCO_ESCO)
+			coex_sta->sco_exist = true;
+		else
+			coex_sta->sco_exist = false;
+	}
+
+	halbtc8812a1ant_update_bt_link_info(btcoexist);
+
+	if (!(bt_info&BT_INFO_8812A_1ANT_B_CONNECTION)) {
+		coex_dm->bt_status = BT_8812A_1ANT_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_1ANT_B_CONNECTION) {
+		/*  connection exists but not busy */
+		coex_dm->bt_status = BT_8812A_1ANT_BT_STATUS_CONNECTED_IDLE;
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), bt connected-idle!!!\n");
+	} else if ((bt_info&BT_INFO_8812A_1ANT_B_SCO_ESCO) ||
+		   (bt_info&BT_INFO_8812A_1ANT_B_SCO_BUSY)) {
+		coex_dm->bt_status = BT_8812A_1ANT_BT_STATUS_SCO_BUSY;
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), bt sco busy!!!\n");
+	} else if (bt_info&BT_INFO_8812A_1ANT_B_ACL_BUSY) {
+		if (BT_8812A_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status)
+			coex_dm->reset_tdma_adjust = true;
+		coex_dm->bt_status = BT_8812A_1ANT_BT_STATUS_ACL_BUSY;
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), bt acl busy!!!\n");
+	} else {
+		coex_dm->bt_status = BT_8812A_1ANT_BT_STATUS_MAX;
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], BtInfoNotify(), bt non-defined state!!!\n");
+	}
+
+	if (bt_link_info->sco_exist) {
+		rej_ap_agg_pkt = true;
+		/*  disable cck 1M2M. */
+		halbtc8812a1ant_update_ra_mask(btcoexist, NORMAL_EXEC,
+					       BTC_RATE_DISABLE, 0x00000003);
+	} else {
+		/*  enable cck 1M2M. */
+		halbtc8812a1ant_update_ra_mask(btcoexist, NORMAL_EXEC,
+					       BTC_RATE_ENABLE, 0x00000003);
+	}
+
+	if ((BT_8812A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) ||
+	    (BT_8812A_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
+	    (BT_8812A_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) {
+		bt_busy = true;
+		if (bt_link_info->hid_exist)
+			b_bt_ctrl_buf_size = true;
+	} else {
+		bt_busy = false;
+	}
+	btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy);
+
+	/*Aggregation related setting */
+	/*  if sco, reject AddBA */
+	btcoexist->btc_set(btcoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT,
+			   &rej_ap_agg_pkt);
+	/*  decide BT control aggregation buf size or not */
+	btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE,
+			   &b_bt_ctrl_buf_size);
+	/*  real update aggregation setting */
+	btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
+	/*  */
+
+	halbtc8812a1ant_RunCoexistMechanism(btcoexist);
+}
+
+void ex_halbtc8812a1ant_halt_notify(struct btc_coexist *btcoexist)
+{
+	BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Halt notify\n"));
+
+	hal8812a1_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
+	halbtc8812a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
+	halbtc8812a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, false, true);
+	ex_btc8812a1ant_media_stat_notify(btcoexist, BTC_MEDIA_DISCONNECT);
+}
+
+void ex_halbtc8812a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
+{
+	BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify\n"));
+
+	if (BTC_WIFI_PNP_SLEEP == pnp_state) {
+		btcoexist->stop_coex_dm = true;
+		hal8812a1_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9);
+	}
+}
+
+void ex_halbtc8812a1ant_periodical(struct btc_coexist *btcoexist)
+{
+	static u8 dis_ver_info_cnt;
+	u32 fw_ver = 0, bt_patch_ver = 0;
+	struct btc_board_info *board_info = &btcoexist->board_info;
+	struct btc_stack_info *stack_info = &btcoexist->stack_info;
+
+	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_1ant, glcoex_ver_8812a_1ant,
+			  fw_ver, bt_patch_ver, bt_patch_ver);
+		BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT,
+			  "[BTCoex], ****************************************************************\n");
+	}
+
+	halbtc8812a1ant_query_bt_info(btcoexist);
+	halbtc8812a1ant_monitor_bt_ctr(btcoexist);
+	hal8812a1_monitor_bt_en_dis(btcoexist);
+}
+
+void ex_halbtc8812a1ant_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 = 0;
+
+	switch (op_code) {
+	case BTC_DBG_SET_COEX_NORMAL:
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], Set CoexMode to Normal\n");
+		btcoexist->manual_control = false;
+		halbtc8812a1ant_init_coex_dm(btcoexist);
+		break;
+	case BTC_DBG_SET_COEX_WIFI_ONLY:
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], Set CoexMode to Wifi Only\n");
+		btcoexist->manual_control = true;
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9);
+		break;
+	case BTC_DBG_SET_COEX_BT_ONLY:
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], Set CoexMode to BT only\n");
+		btcoexist->manual_control = true;
+		halbtc8812a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+						 0x0, 0x0);
+		halbtc8812a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
+		break;
+	case BTC_DBG_SET_COEX_DEC_BT_PWR:
+		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE,
+			  "[BTCoex], Set Dec BT power\n");
+		data_len = 4;
+		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/halbtc8812a1ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.h
new file mode 100644
index 0000000..ae2a916
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8812a1ant.h
@@ -0,0 +1,175 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
+ *
+ * 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-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
+ *
+ ******************************************************************************/
+
+#ifndef _BTC8812A1ANT_
+#define _BTC8812A1ANT_
+
+/*  The following is for 8812A_1ANT BT Co-exist definition */
+#define	BT_INFO_8812A_1ANT_B_FTP				BIT7
+#define	BT_INFO_8812A_1ANT_B_A2DP				BIT6
+#define	BT_INFO_8812A_1ANT_B_HID				BIT5
+#define	BT_INFO_8812A_1ANT_B_SCO_BUSY				BIT4
+#define	BT_INFO_8812A_1ANT_B_ACL_BUSY				BIT3
+#define	BT_INFO_8812A_1ANT_B_INQ_PAGE				BIT2
+#define	BT_INFO_8812A_1ANT_B_SCO_ESCO				BIT1
+#define	BT_INFO_8812A_1ANT_B_CONNECTION				BIT0
+
+#define	BT_INFO_8812A_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_)	\
+		(((_BT_INFO_EXT_&BIT0)) ? true : false)
+
+#define	BTC_RSSI_COEX_THRESH_TOL_8812A_1ANT		2
+
+#define	BTC_8812A_1ANT_SWITCH_TO_WIFI			0
+#define	BTC_8812A_1ANT_SWITCH_TO_BT			1
+
+enum BT_INFO_SRC_8812A_1ANT {
+	BT_INFO_SRC_8812A_1ANT_WIFI_FW			= 0x0,
+	BT_INFO_SRC_8812A_1ANT_BT_RSP			= 0x1,
+	BT_INFO_SRC_8812A_1ANT_BT_ACTIVE_SEND		= 0x2,
+	BT_INFO_SRC_8812A_1ANT_MAX
+};
+
+enum BT_8812A_1ANT_BT_STATUS {
+	BT_8812A_1ANT_BT_STATUS_NON_CONNECTED_IDLE	= 0x0,
+	BT_8812A_1ANT_BT_STATUS_CONNECTED_IDLE		= 0x1,
+	BT_8812A_1ANT_BT_STATUS_INQ_PAGE		= 0x2,
+	BT_8812A_1ANT_BT_STATUS_ACL_BUSY		= 0x3,
+	BT_8812A_1ANT_BT_STATUS_SCO_BUSY		= 0x4,
+	BT_8812A_1ANT_BT_STATUS_ACL_SCO_BUSY		= 0x5,
+	BT_8812A_1ANT_BT_STATUS_MAX
+};
+
+enum BT_8812A_1ANT_WIFI_STATUS {
+	BT_8812A_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE		= 0x0,
+	BT_8812A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN	= 0x1,
+	BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SCAN		= 0x2,
+	BT_8812A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT		= 0x3,
+	BT_8812A_1ANT_WIFI_STATUS_CONNECTED_IDLE		= 0x4,
+	BT_8812A_1ANT_WIFI_STATUS_CONNECTED_BUSY		= 0x5,
+	BT_8812A_1ANT_WIFI_STATUS_MAX
+};
+
+enum BT_8812A_1ANT_COEX_ALGO {
+	BT_8812A_1ANT_COEX_ALGO_UNDEFINED		= 0x0,
+	BT_8812A_1ANT_COEX_ALGO_SCO			= 0x1,
+	BT_8812A_1ANT_COEX_ALGO_HID			= 0x2,
+	BT_8812A_1ANT_COEX_ALGO_A2DP			= 0x3,
+	BT_8812A_1ANT_COEX_ALGO_A2DP_PANHS		= 0x4,
+	BT_8812A_1ANT_COEX_ALGO_PANEDR			= 0x5,
+	BT_8812A_1ANT_COEX_ALGO_PANHS			= 0x6,
+	BT_8812A_1ANT_COEX_ALGO_PANEDR_A2DP		= 0x7,
+	BT_8812A_1ANT_COEX_ALGO_PANEDR_HID		= 0x8,
+	BT_8812A_1ANT_COEX_ALGO_HID_A2DP_PANEDR		= 0x9,
+	BT_8812A_1ANT_COEX_ALGO_HID_A2DP		= 0xa,
+	BT_8812A_1ANT_COEX_ALGO_MAX			= 0xb,
+};
+
+struct coex_dm_8812a_1ant {
+	/*  fw mechanism */
+	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 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_low_penalty_ra;
+	bool cur_low_penalty_ra;
+	bool pre_dac_swing_on;/* not used */
+	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;
+	/*  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 error_condition;
+};
+
+struct coex_sta_8812a_1ant {
+	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_1ANT_MAX][10];
+	u32 bt_info_c2h_cnt[BT_INFO_SRC_8812A_1ANT_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_halbtc8812a1ant_power_on_setting(struct btc_coexist *btcoexist);
+void ex_halbtc8812a1ant_init_hwconfig(struct btc_coexist *btcoexist);
+void ex_halbtc8812a1ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_halbtc8812a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_halbtc8812a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8812a1ant_media_stat_notify(struct btc_coexist *btcoexist,
+				       u8 type);
+void ex_halbtc8812a1ant_special_packet_notify(struct btc_coexist *btcoexist,
+					      u8 type);
+void ex_halbtc8812a1ant_bt_info_notify(struct btc_coexist *btcoexist,
+				       u8 *tmp_buf, u8 length);
+void ex_halbtc8812a1ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_halbtc8812a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
+void ex_halbtc8812a1ant_periodical(struct btc_coexist *btcoexist);
+void ex_halbtc8812a1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_halbtc8812a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code,
+				    u8 op_len, u8 *data);
+
+#endif
-- 
2.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" 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 related

* [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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox