* Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames
From: Stanislaw Gruszka @ 2019-06-12 10:25 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: Lorenzo Bianconi, nbd, kvalo, linux-wireless
In-Reply-To: <20190612095302.GD8107@localhost.localdomain>
On Wed, Jun 12, 2019 at 11:53:03AM +0200, Lorenzo Bianconi wrote:
> > On Fri, May 31, 2019 at 11:38:23AM +0200, Lorenzo Bianconi wrote:
>
> [...]
>
> > > }
> > >
> > > urb->num_sgs = max_t(int, i, urb->num_sgs);
> > > - urb->transfer_buffer_length = urb->num_sgs * q->buf_size,
> > > + urb->transfer_buffer_length = urb->num_sgs * data_size;
> > > sg_init_marker(urb->sg, urb->num_sgs);
> > >
> > > return i ? : -ENOMEM;
> > > @@ -611,8 +611,12 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
> > > if (!q->entry)
> > > return -ENOMEM;
> > >
> > > - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> > > + if (dev->usb.sg_en)
> > > + q->buf_size = MT_BUF_WITH_OVERHEAD(MT_RX_BUF_SIZE);
> >
> > I strongly recommend to not doing this. While this should work
> > in theory creating buffer with size of 2k + some bytes might
> > trigger various bugs in dma mapping or other low level code.
>
> even in practice actually :)
I wouldn't be sure about this. It's not common to have buffers of
such size and crossing pages boundaries. It really can trigger
nasty bugs on various IOMMU drivers.
> but we can be more cautious since probably copying
> the first 128B will not make any difference
Not sure if I understand what you mean.
> > And skb_shered_info is needed only in first buffer IIUC.
> >
> > Also this patch seems to make first patch unnecessary except for
> > non sg_en case (in which I think rx AMSDU is broken anyway),
> > so I would prefer just to apply first patch.
>
> I do not think rx AMSDU is broken for non sg_en case since the max rx value
> allowed should be 3839 IIRC and we alloc one page in this case
If that's the case we should be fine, but then I do not understand
why we allocate 8*2k buffers for sg_en case, isn't that AP can
sent AMSDU frame 16k big?
Stanislaw
^ permalink raw reply
* Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support
From: Lorenzo Bianconi @ 2019-06-12 10:21 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Lorenzo Bianconi, nbd, kvalo, linux-wireless
In-Reply-To: <20190612100014.GA4431@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1562 bytes --]
On Jun 12, Stanislaw Gruszka wrote:
> On Wed, Jun 12, 2019 at 11:45:21AM +0200, Lorenzo Bianconi wrote:
> > > > +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> > > > + int *nsgs)
> > > > +{
> > > > + int data_len = min(len, MT_SKB_HEAD_LEN);
>
> Oh, and this looks unneeded as well as for len < MT_SKB_HEAD_LEN=128
> we will go through fast path.
I guess if we remove data_len = min(len, MT_SKB_HEAD_LEN) and even *nsgs = 0 at
the end we are making some assumptions on the value of MT_SKB_HEAD_LEN and
buf_size. In the patch I just avoided them but maybe we can just assume that
MT_SKB_HEAD_LEN and buf_size will not changed in the future. What do you
think?
>
> > > mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
> > > of the buffer in fragment, which supose to be more efficient,
> > > see comment in iwl_mvm_pass_packet_to_mac80211().
> >
> > Right here we copy 128B instead of 32 but I think it is good to have L3 and L4
> > header in the linear area of the skb since otherwise the stack will need to
> > align them
>
> Not sure if understand, I think aliment of L3 & L4 headers will be
> the same, assuming ieee80211 header is aligned the same in fragment
> buffer and in linear area. But if you think this is better to copy those
> to linear area I'm ok with that.
Sorry I have not been so clear. I mean in the stack before accessing a given
header we will run pskb_may_pull() that can end up copying the skb if there is
not enough space in the skb->head
Regards,
Lorenzo
>
> Stanislaw
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
From: Ulf Hansson @ 2019-06-12 10:10 UTC (permalink / raw)
To: Doug Anderson
Cc: Hunter, Adrian, Kalle Valo, Arend van Spriel,
brcm80211-dev-list.pdl@broadcom.com,
linux-rockchip@lists.infradead.org, Double Lo,
briannorris@chromium.org, linux-wireless@vger.kernel.org,
Naveen Gupta, Madhan Mohan R, mka@chromium.org, Wright Feng,
Chi-Hsien Lin, netdev@vger.kernel.org,
brcm80211-dev-list@cypress.com, Franky Lin,
linux-kernel@vger.kernel.org, Hante Meuleman, YueHaibing,
David S. Miller
In-Reply-To: <CAD=FV=U8eo78Ee9xjhGXJMv=8YF9o89KLX024GH3iBRnRjCRvQ@mail.gmail.com>
On Mon, 10 Jun 2019 at 18:50, Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Mon, Jun 10, 2019 at 1:56 AM Hunter, Adrian <adrian.hunter@intel.com> wrote:
> >
> > > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> > > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> > > @@ -16,6 +16,7 @@
> > > #include <linux/mmc/sdio_ids.h>
> > > #include <linux/mmc/sdio_func.h>
> > > #include <linux/mmc/card.h>
> > > +#include <linux/mmc/core.h>
> >
> > SDIO function drivers should not really include linux/mmc/core.h
> > (Also don't know why linux/mmc/card.h is included)
>
> OK, so I guess you're requesting an extra level of "sdio_" wrappers
> for all the functions I need to call. I don't think the wrappers buy
> us a ton other than to abstract things a little bit and make it look
> prettier. :-) ...but certainly I can code that up if that's what
> everyone wants.
Are the new code you refer to going to be used for anything else but
SDIO? If not, please put them in the sdio specific headers instead.
BTW, apologize for not looking at this series any earlier, but I will
come to it soon.
>
> Just to make sure, I looked in "drivers/net/wireless/" and I do see
> quite a few instances of "mmc_" functions being used. That doesn't
> mean all these instances are correct but it does appear to be
> commonplace. Selected examples:
>
> drivers/net/wireless/ath/ath10k/sdio.c:
> ret = mmc_hw_reset(ar_sdio->func->card->host);
mmc_hw_reset() is already an exported function, used by the mmc block
layer. So I think this is okay.
>
> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
> mmc_set_data_timeout(md, func->card);
> mmc_wait_for_req(func->card->host, mr);
These are not okay, none of these things calls should really be done
from an SDIO func driver.
It tells me that the func driver is a doing workaround for something
that should be managed in a common way.
>
> drivers/net/wireless/marvell/mwifiex/sdio.c:
> mmc_hw_reset(func->card->host);
Okay.
>
> drivers/net/wireless/rsi/rsi_91x_sdio.c:
> err = mmc_wait_for_cmd(host, &cmd, 3);
Not okay.
>
>
> ...anyway, I'll give it a few days and if nobody else chimes in then
> I'll assume you indeed want "sdio_" wrappers for things and I'll post
> a v4. If patch #1 happens to land in the meantime then I won't
> object. ;-)
Adrian has a very good point. We need to strive to avoid exporting
APIs to here and there and just trust that they will be used wisely.
If the above calls to mmc_wait_for_req|cmd() and
mmc_set_data_timeout() could have been avoided, we would probably have
a more proper solution by now.
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH] wireless: wil6210: no need to check return value of debugfs_create functions
From: Greg Kroah-Hartman @ 2019-06-12 10:09 UTC (permalink / raw)
To: Maya Erez, Kalle Valo; +Cc: David S. Miller, linux-wireless, wil6210
In-Reply-To: <20190612100717.GA19167@kroah.com>
On Wed, Jun 12, 2019 at 12:07:17PM +0200, Greg Kroah-Hartman wrote:
> On Tue, Jun 11, 2019 at 09:10:24PM +0200, Greg Kroah-Hartman wrote:
> > When calling debugfs functions, there is no need to ever check the
> > return value. The function can work or not, but the code logic should
> > never do something different based on this.
> >
> > Cc: Maya Erez <merez@codeaurora.org>
> > Cc: Kalle Valo <kvalo@codeaurora.org>
> > Cc: "David S. Miller" <davem@davemloft.net>
> > Cc: linux-wireless@vger.kernel.org
> > Cc: wil6210@qti.qualcomm.com
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > ---
> > drivers/net/wireless/ath/wil6210/debugfs.c | 80 ++++++----------------
> > 1 file changed, 22 insertions(+), 58 deletions(-)
>
> Oops, 0-day finally woke up and shows I messed this patch up. Please
> drop it, I will submit a v2 soon.
{sigh}, no, that was a different patch that broke things. This pathc is
fine, please consider it as-is.
I'll go get more coffee...
greg k-h
^ permalink raw reply
* Re: [PATCH] wireless: wil6210: no need to check return value of debugfs_create functions
From: Greg Kroah-Hartman @ 2019-06-12 10:07 UTC (permalink / raw)
To: Maya Erez, Kalle Valo; +Cc: David S. Miller, linux-wireless, wil6210
In-Reply-To: <20190611191024.GA17227@kroah.com>
On Tue, Jun 11, 2019 at 09:10:24PM +0200, Greg Kroah-Hartman wrote:
> When calling debugfs functions, there is no need to ever check the
> return value. The function can work or not, but the code logic should
> never do something different based on this.
>
> Cc: Maya Erez <merez@codeaurora.org>
> Cc: Kalle Valo <kvalo@codeaurora.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: linux-wireless@vger.kernel.org
> Cc: wil6210@qti.qualcomm.com
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
> drivers/net/wireless/ath/wil6210/debugfs.c | 80 ++++++----------------
> 1 file changed, 22 insertions(+), 58 deletions(-)
Oops, 0-day finally woke up and shows I messed this patch up. Please
drop it, I will submit a v2 soon.
thanks,
greg k-h
^ permalink raw reply
* [PATCH] mac80211: drop robust management frames from unknown TA
From: Johannes Berg @ 2019-06-12 10:04 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
When receiving a robust management frame, drop it if we don't have
rx->sta since then we don't have a security association and thus
couldn't possibly validate the frame.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/rx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 25577ede2986..fd3740000e87 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3831,6 +3831,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
case NL80211_IFTYPE_STATION:
if (!bssid && !sdata->u.mgd.use_4addr)
return false;
+ if (ieee80211_is_robust_mgmt_frame(skb) && !rx->sta)
+ return false;
if (multicast)
return true;
return ether_addr_equal(sdata->vif.addr, hdr->addr1);
--
2.17.2
^ permalink raw reply related
* Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support
From: Stanislaw Gruszka @ 2019-06-12 10:00 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: Lorenzo Bianconi, nbd, kvalo, linux-wireless
In-Reply-To: <20190612094519.GC8107@localhost.localdomain>
On Wed, Jun 12, 2019 at 11:45:21AM +0200, Lorenzo Bianconi wrote:
> > > +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> > > + int *nsgs)
> > > +{
> > > + int data_len = min(len, MT_SKB_HEAD_LEN);
Oh, and this looks unneeded as well as for len < MT_SKB_HEAD_LEN=128
we will go through fast path.
> > mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
> > of the buffer in fragment, which supose to be more efficient,
> > see comment in iwl_mvm_pass_packet_to_mac80211().
>
> Right here we copy 128B instead of 32 but I think it is good to have L3 and L4
> header in the linear area of the skb since otherwise the stack will need to
> align them
Not sure if understand, I think aliment of L3 & L4 headers will be
the same, assuming ieee80211 header is aligned the same in fragment
buffer and in linear area. But if you think this is better to copy those
to linear area I'm ok with that.
Stanislaw
^ permalink raw reply
* Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames
From: Lorenzo Bianconi @ 2019-06-12 9:53 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Lorenzo Bianconi, nbd, kvalo, linux-wireless
In-Reply-To: <20190612091036.GB2965@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1400 bytes --]
> On Fri, May 31, 2019 at 11:38:23AM +0200, Lorenzo Bianconi wrote:
[...]
> > }
> >
> > urb->num_sgs = max_t(int, i, urb->num_sgs);
> > - urb->transfer_buffer_length = urb->num_sgs * q->buf_size,
> > + urb->transfer_buffer_length = urb->num_sgs * data_size;
> > sg_init_marker(urb->sg, urb->num_sgs);
> >
> > return i ? : -ENOMEM;
> > @@ -611,8 +611,12 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
> > if (!q->entry)
> > return -ENOMEM;
> >
> > - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> > + if (dev->usb.sg_en)
> > + q->buf_size = MT_BUF_WITH_OVERHEAD(MT_RX_BUF_SIZE);
>
> I strongly recommend to not doing this. While this should work
> in theory creating buffer with size of 2k + some bytes might
> trigger various bugs in dma mapping or other low level code.
even in practice actually :) but we can be more cautious since probably copying
the first 128B will not make any difference
>
> And skb_shered_info is needed only in first buffer IIUC.
>
> Also this patch seems to make first patch unnecessary except for
> non sg_en case (in which I think rx AMSDU is broken anyway),
> so I would prefer just to apply first patch.
I do not think rx AMSDU is broken for non sg_en case since the max rx value
allowed should be 3839 IIRC and we alloc one page in this case
Regards,
Lorenzo
>
> Stanislaw
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] wlcore/wl18xx: Add invert-irq OF property for physically inverted IRQ
From: Eugeniu Rosca @ 2019-06-12 9:45 UTC (permalink / raw)
To: Marc Zyngier, Geert Uytterhoeven, Tony Lindgren, Kalle Valo,
Eyal Reizer
Cc: Simon Horman, David S. Miller, Greg Kroah-Hartman, Randy Dunlap,
Ulf Hansson, John Stultz, linux-wireless, netdev,
Linux Kernel Mailing List, Spyridon Papageorgiou, Joshua Frkuska,
George G . Davis, Andrey Gusakov, Linux-Renesas, Eugeniu Rosca,
Eugeniu Rosca, Thomas Gleixner, Jason Cooper, Linus Walleij
In-Reply-To: <08bc4755-5f47-d792-8b5a-927b5fbe7619@arm.com>
Hi,
cc: Linus Walleij
On Tue, Jun 11, 2019 at 10:00:41AM +0100, Marc Zyngier wrote:
> On 11/06/2019 09:45, Geert Uytterhoeven wrote:
> > CC irqchip
> >
> > Original thread at
> > https://lore.kernel.org/lkml/20190607172958.20745-1-erosca@de.adit-jv.com/
> >
> > On Mon, Jun 10, 2019 at 10:30 AM Tony Lindgren <tony@atomide.com> wrote:
> >> * Kalle Valo <kvalo@codeaurora.org> [190610 07:01]:
> >>> Eugeniu Rosca <erosca@de.adit-jv.com> writes:
> >>>
> >>>> The wl1837mod datasheet [1] says about the WL_IRQ pin:
> >>>>
> >>>> ---8<---
> >>>> SDIO available, interrupt out. Active high. [..]
> >>>> Set to rising edge (active high) on powerup.
> >>>> ---8<---
> >>>>
> >>>> That's the reason of seeing the interrupt configured as:
> >>>> - IRQ_TYPE_EDGE_RISING on HiKey 960/970
> >>>> - IRQ_TYPE_LEVEL_HIGH on a number of i.MX6 platforms
> >>>>
> >>>> We assert that all those platforms have the WL_IRQ pin connected
> >>>> to the SoC _directly_ (confirmed on HiKey 970 [2]).
> >>>>
> >>>> That's not the case for R-Car Kingfisher extension target, which carries
> >>>> a WL1837MODGIMOCT IC. There is an SN74LV1T04DBVR inverter present
> >>>> between the WLAN_IRQ pin of the WL18* chip and the SoC, effectively
> >>>> reversing the requirement quoted from [1]. IOW, in Kingfisher DTS
> >>>> configuration we would need to use IRQ_TYPE_EDGE_FALLING or
> >>>> IRQ_TYPE_LEVEL_LOW.
> >>>>
> >>>> Unfortunately, v4.2-rc1 commit bd763482c82ea2 ("wl18xx: wlan_irq:
> >>>> support platform dependent interrupt types") made a special case out
> >>>> of these interrupt types. After this commit, it is impossible to provide
> >>>> an IRQ configuration via DTS which would describe an inverter present
> >>>> between the WL18* chip and the SoC, generating the need for workarounds
> >>>> like [3].
> >>>>
> >>>> Create a boolean OF property, called "invert-irq" to specify that
> >>>> the WLAN_IRQ pin of WL18* is connected to the SoC via an inverter.
> >>>>
> >>>> This solution has been successfully tested on R-Car H3ULCB-KF-M06 using
> >>>> the DTS configuration [4] combined with the "invert-irq" property.
> >>>>
> >>>> [1] http://www.ti.com/lit/ds/symlink/wl1837mod.pdf
> >>>> [2] https://www.96boards.org/documentation/consumer/hikey/hikey970/hardware-docs/
> >>>> [3] https://github.com/CogentEmbedded/meta-rcar/blob/289fbd4f8354/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch
> >>>> [4] https://patchwork.kernel.org/patch/10895879/
> >>>> ("arm64: dts: ulcb-kf: Add support for TI WL1837")
> >>>>
> >>>> Signed-off-by: Eugeniu Rosca <erosca@de.adit-jv.com>
> >>>
> >>> Tony&Eyal, do you agree with this?
> >>
> >> Yeah if there's some hardware between the WLAN device and the SoC
> >> inverting the interrupt, I don't think we have clear a way to deal
> >> with it short of setting up a separate irqchip that does the
> >> translation.
> >
> > Yeah, inverting the interrupt type in DT works only for simple devices,
> > that don't need configuration.
> > A simple irqchip driver that just inverts the type sounds like a good
> > solution to me. Does something like that already exists?
>
> We already have plenty of that in the tree, the canonical example
> probably being drivers/irqchip/irq-mtk-sysirq.c. It should be pretty
> easy to turn this driver into something more generic.
I don't think drivers/irqchip/irq-mtk-sysirq.c can serve the
use-case/purpose of this patch. The MTK driver seems to be dealing with
the polarity inversion of on-SoC interrupts which are routed to GiC,
whereas in this patch we are talking about an off-chip interrupt
wired to R-Car GPIO controller.
It looks to me that the nice DTS sketch shared by Linus Walleij in [5]
might come closer to the concept proposed by Geert? FWIW, the
infrastructure/implementation to make this possible is still not ready.
One question to the wlcore/wl18xx maintainers: Why exactly do you give
freedom to users to set the interrupt as LEVEL_LOW/EDGE_FALLING [6]?
Apparently, this:
- complicates the wl18xx driver, thus increasing the chance for bugs
- is not supposed to reflect any HW differences between boards using
LEVEL_LOW/EDGE_FALLING and the boards using LEVEL_HIGH/EDGE_RISING
- doesn't bring any obvious advantage to the users, who are expected to
sense the same behavior regardless of the IRQ type set in DTS
- prevent the users to set IRQ type to LEVEL_LOW/EDGE_FALLING when
there is an inverter present between WL_IRQ and SoC
- seems to be not used almost at all, as 99% of mainline DTS set the
IRQ type to the canonical/NLCP LEVEL_HIGH/EDGE_RISING
[5] https://patchwork.ozlabs.org/patch/1095690/#2167076
("[V1,1/2] gpio: make it possible to set active-state on GPIO lines")
--------------------8<-------------------
gpio0: gpio {
compatible = "foo,chip";
gpio-controller;
(...)
};
inv0: inverter {
compatible = "inverter";
gpio-controller;
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
};
consumer {
compatible = "bar";
gpios = <&inv0 0 GPIO_ACTIVE_HIGH>;
};
--------------------8<-------------------
[6] bd763482c82ea2 ("wl18xx: wlan_irq: support platform dependent interrupt types")
--
Best Regards,
Eugeniu.
^ permalink raw reply
* Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support
From: Lorenzo Bianconi @ 2019-06-12 9:45 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Lorenzo Bianconi, nbd, kvalo, linux-wireless
In-Reply-To: <20190612085844.GA2965@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 3404 bytes --]
> Hi and sorry for late comment.
>
Hi Stanislaw,
> On Fri, May 31, 2019 at 11:38:22AM +0200, Lorenzo Bianconi wrote:
> > Commit f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes
> > for rx") breaks A-MSDU support. When A-MSDU is enable the device can
> > receive frames up to q->buf_size but they will be discarded in
> > mt76u_process_rx_entry since there is no enough room for
> > skb_shared_info. Fix the issue reallocating the skb and copying in the
> > linear area the first 128B of the received frames and in the frag_list
> > the remaining part.
> >
> > Fixes: f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes for rx")
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> > drivers/net/wireless/mediatek/mt76/usb.c | 52 +++++++++++++++++++----
> > 2 files changed, 44 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> > index 97a1296562d0..74d4edf941d6 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> > @@ -30,6 +30,7 @@
> > #define MT_TX_RING_SIZE 256
> > #define MT_MCU_RING_SIZE 32
> > #define MT_RX_BUF_SIZE 2048
> > +#define MT_SKB_HEAD_LEN 128
> >
> > struct mt76_dev;
> > struct mt76_wcid;
> > diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> > index bbaa1365bbda..2bfc8214c0d8 100644
> > --- a/drivers/net/wireless/mediatek/mt76/usb.c
> > +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> > @@ -429,6 +429,48 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
> > return dma_len;
> > }
> >
> > +static struct sk_buff *
> > +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> > + int *nsgs)
> > +{
> > + int data_len = min(len, MT_SKB_HEAD_LEN);
> > + struct sk_buff *skb;
> > +
> > + if (SKB_WITH_OVERHEAD(buf_size) >= MT_DMA_HDR_LEN + len) {
> > + /* fast path */
> > + skb = build_skb(data, buf_size);
> > + if (!skb)
> > + return NULL;
> > +
> > + skb_reserve(skb, MT_DMA_HDR_LEN);
> > + __skb_put(skb, len);
> > +
> > + return skb;
> > + }
> > +
> > + /* slow path, not enough space for data and
> > + * skb_shared_info
> > + */
> > + skb = alloc_skb(data_len, GFP_ATOMIC);
> > + if (!skb)
> > + return NULL;
> > +
> > + skb_put_data(skb, data + MT_DMA_HDR_LEN, data_len);
> mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
> of the buffer in fragment, which supose to be more efficient,
> see comment in iwl_mvm_pass_packet_to_mac80211().
Right here we copy 128B instead of 32 but I think it is good to have L3 and L4
header in the linear area of the skb since otherwise the stack will need to
align them
>
> > + data += (data_len + MT_DMA_HDR_LEN);
> > + len -= data_len;
> > + if (len > 0) {
> > + struct page *page = virt_to_head_page(data);
> > + int offset = data - (u8 *)page_address(page);
> u8 cast not needed.
>
> > + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
> > + page, offset, len, buf_size);
> > + } else {
> > + *nsgs = 0;
> This seems to be not necessary or a bug (use first buffer 2 times).
maybe I have been a little bit too paranoid here :)
Regards,
Lorenzo
>
> Stanislaw
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH] mt76: mt76x02u: fix sparse warnings: should it be static?
From: Lorenzo Bianconi @ 2019-06-12 9:31 UTC (permalink / raw)
To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sgruszka
Fix following sparse warnings in mt76x02_usb_core.c
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:29:6: warning:
symbol 'mt76x02u_tx_complete_skb' was not declared. Should it be static?
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:37:5: warning:
symbol 'mt76x02u_skb_dma_info' was not declared. Should it be static?
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:96:52: warning:
restricted __le16 degrades to integer
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:74:5: warning:
symbol 'mt76x02u_tx_prepare_skb' was not declared. Should it be static?
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:244:6: warning:
symbol 'mt76x02u_init_beacon_config' was not declared. Should it be
static?
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c:262:6: warning:
symbol 'mt76x02u_exit_beacon_config' was not declared. Should it be
static?
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index f3696afc1dde..1157d905b28c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "mt76x02.h"
+#include "mt76x02_usb.h"
static void mt76x02u_remove_dma_hdr(struct sk_buff *skb)
{
--
2.21.0
^ permalink raw reply related
* Re: rtw88: M.2 RTL8822BE not working - rfe 3 isn't supported
From: Stanislaw Gruszka @ 2019-06-12 9:13 UTC (permalink / raw)
To: g.schlmm; +Cc: linux-wireless, yhchuang
In-Reply-To: <0d0159a8-a83e-cef3-fd32-4928a2301719@gmail.com>
Cc Tony
On Sat, Jun 08, 2019 at 02:26:51PM +0200, g.schlmm wrote:
> my RTL8822BE M.2 card is not working with linux 5.2rc3
>
> the staging r8822be driver in linux 5.1 was working for this card
>
> from dmesg:
> > [ 8.001186] rtw_pci 0000:04:00.0: rfe 3 isn't supported
> > [ 8.003870] rtw_pci 0000:04:00.0: failed to setup chip efuse info
> > [ 8.006405] rtw_pci 0000:04:00.0: failed to setup chip information
>
> lspci:
> > 04:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. RTL8822BE 802.11a/b/g/n/ac WiFi adapter
> > Subsystem: Lenovo RTL8822BE 802.11a/b/g/n/ac WiFi adapter
> > Flags: fast devsel, IRQ 19
> > I/O ports at c000 [size=256]
> > Memory at 81200000 (64-bit, non-prefetchable) [size=64K]
> > Capabilities: [40] Power Management version 3
> > Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> > Capabilities: [70] Express Endpoint, MSI 00
> > Capabilities: [100] Advanced Error Reporting
> > Capabilities: [148] Device Serial Number 00-e0-4c-ff-fe-b8-22-01
> > Capabilities: [158] Latency Tolerance Reporting
> > Capabilities: [160] L1 PM Substates
> > Kernel modules: rtwpci
^ permalink raw reply
* Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames
From: Stanislaw Gruszka @ 2019-06-12 9:10 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: nbd, kvalo, linux-wireless, lorenzo.bianconi
In-Reply-To: <2ed0b595a12944a8cfea14e066bcc4fa24f0ba44.1559293385.git.lorenzo@kernel.org>
On Fri, May 31, 2019 at 11:38:23AM +0200, Lorenzo Bianconi wrote:
> Set usb buffer size taking into account skb_shared_info in order to
> not always copy the first part of received frames if A-MSDU is enabled
> for SG capable devices
>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/mt76.h | 3 +++
> drivers/net/wireless/mediatek/mt76/usb.c | 12 ++++++++----
> 2 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 74d4edf941d6..7899e9b88b54 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -32,6 +32,9 @@
> #define MT_RX_BUF_SIZE 2048
> #define MT_SKB_HEAD_LEN 128
>
> +#define MT_BUF_WITH_OVERHEAD(x) \
> + ((x) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
> +
> struct mt76_dev;
> struct mt76_wcid;
>
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index 2bfc8214c0d8..5081643ce701 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -286,7 +286,7 @@ static int
> mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
> int nsgs, gfp_t gfp)
> {
> - int i;
> + int i, data_size = SKB_WITH_OVERHEAD(q->buf_size);
>
> for (i = 0; i < nsgs; i++) {
> struct page *page;
> @@ -299,7 +299,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
>
> page = virt_to_head_page(data);
> offset = data - page_address(page);
> - sg_set_page(&urb->sg[i], page, q->buf_size, offset);
> + sg_set_page(&urb->sg[i], page, data_size, offset);
> }
>
> if (i < nsgs) {
> @@ -311,7 +311,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
> }
>
> urb->num_sgs = max_t(int, i, urb->num_sgs);
> - urb->transfer_buffer_length = urb->num_sgs * q->buf_size,
> + urb->transfer_buffer_length = urb->num_sgs * data_size;
> sg_init_marker(urb->sg, urb->num_sgs);
>
> return i ? : -ENOMEM;
> @@ -611,8 +611,12 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
> if (!q->entry)
> return -ENOMEM;
>
> - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> + if (dev->usb.sg_en)
> + q->buf_size = MT_BUF_WITH_OVERHEAD(MT_RX_BUF_SIZE);
I strongly recommend to not doing this. While this should work
in theory creating buffer with size of 2k + some bytes might
trigger various bugs in dma mapping or other low level code.
And skb_shered_info is needed only in first buffer IIUC.
Also this patch seems to make first patch unnecessary except for
non sg_en case (in which I think rx AMSDU is broken anyway),
so I would prefer just to apply first patch.
Stanislaw
^ permalink raw reply
* Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support
From: Stanislaw Gruszka @ 2019-06-12 8:58 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: nbd, kvalo, linux-wireless, lorenzo.bianconi
In-Reply-To: <52ea155d9889aa15df44b4910806b74fa2fd9056.1559293385.git.lorenzo@kernel.org>
Hi and sorry for late comment.
On Fri, May 31, 2019 at 11:38:22AM +0200, Lorenzo Bianconi wrote:
> Commit f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes
> for rx") breaks A-MSDU support. When A-MSDU is enable the device can
> receive frames up to q->buf_size but they will be discarded in
> mt76u_process_rx_entry since there is no enough room for
> skb_shared_info. Fix the issue reallocating the skb and copying in the
> linear area the first 128B of the received frames and in the frag_list
> the remaining part.
>
> Fixes: f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes for rx")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> drivers/net/wireless/mediatek/mt76/usb.c | 52 +++++++++++++++++++----
> 2 files changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 97a1296562d0..74d4edf941d6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -30,6 +30,7 @@
> #define MT_TX_RING_SIZE 256
> #define MT_MCU_RING_SIZE 32
> #define MT_RX_BUF_SIZE 2048
> +#define MT_SKB_HEAD_LEN 128
>
> struct mt76_dev;
> struct mt76_wcid;
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index bbaa1365bbda..2bfc8214c0d8 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -429,6 +429,48 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
> return dma_len;
> }
>
> +static struct sk_buff *
> +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> + int *nsgs)
> +{
> + int data_len = min(len, MT_SKB_HEAD_LEN);
> + struct sk_buff *skb;
> +
> + if (SKB_WITH_OVERHEAD(buf_size) >= MT_DMA_HDR_LEN + len) {
> + /* fast path */
> + skb = build_skb(data, buf_size);
> + if (!skb)
> + return NULL;
> +
> + skb_reserve(skb, MT_DMA_HDR_LEN);
> + __skb_put(skb, len);
> +
> + return skb;
> + }
> +
> + /* slow path, not enough space for data and
> + * skb_shared_info
> + */
> + skb = alloc_skb(data_len, GFP_ATOMIC);
> + if (!skb)
> + return NULL;
> +
> + skb_put_data(skb, data + MT_DMA_HDR_LEN, data_len);
mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
of the buffer in fragment, which supose to be more efficient,
see comment in iwl_mvm_pass_packet_to_mac80211().
> + data += (data_len + MT_DMA_HDR_LEN);
> + len -= data_len;
> + if (len > 0) {
> + struct page *page = virt_to_head_page(data);
> + int offset = data - (u8 *)page_address(page);
u8 cast not needed.
> + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
> + page, offset, len, buf_size);
> + } else {
> + *nsgs = 0;
This seems to be not necessary or a bug (use first buffer 2 times).
Stanislaw
^ permalink raw reply
* Re: [RFC PATCH v2 3/3] ath11k: register HE mesh capabilities
From: Sven Eckelmann @ 2019-06-12 8:42 UTC (permalink / raw)
To: ath11k; +Cc: Bob Copeland, linux-wireless
In-Reply-To: <1919330.hVZVHELXip@bentobox>
[-- Attachment #1: Type: text/plain, Size: 1041 bytes --]
On Tuesday, 11 June 2019 21:52:20 CEST Sven Eckelmann wrote:
[...]
> if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
> rate_control_rate_init(sta);
>
> /* inform drivers about changes */
> rate_control_rate_update(local, sband, sta, changed);
>
> Both will at least cause a call to ath11k_peer_assoc_prepare +
> ath11k_wmi_send_peer_assoc_cmd but unfortunately the ath11k firmware hangs
> afterwards.
The fw hang seems to be related to the not set bss_conf.he_support in
ath11k_mac_vdev_start_restart. This has to be set when ieee80211_join_mesh
calls ieee80211_vif_use_channel. Otherwise the firmware will set a HT/VHT mode
in the firmware. Any sta with an higher phy mode will just hang the firmware.
So the two main problems right now are:
* set bss_conf.he_support during mesh_join before
ath11k_mac_vdev_start_restart is called
- no clue what the best approach is
* let ath11k redo the association procedure with he_cap->has_he set to true
when wpa_supplicant is in control of the peers.
Kind regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] mt76: mt7615: update peer's bssid when state transition changes
From: Ryder Lee @ 2019-06-12 8:37 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Sean Wang, YF Luo, linux-wireless, linux-kernel, Yiwei Chung,
linux-mediatek, Roy Luo, Lorenzo Bianconi, Felix Fietkau
In-Reply-To: <20190612082618.GA8107@localhost.localdomain>
On Wed, 2019-06-12 at 10:26 +0200, Lorenzo Bianconi wrote:
> > Driver should update peer's bssid and bss information when
> > state transition changes.
> >
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> > .../net/wireless/mediatek/mt76/mt7615/main.c | 5 +-
> > .../net/wireless/mediatek/mt76/mt7615/mcu.c | 49 ++++++++++---------
> > 2 files changed, 27 insertions(+), 27 deletions(-)
> >
>
> [...]
>
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > index e82086eb8aa4..8fc12cd37906 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > @@ -741,17 +741,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> > u8 *buf, *data, tx_wlan_idx = 0;
> > struct req_hdr *hdr;
> >
> > - if (en) {
> > - len += sizeof(struct bss_info_omac);
> > - features |= BIT(BSS_INFO_OMAC);
> > - if (mvif->omac_idx > EXT_BSSID_START) {
> > - len += sizeof(struct bss_info_ext_bss);
> > - features |= BIT(BSS_INFO_EXT_BSS);
> > - ntlv++;
> > - }
> > - ntlv++;
> > - }
> > -
> > switch (vif->type) {
> > case NL80211_IFTYPE_AP:
> > case NL80211_IFTYPE_MESH_POINT:
> > @@ -759,22 +748,23 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> > conn_type = CONNECTION_INFRA_AP;
> > break;
> > case NL80211_IFTYPE_STATION: {
> > - struct ieee80211_sta *sta;
> > - struct mt7615_sta *msta;
> > -
> > - rcu_read_lock();
> > -
> > - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
> > - if (!sta) {
> > + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */
> > + if (en) {
> > + struct ieee80211_sta *sta;
> > + struct mt7615_sta *msta;
> > +
> > + rcu_read_lock();
> > + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
> > + if (!sta) {
> > + rcu_read_unlock();
> > + return -EINVAL;
> > + }
> > +
> > + msta = (struct mt7615_sta *)sta->drv_priv;
> > + tx_wlan_idx = msta->wcid.idx;
> > rcu_read_unlock();
> > - return -EINVAL;
> > }
> > -
> > - msta = (struct mt7615_sta *)sta->drv_priv;
> > - tx_wlan_idx = msta->wcid.idx;
> > conn_type = CONNECTION_INFRA_STA;
> > -
> > - rcu_read_unlock();
> > break;
> > }
> > default:
> > @@ -782,6 +772,17 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> > break;
> > }
> >
> > + if (en) {
> > + len += sizeof(struct bss_info_omac);
> > + features |= BIT(BSS_INFO_OMAC);
> > + if (mvif->omac_idx > EXT_BSSID_START) {
> > + len += sizeof(struct bss_info_ext_bss);
> > + features |= BIT(BSS_INFO_EXT_BSS);
> > + ntlv++;
> > + }
> > + ntlv++;
> > + }
>
> What did you move this chunk down?
Ah, my bad. I originally planned to add other conditions and it may
change 'en' so moved these stuff behind them.
Anyway I forgot to remove this part. Will fix it
Ryder.
> Regards,
> Lorenzo
>
> > +
> > buf = kzalloc(len, GFP_KERNEL);
> > if (!buf)
> > return -ENOMEM;
> > --
> > 2.18.0
> >
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH v2] mt76: mt7615: add support for per-chain signal strength reporting
From: Lorenzo Bianconi @ 2019-06-12 8:37 UTC (permalink / raw)
To: Ryder Lee
Cc: Felix Fietkau, Lorenzo Bianconi, Roy Luo, YF Luo, Yiwei Chung,
Sean Wang, linux-wireless, linux-mediatek, linux-kernel
In-Reply-To: <22e5caff3581dc92fd6fec2f25966d86b7276bba.1560220443.git.ryder.lee@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 2776 bytes --]
> Fill in RX status->chain_signal to avoid empty value.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
> Changes since v2 - correct calculation sequence
> ---
> .../net/wireless/mediatek/mt76/mt7615/mac.c | 30 ++++++++++++++++++-
> .../net/wireless/mediatek/mt76/mt7615/mac.h | 5 ++++
> 2 files changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
> index b60d42b5923d..2f49a99e77b1 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
> @@ -13,6 +13,11 @@
> #include "../dma.h"
> #include "mac.h"
>
[...]
> @@ -169,7 +175,29 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
>
> status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
>
> - /* TODO: RSSI */
> + status->chains = dev->mt76.antenna_mask;
> + status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3);
> + status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3);
> + status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3);
> + status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3);
> + status->signal = status->chain_signal[0];
> +
> + switch (status->chains) {
> + case 0xf:
> + status->signal = max(status->signal,
> + status->chain_signal[3]);
> + /* fall through */
> + case 0x7:
> + status->signal = max(status->signal,
> + status->chain_signal[2]);
> + /* fall through */
> + case 0x3:
> + status->signal = max(status->signal,
> + status->chain_signal[1]);
> + break;
> + default:
> + break;
> + }
is it possible to enable rx chains selectively (e.g. chain 0 and 2)?
If so we can do something like:
for (i = 1; i < hweight8(dev->mt76.antenna_mask); i++) {
if (!(status->chains & BIT(i)))
continue;
status->signal = max(status->signal,
status->chain_signal[i]);
}
Regards,
Lorenzo
> rxd += 6;
> if ((u8 *)rxd - skb->data >= skb->len)
> return -EINVAL;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h
> index 18ad4b8a3807..b00ce8db58e9 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h
> @@ -98,6 +98,11 @@ enum rx_pkt_type {
> #define MT_RXV2_GROUP_ID GENMASK(26, 21)
> #define MT_RXV2_LENGTH GENMASK(20, 0)
>
> +#define MT_RXV4_RCPI3 GENMASK(31, 24)
> +#define MT_RXV4_RCPI2 GENMASK(23, 16)
> +#define MT_RXV4_RCPI1 GENMASK(15, 8)
> +#define MT_RXV4_RCPI0 GENMASK(7, 0)
> +
> enum tx_header_format {
> MT_HDR_FORMAT_802_3,
> MT_HDR_FORMAT_CMD,
> --
> 2.18.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] mt76: mt7615: update peer's bssid when state transition changes
From: Lorenzo Bianconi @ 2019-06-12 8:26 UTC (permalink / raw)
To: Ryder Lee
Cc: Felix Fietkau, Lorenzo Bianconi, Roy Luo, YF Luo, Yiwei Chung,
Sean Wang, linux-wireless, linux-mediatek, linux-kernel
In-Reply-To: <449fee28c558b6f02b62275f9beefaab02b47efc.1560221172.git.ryder.lee@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 2667 bytes --]
> Driver should update peer's bssid and bss information when
> state transition changes.
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
> .../net/wireless/mediatek/mt76/mt7615/main.c | 5 +-
> .../net/wireless/mediatek/mt76/mt7615/mcu.c | 49 ++++++++++---------
> 2 files changed, 27 insertions(+), 27 deletions(-)
>
[...]
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> index e82086eb8aa4..8fc12cd37906 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> @@ -741,17 +741,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> u8 *buf, *data, tx_wlan_idx = 0;
> struct req_hdr *hdr;
>
> - if (en) {
> - len += sizeof(struct bss_info_omac);
> - features |= BIT(BSS_INFO_OMAC);
> - if (mvif->omac_idx > EXT_BSSID_START) {
> - len += sizeof(struct bss_info_ext_bss);
> - features |= BIT(BSS_INFO_EXT_BSS);
> - ntlv++;
> - }
> - ntlv++;
> - }
> -
> switch (vif->type) {
> case NL80211_IFTYPE_AP:
> case NL80211_IFTYPE_MESH_POINT:
> @@ -759,22 +748,23 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> conn_type = CONNECTION_INFRA_AP;
> break;
> case NL80211_IFTYPE_STATION: {
> - struct ieee80211_sta *sta;
> - struct mt7615_sta *msta;
> -
> - rcu_read_lock();
> -
> - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
> - if (!sta) {
> + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */
> + if (en) {
> + struct ieee80211_sta *sta;
> + struct mt7615_sta *msta;
> +
> + rcu_read_lock();
> + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
> + if (!sta) {
> + rcu_read_unlock();
> + return -EINVAL;
> + }
> +
> + msta = (struct mt7615_sta *)sta->drv_priv;
> + tx_wlan_idx = msta->wcid.idx;
> rcu_read_unlock();
> - return -EINVAL;
> }
> -
> - msta = (struct mt7615_sta *)sta->drv_priv;
> - tx_wlan_idx = msta->wcid.idx;
> conn_type = CONNECTION_INFRA_STA;
> -
> - rcu_read_unlock();
> break;
> }
> default:
> @@ -782,6 +772,17 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> break;
> }
>
> + if (en) {
> + len += sizeof(struct bss_info_omac);
> + features |= BIT(BSS_INFO_OMAC);
> + if (mvif->omac_idx > EXT_BSSID_START) {
> + len += sizeof(struct bss_info_ext_bss);
> + features |= BIT(BSS_INFO_EXT_BSS);
> + ntlv++;
> + }
> + ntlv++;
> + }
What did you move this chunk down?
Regards,
Lorenzo
> +
> buf = kzalloc(len, GFP_KERNEL);
> if (!buf)
> return -ENOMEM;
> --
> 2.18.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [RESEND] brcmfmac support for BCM4359 sdio on arm64 ??
From: Christian Hewitt @ 2019-06-12 8:22 UTC (permalink / raw)
To: Arend Van Spriel
Cc: linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
Wright.Feng, Neil Armstrong, Christoph Muellner
In-Reply-To: <37d2964d-1c2b-51bd-ac98-2cc171aa0c9c@broadcom.com>
> On 11 Jun 2019, at 1:45 pm, Arend Van Spriel <arend.vanspriel@broadcom.com> wrote:
[snip]
> The splat could be relevant. Maybe try the patch below to get actual values that are checked in the WARN_ON.
Hi Arend,
I think the patch got mangled in transit - it wouldn’t compile. Can you please resend, perhaps share via a paste site?
Christian
^ permalink raw reply
* Re: [PATCH 07/11] rtw88: 8822c: use more accurate ofdm fa counting
From: Kalle Valo @ 2019-06-12 7:42 UTC (permalink / raw)
To: yhchuang; +Cc: linux-wireless
In-Reply-To: <1560321917-17751-8-git-send-email-yhchuang@realtek.com>
<yhchuang@realtek.com> writes:
> From: Yan-Hsuan Chuang <yhchuang@realtek.com>
>
> 8822c used to count OFDM FA count by subtracting tx count from FA count.
> But it need to substract more counters to be accurate.
>
> However, we can count it by adding up all of the FA counters we want.
> And it is simpler to add than list all of the components to substract.
>
> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
[...]
> --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
> @@ -1491,13 +1491,29 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
> u32 cck_enable;
> u32 cck_fa_cnt;
> u32 ofdm_fa_cnt;
> - u32 ofdm_tx_counter;
> + u32 ofdm_fa_cnt1, ofdm_fa_cnt2, ofdm_fa_cnt3, ofdm_fa_cnt4, ofdm_fa_cnt5;
> + u16 parity_fail, rate_illegal, crc8_fail, mcs_fail, sb_search_fail,
> + fast_fsync, crc8_fail_vhta, mcs_fail_vht;
>
> cck_enable = rtw_read32(rtwdev, REG_ENCCK) & BIT_CCK_BLK_EN;
> cck_fa_cnt = rtw_read16(rtwdev, REG_CCK_FACNT);
> - ofdm_fa_cnt = rtw_read16(rtwdev, REG_OFDM_FACNT);
> - ofdm_tx_counter = rtw_read16(rtwdev, REG_OFDM_TXCNT);
> - ofdm_fa_cnt -= ofdm_tx_counter;
> +
> + ofdm_fa_cnt1 = rtw_read32(rtwdev, REG_OFDM_FACNT1);
> + ofdm_fa_cnt2 = rtw_read32(rtwdev, REG_OFDM_FACNT2);
> + ofdm_fa_cnt3 = rtw_read32(rtwdev, REG_OFDM_FACNT3);
> + ofdm_fa_cnt4 = rtw_read32(rtwdev, REG_OFDM_FACNT4);
> + ofdm_fa_cnt5 = rtw_read32(rtwdev, REG_OFDM_FACNT5);
> +
> + parity_fail = (ofdm_fa_cnt1 & 0xffff0000) >> 16;
> + rate_illegal = (ofdm_fa_cnt2 & 0xffff);
> + crc8_fail = (ofdm_fa_cnt2 & 0xffff0000) >> 16;
> + crc8_fail_vhta = (ofdm_fa_cnt3 & 0xffff);
> + mcs_fail = (ofdm_fa_cnt4 & 0xffff);
> + mcs_fail_vht = (ofdm_fa_cnt4 & 0xffff0000) >> 16;
> + fast_fsync = (ofdm_fa_cnt5 & 0xffff);
> + sb_search_fail = (ofdm_fa_cnt5 & 0xffff0000) >> 16;
No magic numbers, please. IMO the cleanest way is to use create defines
using GENMASK() and FIELD_GET(), that way the values are proper
documented. An example (but not compile tested so can be buggy!):
#define OFDM_FA_CNT1_PARITY_FAIL GENMASK(31, 16)
parity_fail = FIELD_GET(OFDM_FA_CNT1_PARITY_FAIL, ofdm_fa_cnt1);
--
Kalle Valo
^ permalink raw reply
* Re: [BISECTED REGRESSION] b43legacy broken on G4 PowerBook
From: Christoph Hellwig @ 2019-06-12 6:55 UTC (permalink / raw)
To: Larry Finger
Cc: Christoph Hellwig, Aaro Koskinen, Christian Zigotzky,
Michael Ellerman, linux-kernel, linux-wireless, linuxppc-dev
In-Reply-To: <5aaa600b-5b59-1f68-454f-20403c318f1a@lwfinger.net>
On Tue, Jun 11, 2019 at 05:20:12PM -0500, Larry Finger wrote:
> Your first patch did not work as the configuration does not have
> CONFIG_ZONE_DMA. As a result, the initial value of min_mask always starts
> at 32 bits and is taken down to 31 with the maximum pfn minimization. When
> I forced the initial value of min_mask to 30 bits, the device worked.
Ooops, yes. But I think we could just enable ZONE_DMA on 32-bit
powerpc. Crude enablement hack below:
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8c1c636308c8..1dd71a98b70c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -372,7 +372,7 @@ config PPC_ADV_DEBUG_DAC_RANGE
config ZONE_DMA
bool
- default y if PPC_BOOK3E_64
+ default y
config PGTABLE_LEVELS
int
^ permalink raw reply related
* [PATCH 03/11] rtw88: add beacon function setting
From: yhchuang @ 2019-06-12 6:45 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <1560321917-17751-1-git-send-email-yhchuang@realtek.com>
From: Chin-Yen Lee <timlee@realtek.com>
Add beacon function setting routines for each hardware port.
If beacon function is not enabled, the hardware is not able
to synchronize with AP's beacon and can miss the beacons
under some scenarios such as PS mode.
For AP and Adhoc modes that require to send beacons, do not
update the TSF, otherwise the beacon interval may be affected.
Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
drivers/net/wireless/realtek/rtw88/mac80211.c | 13 +++++++++++++
drivers/net/wireless/realtek/rtw88/main.c | 5 +++++
drivers/net/wireless/realtek/rtw88/main.h | 3 +++
3 files changed, 21 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 61436bb..abe6a14 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -85,30 +85,35 @@ static const struct rtw_vif_port rtw_vif_port[] = {
.bssid = {.addr = 0x0618},
.net_type = {.addr = 0x0100, .mask = 0x30000},
.aid = {.addr = 0x06a8, .mask = 0x7ff},
+ .bcn_ctrl = {.addr = 0x0550, .mask = 0xff},
},
[1] = {
.mac_addr = {.addr = 0x0700},
.bssid = {.addr = 0x0708},
.net_type = {.addr = 0x0100, .mask = 0xc0000},
.aid = {.addr = 0x0710, .mask = 0x7ff},
+ .bcn_ctrl = {.addr = 0x0551, .mask = 0xff},
},
[2] = {
.mac_addr = {.addr = 0x1620},
.bssid = {.addr = 0x1628},
.net_type = {.addr = 0x1100, .mask = 0x3},
.aid = {.addr = 0x1600, .mask = 0x7ff},
+ .bcn_ctrl = {.addr = 0x0578, .mask = 0xff},
},
[3] = {
.mac_addr = {.addr = 0x1630},
.bssid = {.addr = 0x1638},
.net_type = {.addr = 0x1100, .mask = 0xc},
.aid = {.addr = 0x1604, .mask = 0x7ff},
+ .bcn_ctrl = {.addr = 0x0579, .mask = 0xff},
},
[4] = {
.mac_addr = {.addr = 0x1640},
.bssid = {.addr = 0x1648},
.net_type = {.addr = 0x1100, .mask = 0x30},
.aid = {.addr = 0x1608, .mask = 0x7ff},
+ .bcn_ctrl = {.addr = 0x057a, .mask = 0xff},
},
};
@@ -120,6 +125,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
enum rtw_net_type net_type;
u32 config = 0;
u8 port = 0;
+ u8 bcn_ctrl = 0;
rtwvif->port = port;
rtwvif->vif = vif;
@@ -136,13 +142,16 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
net_type = RTW_NET_AP_MODE;
+ bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
break;
case NL80211_IFTYPE_ADHOC:
net_type = RTW_NET_AD_HOC;
+ bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
break;
case NL80211_IFTYPE_STATION:
default:
net_type = RTW_NET_NO_LINK;
+ bcn_ctrl = BIT_EN_BCN_FUNCTION;
break;
}
@@ -150,6 +159,8 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
config |= PORT_SET_MAC_ADDR;
rtwvif->net_type = net_type;
config |= PORT_SET_NET_TYPE;
+ rtwvif->bcn_ctrl = bcn_ctrl;
+ config |= PORT_SET_BCN_CTRL;
rtw_vif_port_config(rtwdev, rtwvif, config);
mutex_unlock(&rtwdev->mutex);
@@ -173,6 +184,8 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
config |= PORT_SET_MAC_ADDR;
rtwvif->net_type = RTW_NET_NO_LINK;
config |= PORT_SET_NET_TYPE;
+ rtwvif->bcn_ctrl = 0;
+ config |= PORT_SET_BCN_CTRL;
rtw_vif_port_config(rtwdev, rtwvif, config);
mutex_unlock(&rtwdev->mutex);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 306d799..b8e0519 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -308,6 +308,11 @@ void rtw_vif_port_config(struct rtw_dev *rtwdev,
mask = rtwvif->conf->aid.mask;
rtw_write32_mask(rtwdev, addr, mask, rtwvif->aid);
}
+ if (config & PORT_SET_BCN_CTRL) {
+ addr = rtwvif->conf->bcn_ctrl.addr;
+ mask = rtwvif->conf->bcn_ctrl.mask;
+ rtw_write8_mask(rtwdev, addr, mask, rtwvif->bcn_ctrl);
+ }
}
static u8 hw_bw_cap_to_bitamp(u8 bw_cap)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 00fc77f..414d21f 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -431,6 +431,7 @@ enum rtw_vif_port_set {
PORT_SET_BSSID = BIT(1),
PORT_SET_NET_TYPE = BIT(2),
PORT_SET_AID = BIT(3),
+ PORT_SET_BCN_CTRL = BIT(4),
};
struct rtw_vif_port {
@@ -438,6 +439,7 @@ struct rtw_vif_port {
struct rtw_hw_reg bssid;
struct rtw_hw_reg net_type;
struct rtw_hw_reg aid;
+ struct rtw_hw_reg bcn_ctrl;
};
struct rtw_tx_pkt_info {
@@ -591,6 +593,7 @@ struct rtw_vif {
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
u8 port;
+ u8 bcn_ctrl;
const struct rtw_vif_port *conf;
struct rtw_traffic_stats stats;
--
2.7.4
^ permalink raw reply related
* [PATCH 05/11] rtw88: 8822c: update channel and bandwidth BB setting
From: yhchuang @ 2019-06-12 6:45 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <1560321917-17751-1-git-send-email-yhchuang@realtek.com>
From: Chien-Hsun Liao <ben.liao@realtek.com>
In 2G channels, the cck source and rxagc should be set to different
values based on different bandwidth to increase the performance of rx
sensitivity.
To improve rx throughput performance, the values of sbd subtune and
pt_opt should be changed in different bandwidth.
Signed-off-by: Chien-Hsun Liao <ben.liao@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 56 +++++++++++++++++++++++----
drivers/net/wireless/realtek/rtw88/rtw8822c.h | 7 ++++
2 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index b4f7242e..86acf60 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -1015,8 +1015,28 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_clr(rtwdev, REG_CCKTXONLY, BIT_BB_CCK_CHECK_EN);
rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0xF);
- rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x0);
- rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x0);
+ switch (bw) {
+ case RTW_CHANNEL_WIDTH_20:
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_CCK,
+ 0x5);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_CCK,
+ 0x5);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_OFDM,
+ 0x6);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_OFDM,
+ 0x6);
+ break;
+ case RTW_CHANNEL_WIDTH_40:
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_CCK,
+ 0x4);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_CCK,
+ 0x4);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_OFDM,
+ 0x0);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_OFDM,
+ 0x0);
+ break;
+ }
if (channel == 13 || channel == 14)
rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x969);
else if (channel == 11 || channel == 12)
@@ -1061,14 +1081,20 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0x22);
rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3);
if (channel >= 36 && channel <= 64) {
- rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x1);
- rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x1);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_OFDM,
+ 0x1);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_OFDM,
+ 0x1);
} else if (channel >= 100 && channel <= 144) {
- rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x2);
- rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x2);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_OFDM,
+ 0x2);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_OFDM,
+ 0x2);
} else if (channel >= 149) {
- rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x3);
- rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x3);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BIT_RXAGC_OFDM,
+ 0x3);
+ rtw_write32_mask(rtwdev, REG_RXAGCCTL, BIT_RXAGC_OFDM,
+ 0x3);
}
if (channel >= 36 && channel <= 51)
@@ -1092,6 +1118,9 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xffc0, 0x0);
rtw_write32_mask(rtwdev, REG_TXCLK, 0x700, 0x7);
rtw_write32_mask(rtwdev, REG_TXCLK, 0x700000, 0x6);
+ rtw_write32_mask(rtwdev, REG_CCK_SOURCE, BIT(30), 0x0);
+ rtw_write32_mask(rtwdev, REG_SBD, BIT_SUBTUNE, 0x1);
+ rtw_write32_mask(rtwdev, REG_PT_CHSMO, BIT_PT_OPT, 0x0);
break;
case RTW_CHANNEL_WIDTH_40:
rtw_write32_mask(rtwdev, REG_CCKSB, BIT(4),
@@ -1100,12 +1129,17 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0);
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00,
(primary_ch_idx | (primary_ch_idx << 4)));
+ rtw_write32_mask(rtwdev, REG_CCK_SOURCE, BIT(30), 0x1);
+ rtw_write32_mask(rtwdev, REG_SBD, BIT_SUBTUNE, 0x1);
+ rtw_write32_mask(rtwdev, REG_PT_CHSMO, BIT_PT_OPT, 0x1);
break;
case RTW_CHANNEL_WIDTH_80:
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0xa);
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0);
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00,
(primary_ch_idx | (primary_ch_idx << 4)));
+ rtw_write32_mask(rtwdev, REG_SBD, BIT_SUBTUNE, 0x6);
+ rtw_write32_mask(rtwdev, REG_PT_CHSMO, BIT_PT_OPT, 0x1);
break;
case RTW_CHANNEL_WIDTH_5:
rtw_write32_mask(rtwdev, REG_DFIRBW, 0x3FF0, 0x2AB);
@@ -1113,6 +1147,9 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xffc0, 0x1);
rtw_write32_mask(rtwdev, REG_TXCLK, 0x700, 0x4);
rtw_write32_mask(rtwdev, REG_TXCLK, 0x700000, 0x4);
+ rtw_write32_mask(rtwdev, REG_CCK_SOURCE, BIT(30), 0x0);
+ rtw_write32_mask(rtwdev, REG_SBD, BIT_SUBTUNE, 0x1);
+ rtw_write32_mask(rtwdev, REG_PT_CHSMO, BIT_PT_OPT, 0x0);
break;
case RTW_CHANNEL_WIDTH_10:
rtw_write32_mask(rtwdev, REG_DFIRBW, 0x3FF0, 0x2AB);
@@ -1120,6 +1157,9 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xffc0, 0x2);
rtw_write32_mask(rtwdev, REG_TXCLK, 0x700, 0x6);
rtw_write32_mask(rtwdev, REG_TXCLK, 0x700000, 0x5);
+ rtw_write32_mask(rtwdev, REG_CCK_SOURCE, BIT(30), 0x0);
+ rtw_write32_mask(rtwdev, REG_SBD, BIT_SUBTUNE, 0x1);
+ rtw_write32_mask(rtwdev, REG_PT_CHSMO, BIT_PT_OPT, 0x0);
break;
}
}
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
index d3bd985..5fe6acb 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
@@ -133,6 +133,8 @@ struct rtw8822c_efuse {
#define REG_DYMPRITH 0x86c
#define REG_DYMENTH0 0x870
#define REG_DYMENTH 0x874
+#define REG_SBD 0x88c
+#define BIT_SUBTUNE 0xf000
#define REG_DYMTHMIN 0x8a4
#define REG_TXBWCTL 0x9b0
#define REG_TXCLK 0x9b4
@@ -140,12 +142,16 @@ struct rtw8822c_efuse {
#define REG_MRCM 0xc38
#define REG_AGCSWSH 0xc44
#define REG_ANTWTPD 0xc54
+#define REG_PT_CHSMO 0xcbc
+#define BIT_PT_OPT BIT(21)
#define REG_ORITXCODE 0x1800
#define REG_3WIRE 0x180c
#define BIT_3WIRE_TX_EN BIT(0)
#define BIT_3WIRE_RX_EN BIT(1)
#define BIT_3WIRE_PI_ON BIT(28)
#define REG_RXAGCCTL0 0x18ac
+#define BIT_RXAGC_CCK 0xf000
+#define BIT_RXAGC_OFDM 0x1f0
#define REG_CCKSB 0x1a00
#define REG_RXCCKSEL 0x1a04
#define REG_BGCTRL 0x1a14
@@ -164,6 +170,7 @@ struct rtw8822c_efuse {
#define REG_TXF5 0x1aa0
#define REG_TXF6 0x1aac
#define REG_TXF7 0x1ab0
+#define REG_CCK_SOURCE 0x1abc
#define REG_TXANT 0x1c28
#define REG_ENCCK 0x1c3c
#define BIT_CCK_BLK_EN BIT(1)
--
2.7.4
^ permalink raw reply related
* [PATCH 06/11] rtw88: 8822c: disable rx clock gating before counter reset
From: yhchuang @ 2019-06-12 6:45 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <1560321917-17751-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
Driver Could fail to reset counter if rx clock gating is not disabled.
So we need to disable rx clock gating before resetting counters.
Otherwise counters may increase unexpected.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 4 ++++
drivers/net/wireless/realtek/rtw88/rtw8822c.h | 2 ++
2 files changed, 6 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index 86acf60..b9185b2 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -1508,8 +1508,12 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 2);
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 2);
+
+ /* disable rx clk gating to reset counters */
+ rtw_write32_clr(rtwdev, REG_RX_BREAK, BIT_COM_RX_GCK_EN);
rtw_write32_set(rtwdev, REG_CNT_CTRL, BIT_ALL_CNT_RST);
rtw_write32_clr(rtwdev, REG_CNT_CTRL, BIT_ALL_CNT_RST);
+ rtw_write32_set(rtwdev, REG_RX_BREAK, BIT_COM_RX_GCK_EN);
}
static void rtw8822c_do_iqk(struct rtw_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
index 5fe6acb..bf41359 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
@@ -176,6 +176,8 @@ struct rtw8822c_efuse {
#define BIT_CCK_BLK_EN BIT(1)
#define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1))
#define REG_CCAMSK 0x1c80
+#define REG_RX_BREAK 0x1d2c
+#define BIT_COM_RX_GCK_EN BIT(31)
#define REG_RXFNCTL 0x1d30
#define REG_RXIGI 0x1d70
#define REG_ENFN 0x1e24
--
2.7.4
^ permalink raw reply related
* [PATCH 09/11] rtw88: restore DACK results to save time
From: yhchuang @ 2019-06-12 6:45 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <1560321917-17751-1-git-send-email-yhchuang@realtek.com>
From: Yan-Hsuan Chuang <yhchuang@realtek.com>
DACK is done right after the hardware has been turned on, which
means it will be done every time we leave the IDLE state.
But it takes ~2 seconds to finish DACK.
We can back up the results and restore them. And it only takes a few
milliseconds to restore the results to the hardware, saving a lot of
time.
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
drivers/net/wireless/realtek/rtw88/main.h | 8 +
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 351 +++++++++++++++++++++++++-
drivers/net/wireless/realtek/rtw88/rtw8822c.h | 8 +
3 files changed, 355 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 414d21f..92730507 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -841,6 +841,9 @@ struct rtw_chip_info {
u32 rfe_defs_size;
};
+#define DACK_MSBK_BACKUP_NUM 0xf
+#define DACK_DCK_BACKUP_NUM 0x2
+
struct rtw_dm_info {
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
@@ -856,6 +859,11 @@ struct rtw_dm_info {
u8 cck_gi_u_bnd;
u8 cck_gi_l_bnd;
+
+ /* backup dack results for each path and I/Q */
+ u32 dack_adck[RTW_RF_PATH_MAX];
+ u16 dack_msbk[RTW_RF_PATH_MAX][2][DACK_MSBK_BACKUP_NUM];
+ u8 dack_dck[RTW_RF_PATH_MAX][2][DACK_DCK_BACKUP_NUM];
};
struct rtw_efuse {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index 4896f25..8198f2e 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -203,7 +203,7 @@ static void rtw8822c_dac_iq_offset(struct rtw_dev *rtwdev, u32 *vec, u32 *val)
*val = t;
}
-static u32 rtw8822c_get_path_base_addr(u8 path)
+static u32 rtw8822c_get_path_write_addr(u8 path)
{
u32 base_addr;
@@ -222,6 +222,25 @@ static u32 rtw8822c_get_path_base_addr(u8 path)
return base_addr;
}
+static u32 rtw8822c_get_path_read_addr(u8 path)
+{
+ u32 base_addr;
+
+ switch (path) {
+ case RF_PATH_A:
+ base_addr = 0x2800;
+ break;
+ case RF_PATH_B:
+ base_addr = 0x4500;
+ break;
+ default:
+ WARN_ON(1);
+ return -1;
+ }
+
+ return base_addr;
+}
+
static bool rtw8822c_dac_iq_check(struct rtw_dev *rtwdev, u32 value)
{
bool ret = true;
@@ -316,8 +335,6 @@ static void rtw8822c_dac_cal_rf_mode(struct rtw_dev *rtwdev,
u32 iv[DACK_SN_8822C], qv[DACK_SN_8822C];
u32 rf_a, rf_b;
- mdelay(10);
-
rf_a = rtw_read_rf(rtwdev, RF_PATH_A, 0x0, RFREG_MASK);
rf_b = rtw_read_rf(rtwdev, RF_PATH_B, 0x0, RFREG_MASK);
@@ -347,6 +364,7 @@ static void rtw8822c_dac_bb_setting(struct rtw_dev *rtwdev)
static void rtw8822c_dac_cal_adc(struct rtw_dev *rtwdev,
u8 path, u32 *adc_ic, u32 *adc_qc)
{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 ic = 0, qc = 0, temp = 0;
u32 base_addr;
u32 path_sel;
@@ -354,7 +372,7 @@ static void rtw8822c_dac_cal_adc(struct rtw_dev *rtwdev,
rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] ADCK path(%d)\n", path);
- base_addr = rtw8822c_get_path_base_addr(path);
+ base_addr = rtw8822c_get_path_write_addr(path);
switch (path) {
case RF_PATH_A:
path_sel = 0xa0000;
@@ -396,6 +414,7 @@ static void rtw8822c_dac_cal_adc(struct rtw_dev *rtwdev,
}
temp = (ic & 0x3ff) | ((qc & 0x3ff) << 10);
rtw_write32(rtwdev, base_addr + 0x68, temp);
+ dm_info->dack_adck[path] = temp;
rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] ADCK 0x%08x=0x08%x\n",
base_addr + 0x68, temp);
/* check ADC DC offset */
@@ -422,10 +441,14 @@ static void rtw8822c_dac_cal_adc(struct rtw_dev *rtwdev,
static void rtw8822c_dac_cal_step1(struct rtw_dev *rtwdev, u8 path)
{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 base_addr;
+ u32 read_addr;
- base_addr = rtw8822c_get_path_base_addr(path);
+ base_addr = rtw8822c_get_path_write_addr(path);
+ read_addr = rtw8822c_get_path_read_addr(path);
+ rtw_write32(rtwdev, base_addr + 0x68, dm_info->dack_adck[path]);
rtw_write32(rtwdev, base_addr + 0x0c, 0xdff00220);
if (path == RF_PATH_A) {
rtw_write32(rtwdev, base_addr + 0x60, 0xf0040ff0);
@@ -447,11 +470,13 @@ static void rtw8822c_dac_cal_step1(struct rtw_dev *rtwdev, u8 path)
rtw_write32(rtwdev, base_addr + 0xcc, 0x0a11fb89);
mdelay(1);
rtw_write32(rtwdev, base_addr + 0xb8, 0x62000000);
- mdelay(20);
rtw_write32(rtwdev, base_addr + 0xd4, 0x62000000);
mdelay(20);
+ if (!check_hw_ready(rtwdev, read_addr + 0x08, 0x7fff80, 0xffff) ||
+ !check_hw_ready(rtwdev, read_addr + 0x34, 0x7fff80, 0xffff))
+ rtw_err(rtwdev, "failed to wait for dack ready\n");
rtw_write32(rtwdev, base_addr + 0xb8, 0x02000000);
- mdelay(20);
+ mdelay(1);
rtw_write32(rtwdev, base_addr + 0xbc, 0x0008ff87);
rtw_write32(rtwdev, 0x9b4, 0xdb6db600);
rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c5);
@@ -465,7 +490,7 @@ static void rtw8822c_dac_cal_step2(struct rtw_dev *rtwdev,
u32 base_addr;
u32 ic, qc, ic_in, qc_in;
- base_addr = rtw8822c_get_path_base_addr(path);
+ base_addr = rtw8822c_get_path_write_addr(path);
rtw_write32_mask(rtwdev, base_addr + 0xbc, 0xf0000000, 0x0);
rtw_write32_mask(rtwdev, base_addr + 0xc0, 0xf, 0x8);
rtw_write32_mask(rtwdev, base_addr + 0xd8, 0xf0000000, 0x0);
@@ -514,10 +539,12 @@ static void rtw8822c_dac_cal_step3(struct rtw_dev *rtwdev, u8 path,
u32 *i_out, u32 *q_out)
{
u32 base_addr;
+ u32 read_addr;
u32 ic, qc;
u32 temp;
- base_addr = rtw8822c_get_path_base_addr(path);
+ base_addr = rtw8822c_get_path_write_addr(path);
+ read_addr = rtw8822c_get_path_read_addr(path);
ic = *ic_in;
qc = *qc_in;
@@ -542,11 +569,13 @@ static void rtw8822c_dac_cal_step3(struct rtw_dev *rtwdev, u8 path,
rtw_write32(rtwdev, base_addr + 0xcc, 0x0a11fb89);
mdelay(1);
rtw_write32(rtwdev, base_addr + 0xb8, 0x62000000);
- mdelay(20);
rtw_write32(rtwdev, base_addr + 0xd4, 0x62000000);
mdelay(20);
+ if (!check_hw_ready(rtwdev, read_addr + 0x24, 0x07f80000, ic) ||
+ !check_hw_ready(rtwdev, read_addr + 0x50, 0x07f80000, qc))
+ rtw_err(rtwdev, "failed to write IQ vector to hardware\n");
rtw_write32(rtwdev, base_addr + 0xb8, 0x02000000);
- mdelay(20);
+ mdelay(1);
rtw_write32_mask(rtwdev, base_addr + 0xbc, 0xe, 0x3);
rtw_write32(rtwdev, 0x9b4, 0xdb6db600);
@@ -583,7 +612,7 @@ static void rtw8822c_dac_cal_step3(struct rtw_dev *rtwdev, u8 path,
static void rtw8822c_dac_cal_step4(struct rtw_dev *rtwdev, u8 path)
{
- u32 base_addr = rtw8822c_get_path_base_addr(path);
+ u32 base_addr = rtw8822c_get_path_write_addr(path);
rtw_write32(rtwdev, base_addr + 0x68, 0x0);
rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c4);
@@ -591,6 +620,296 @@ static void rtw8822c_dac_cal_step4(struct rtw_dev *rtwdev, u8 path)
rtw_write32_mask(rtwdev, base_addr + 0x30, BIT(30), 0x1);
}
+static void rtw8822c_dac_cal_backup_vec(struct rtw_dev *rtwdev,
+ u8 path, u8 vec, u32 w_addr, u32 r_addr)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u16 val;
+ u32 i;
+
+ if (WARN_ON(vec >= 2))
+ return;
+
+ for (i = 0; i < DACK_MSBK_BACKUP_NUM; i++) {
+ rtw_write32_mask(rtwdev, w_addr, 0xf0000000, i);
+ val = (u16)rtw_read32_mask(rtwdev, r_addr, 0x7fc0000);
+ dm_info->dack_msbk[path][vec][i] = val;
+ }
+}
+
+static void rtw8822c_dac_cal_backup_path(struct rtw_dev *rtwdev, u8 path)
+{
+ u32 w_off = 0x1c;
+ u32 r_off = 0x2c;
+ u32 w_addr, r_addr;
+
+ if (WARN_ON(path >= 2))
+ return;
+
+ /* backup I vector */
+ w_addr = rtw8822c_get_path_write_addr(path) + 0xb0;
+ r_addr = rtw8822c_get_path_read_addr(path) + 0x10;
+ rtw8822c_dac_cal_backup_vec(rtwdev, path, 0, w_addr, r_addr);
+
+ /* backup Q vector */
+ w_addr = rtw8822c_get_path_write_addr(path) + 0xb0 + w_off;
+ r_addr = rtw8822c_get_path_read_addr(path) + 0x10 + r_off;
+ rtw8822c_dac_cal_backup_vec(rtwdev, path, 1, w_addr, r_addr);
+}
+
+static void rtw8822c_dac_cal_backup_dck(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u8 val;
+
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKA_I_0, 0xf0000000);
+ dm_info->dack_dck[RF_PATH_A][0][0] = val;
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKA_I_1, 0xf);
+ dm_info->dack_dck[RF_PATH_A][0][1] = val;
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKA_Q_0, 0xf0000000);
+ dm_info->dack_dck[RF_PATH_A][1][0] = val;
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKA_Q_1, 0xf);
+ dm_info->dack_dck[RF_PATH_A][1][1] = val;
+
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKB_I_0, 0xf0000000);
+ dm_info->dack_dck[RF_PATH_B][0][0] = val;
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKB_I_1, 0xf);
+ dm_info->dack_dck[RF_PATH_B][1][0] = val;
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKB_Q_0, 0xf0000000);
+ dm_info->dack_dck[RF_PATH_B][0][1] = val;
+ val = (u8)rtw_read32_mask(rtwdev, REG_DCKB_Q_1, 0xf);
+ dm_info->dack_dck[RF_PATH_B][1][1] = val;
+}
+
+static void rtw8822c_dac_cal_backup(struct rtw_dev *rtwdev)
+{
+ u32 temp[3];
+
+ temp[0] = rtw_read32(rtwdev, 0x1860);
+ temp[1] = rtw_read32(rtwdev, 0x4160);
+ temp[2] = rtw_read32(rtwdev, 0x9b4);
+
+ /* set clock */
+ rtw_write32(rtwdev, 0x9b4, 0xdb66db00);
+
+ /* backup path-A I/Q */
+ rtw_write32_clr(rtwdev, 0x1830, BIT(30));
+ rtw_write32_mask(rtwdev, 0x1860, 0xfc000000, 0x3c);
+ rtw8822c_dac_cal_backup_path(rtwdev, RF_PATH_A);
+
+ /* backup path-B I/Q */
+ rtw_write32_clr(rtwdev, 0x4130, BIT(30));
+ rtw_write32_mask(rtwdev, 0x4160, 0xfc000000, 0x3c);
+ rtw8822c_dac_cal_backup_path(rtwdev, RF_PATH_B);
+
+ rtw8822c_dac_cal_backup_dck(rtwdev);
+ rtw_write32_set(rtwdev, 0x1830, BIT(30));
+ rtw_write32_set(rtwdev, 0x4130, BIT(30));
+
+ rtw_write32(rtwdev, 0x1860, temp[0]);
+ rtw_write32(rtwdev, 0x4160, temp[1]);
+ rtw_write32(rtwdev, 0x9b4, temp[2]);
+}
+
+static void rtw8822c_dac_cal_restore_dck(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u8 val;
+
+ rtw_write32_set(rtwdev, REG_DCKA_I_0, BIT(19));
+ val = dm_info->dack_dck[RF_PATH_A][0][0];
+ rtw_write32_mask(rtwdev, REG_DCKA_I_0, 0xf0000000, val);
+ val = dm_info->dack_dck[RF_PATH_A][0][1];
+ rtw_write32_mask(rtwdev, REG_DCKA_I_1, 0xf, val);
+
+ rtw_write32_set(rtwdev, REG_DCKA_Q_0, BIT(19));
+ val = dm_info->dack_dck[RF_PATH_A][1][0];
+ rtw_write32_mask(rtwdev, REG_DCKA_Q_0, 0xf0000000, val);
+ val = dm_info->dack_dck[RF_PATH_A][1][1];
+ rtw_write32_mask(rtwdev, REG_DCKA_Q_1, 0xf, val);
+
+ rtw_write32_set(rtwdev, REG_DCKB_I_0, BIT(19));
+ val = dm_info->dack_dck[RF_PATH_B][0][0];
+ rtw_write32_mask(rtwdev, REG_DCKB_I_0, 0xf0000000, val);
+ val = dm_info->dack_dck[RF_PATH_B][0][1];
+ rtw_write32_mask(rtwdev, REG_DCKB_I_1, 0xf, val);
+
+ rtw_write32_set(rtwdev, REG_DCKB_Q_0, BIT(19));
+ val = dm_info->dack_dck[RF_PATH_B][1][0];
+ rtw_write32_mask(rtwdev, REG_DCKB_Q_0, 0xf0000000, val);
+ val = dm_info->dack_dck[RF_PATH_B][1][1];
+ rtw_write32_mask(rtwdev, REG_DCKB_Q_1, 0xf, val);
+}
+
+static void rtw8822c_dac_cal_restore_prepare(struct rtw_dev *rtwdev)
+{
+ rtw_write32(rtwdev, 0x9b4, 0xdb66db00);
+
+ rtw_write32_mask(rtwdev, 0x18b0, BIT(27), 0x0);
+ rtw_write32_mask(rtwdev, 0x18cc, BIT(27), 0x0);
+ rtw_write32_mask(rtwdev, 0x41b0, BIT(27), 0x0);
+ rtw_write32_mask(rtwdev, 0x41cc, BIT(27), 0x0);
+
+ rtw_write32_mask(rtwdev, 0x1830, BIT(30), 0x0);
+ rtw_write32_mask(rtwdev, 0x1860, 0xfc000000, 0x3c);
+ rtw_write32_mask(rtwdev, 0x18b4, BIT(0), 0x1);
+ rtw_write32_mask(rtwdev, 0x18d0, BIT(0), 0x1);
+
+ rtw_write32_mask(rtwdev, 0x4130, BIT(30), 0x0);
+ rtw_write32_mask(rtwdev, 0x4160, 0xfc000000, 0x3c);
+ rtw_write32_mask(rtwdev, 0x41b4, BIT(0), 0x1);
+ rtw_write32_mask(rtwdev, 0x41d0, BIT(0), 0x1);
+
+ rtw_write32_mask(rtwdev, 0x18b0, 0xf00, 0x0);
+ rtw_write32_mask(rtwdev, 0x18c0, BIT(14), 0x0);
+ rtw_write32_mask(rtwdev, 0x18cc, 0xf00, 0x0);
+ rtw_write32_mask(rtwdev, 0x18dc, BIT(14), 0x0);
+
+ rtw_write32_mask(rtwdev, 0x18b0, BIT(0), 0x0);
+ rtw_write32_mask(rtwdev, 0x18cc, BIT(0), 0x0);
+ rtw_write32_mask(rtwdev, 0x18b0, BIT(0), 0x1);
+ rtw_write32_mask(rtwdev, 0x18cc, BIT(0), 0x1);
+
+ rtw8822c_dac_cal_restore_dck(rtwdev);
+
+ rtw_write32_mask(rtwdev, 0x18c0, 0x38000, 0x7);
+ rtw_write32_mask(rtwdev, 0x18dc, 0x38000, 0x7);
+ rtw_write32_mask(rtwdev, 0x41c0, 0x38000, 0x7);
+ rtw_write32_mask(rtwdev, 0x41dc, 0x38000, 0x7);
+
+ rtw_write32_mask(rtwdev, 0x18b8, BIT(26) | BIT(25), 0x1);
+ rtw_write32_mask(rtwdev, 0x18d4, BIT(26) | BIT(25), 0x1);
+
+ rtw_write32_mask(rtwdev, 0x41b0, 0xf00, 0x0);
+ rtw_write32_mask(rtwdev, 0x41c0, BIT(14), 0x0);
+ rtw_write32_mask(rtwdev, 0x41cc, 0xf00, 0x0);
+ rtw_write32_mask(rtwdev, 0x41dc, BIT(14), 0x0);
+
+ rtw_write32_mask(rtwdev, 0x41b0, BIT(0), 0x0);
+ rtw_write32_mask(rtwdev, 0x41cc, BIT(0), 0x0);
+ rtw_write32_mask(rtwdev, 0x41b0, BIT(0), 0x1);
+ rtw_write32_mask(rtwdev, 0x41cc, BIT(0), 0x1);
+
+ rtw_write32_mask(rtwdev, 0x41b8, BIT(26) | BIT(25), 0x1);
+ rtw_write32_mask(rtwdev, 0x41d4, BIT(26) | BIT(25), 0x1);
+}
+
+static bool rtw8822c_dac_cal_restore_wait(struct rtw_dev *rtwdev,
+ u32 target_addr, u32 toggle_addr)
+{
+ u32 cnt = 0;
+
+ do {
+ rtw_write32_mask(rtwdev, toggle_addr, BIT(26) | BIT(25), 0x0);
+ rtw_write32_mask(rtwdev, toggle_addr, BIT(26) | BIT(25), 0x2);
+
+ if (rtw_read32_mask(rtwdev, target_addr, 0xf) == 0x6)
+ return true;
+
+ } while (cnt++ < 100);
+
+ return false;
+}
+
+static bool rtw8822c_dac_cal_restore_path(struct rtw_dev *rtwdev, u8 path)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u32 w_off = 0x1c;
+ u32 r_off = 0x2c;
+ u32 w_i, r_i, w_q, r_q;
+ u32 value;
+ u32 i;
+
+ w_i = rtw8822c_get_path_write_addr(path) + 0xb0;
+ r_i = rtw8822c_get_path_read_addr(path) + 0x08;
+ w_q = rtw8822c_get_path_write_addr(path) + 0xb0 + w_off;
+ r_q = rtw8822c_get_path_read_addr(path) + 0x08 + r_off;
+
+ if (!rtw8822c_dac_cal_restore_wait(rtwdev, r_i, w_i + 0x8))
+ return false;
+
+ for (i = 0; i < DACK_MSBK_BACKUP_NUM; i++) {
+ rtw_write32_mask(rtwdev, w_i + 0x4, BIT(2), 0x0);
+ value = dm_info->dack_msbk[path][0][i];
+ rtw_write32_mask(rtwdev, w_i + 0x4, 0xff8, value);
+ rtw_write32_mask(rtwdev, w_i, 0xf0000000, i);
+ rtw_write32_mask(rtwdev, w_i + 0x4, BIT(2), 0x1);
+ }
+
+ rtw_write32_mask(rtwdev, w_i + 0x4, BIT(2), 0x0);
+
+ if (!rtw8822c_dac_cal_restore_wait(rtwdev, r_q, w_q + 0x8))
+ return false;
+
+ for (i = 0; i < DACK_MSBK_BACKUP_NUM; i++) {
+ rtw_write32_mask(rtwdev, w_q + 0x4, BIT(2), 0x0);
+ value = dm_info->dack_msbk[path][1][i];
+ rtw_write32_mask(rtwdev, w_q + 0x4, 0xff8, value);
+ rtw_write32_mask(rtwdev, w_q, 0xf0000000, i);
+ rtw_write32_mask(rtwdev, w_q + 0x4, BIT(2), 0x1);
+ }
+ rtw_write32_mask(rtwdev, w_q + 0x4, BIT(2), 0x0);
+
+ rtw_write32_mask(rtwdev, w_i + 0x8, BIT(26) | BIT(25), 0x0);
+ rtw_write32_mask(rtwdev, w_q + 0x8, BIT(26) | BIT(25), 0x0);
+ rtw_write32_mask(rtwdev, w_i + 0x4, BIT(0), 0x0);
+ rtw_write32_mask(rtwdev, w_q + 0x4, BIT(0), 0x0);
+
+ return true;
+}
+
+static bool __rtw8822c_dac_cal_restore(struct rtw_dev *rtwdev)
+{
+ if (!rtw8822c_dac_cal_restore_path(rtwdev, RF_PATH_A))
+ return false;
+
+ if (!rtw8822c_dac_cal_restore_path(rtwdev, RF_PATH_B))
+ return false;
+
+ return true;
+}
+
+static bool rtw8822c_dac_cal_restore(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u32 temp[3];
+
+ /* sample the first element for both path's IQ vector */
+ if (dm_info->dack_msbk[RF_PATH_A][0][0] == 0 &&
+ dm_info->dack_msbk[RF_PATH_A][1][0] == 0 &&
+ dm_info->dack_msbk[RF_PATH_B][0][0] == 0 &&
+ dm_info->dack_msbk[RF_PATH_B][1][0] == 0)
+ return false;
+
+ temp[0] = rtw_read32(rtwdev, 0x1860);
+ temp[1] = rtw_read32(rtwdev, 0x4160);
+ temp[2] = rtw_read32(rtwdev, 0x9b4);
+
+ rtw8822c_dac_cal_restore_prepare(rtwdev);
+ if (!check_hw_ready(rtwdev, 0x2808, 0x7fff80, 0xffff) ||
+ !check_hw_ready(rtwdev, 0x2834, 0x7fff80, 0xffff) ||
+ !check_hw_ready(rtwdev, 0x4508, 0x7fff80, 0xffff) ||
+ !check_hw_ready(rtwdev, 0x4534, 0x7fff80, 0xffff))
+ return false;
+
+ if (!__rtw8822c_dac_cal_restore(rtwdev)) {
+ rtw_err(rtwdev, "failed to restore dack vectors\n");
+ return false;
+ }
+
+ rtw_write32_mask(rtwdev, 0x1830, BIT(30), 0x1);
+ rtw_write32_mask(rtwdev, 0x4130, BIT(30), 0x1);
+ rtw_write32(rtwdev, 0x1860, temp[0]);
+ rtw_write32(rtwdev, 0x4160, temp[1]);
+ rtw_write32_mask(rtwdev, 0x18b0, BIT(27), 0x1);
+ rtw_write32_mask(rtwdev, 0x18cc, BIT(27), 0x1);
+ rtw_write32_mask(rtwdev, 0x41b0, BIT(27), 0x1);
+ rtw_write32_mask(rtwdev, 0x41cc, BIT(27), 0x1);
+ rtw_write32(rtwdev, 0x9b4, temp[2]);
+
+ return true;
+}
+
static void rtw8822c_rf_dac_cal(struct rtw_dev *rtwdev)
{
struct rtw_backup_info backup_rf[DACK_RF_8822C * DACK_PATH_8822C];
@@ -600,6 +919,11 @@ static void rtw8822c_rf_dac_cal(struct rtw_dev *rtwdev)
u32 ic_a = 0x0, qc_a = 0x0, ic_b = 0x0, qc_b = 0x0;
u32 adc_ic_a = 0x0, adc_qc_a = 0x0, adc_ic_b = 0x0, adc_qc_b = 0x0;
+ if (rtw8822c_dac_cal_restore(rtwdev))
+ return;
+
+ /* not able to restore, do it */
+
rtw8822c_dac_backup_reg(rtwdev, backup, backup_rf);
rtw8822c_dac_bb_setting(rtwdev);
@@ -644,6 +968,9 @@ static void rtw8822c_rf_dac_cal(struct rtw_dev *rtwdev)
rtw8822c_dac_restore_reg(rtwdev, backup, backup_rf);
+ /* backup results to restore, saving a lot of time */
+ rtw8822c_dac_cal_backup(rtwdev);
+
rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path A: ic=0x%x, qc=0x%x\n", ic_a, qc_a);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path B: ic=0x%x, qc=0x%x\n", ic_b, qc_b);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path A: i=0x%x, q=0x%x\n", i_a, q_a);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
index 62ef128..ac730e7 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
@@ -150,6 +150,10 @@ struct rtw8822c_efuse {
#define BIT_3WIRE_RX_EN BIT(1)
#define BIT_3WIRE_PI_ON BIT(28)
#define REG_RXAGCCTL0 0x18ac
+#define REG_DCKA_I_0 0x18bc
+#define REG_DCKA_I_1 0x18c0
+#define REG_DCKA_Q_0 0x18d8
+#define REG_DCKA_Q_1 0x18dc
#define BIT_RXAGC_CCK 0xf000
#define BIT_RXAGC_OFDM 0x1f0
#define REG_CCKSB 0x1a00
@@ -196,5 +200,9 @@ struct rtw8822c_efuse {
#define REG_ORITXCODE2 0x4100
#define REG_3WIRE2 0x410c
#define REG_RXAGCCTL 0x41ac
+#define REG_DCKB_I_0 0x41bc
+#define REG_DCKB_I_1 0x41c0
+#define REG_DCKB_Q_0 0x41d8
+#define REG_DCKB_Q_1 0x41dc
#endif
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox