* Re: [PATCH 2/4] mt76: mmio: move mt76_insert_hdr_pad in mt76_dma_tx_queue_skb
From: Lorenzo Bianconi @ 2019-03-11 15:01 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Lorenzo Bianconi, nbd, ryder.lee, roychl666, linux-wireless
In-Reply-To: <20190311145852.GF6089@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 2052 bytes --]
> On Mon, Mar 11, 2019 at 03:25:18PM +0100, Lorenzo Bianconi wrote:
> > On Mar 11, Stanislaw Gruszka wrote:
> > > On Mon, Mar 11, 2019 at 01:35:24PM +0100, Lorenzo Bianconi wrote:
> > > > Introduce tx_aligned4_skbs in mt76_driver_ops and move
> > > > mt76_insert_hdr_pad in mt76_dma_tx_queue_skb. This is a preliminary
> > > > patch in order to unify tx dma mapping for mt76x02 and new chipsets
> > > >
> > > > Signed-off-by: Felix Fietkau <nbd@nbd.name>
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > ---
> > > > drivers/net/wireless/mediatek/mt76/dma.c | 3 +++
> > > > drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> > > > drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 +
> > > > drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 13 +++++--------
> > > > drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 1 +
> > > > 5 files changed, 11 insertions(+), 8 deletions(-)
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> > > > index a66832a02281..14dd6585bab4 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/dma.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> > > > @@ -300,6 +300,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
> > > > }
> > > >
> > > > skb->prev = skb->next = NULL;
> > > > + if (dev->drv->tx_aligned4_skbs)
> > > > + mt76_insert_hdr_pad(skb);
> > >
> > > We need 4 bytes aligned skbs for mt76x02 or we just need header
> > > lenght be multiple of 4 ?
> >
> > I think IV/LLC should be 4 byte aligned
>
> mt76_insert_hdr_pad() does not change alignment of IV/LLC , it only
> moves header.
>
> I'm not sure what is actually needed (4 bytes alignment or 4 bytes
> lenght), but I just saw Felix sent 2 mac80211 patches that hopfully
> do the right thing, so this code after appling mac80211 changes
> and set TX_NEEDS_ALIGNED4_SKBS can be removed.
this is the plan :)
Regards,
Lorenzo
>
> Stanislaw
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 2/4] mt76: mmio: move mt76_insert_hdr_pad in mt76_dma_tx_queue_skb
From: Stanislaw Gruszka @ 2019-03-11 14:58 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Lorenzo Bianconi, nbd, ryder.lee, roychl666, linux-wireless
In-Reply-To: <20190311142517.GB30882@localhost.localdomain>
On Mon, Mar 11, 2019 at 03:25:18PM +0100, Lorenzo Bianconi wrote:
> On Mar 11, Stanislaw Gruszka wrote:
> > On Mon, Mar 11, 2019 at 01:35:24PM +0100, Lorenzo Bianconi wrote:
> > > Introduce tx_aligned4_skbs in mt76_driver_ops and move
> > > mt76_insert_hdr_pad in mt76_dma_tx_queue_skb. This is a preliminary
> > > patch in order to unify tx dma mapping for mt76x02 and new chipsets
> > >
> > > Signed-off-by: Felix Fietkau <nbd@nbd.name>
> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > ---
> > > drivers/net/wireless/mediatek/mt76/dma.c | 3 +++
> > > drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> > > drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 +
> > > drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 13 +++++--------
> > > drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 1 +
> > > 5 files changed, 11 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> > > index a66832a02281..14dd6585bab4 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/dma.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> > > @@ -300,6 +300,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
> > > }
> > >
> > > skb->prev = skb->next = NULL;
> > > + if (dev->drv->tx_aligned4_skbs)
> > > + mt76_insert_hdr_pad(skb);
> >
> > We need 4 bytes aligned skbs for mt76x02 or we just need header
> > lenght be multiple of 4 ?
>
> I think IV/LLC should be 4 byte aligned
mt76_insert_hdr_pad() does not change alignment of IV/LLC , it only
moves header.
I'm not sure what is actually needed (4 bytes alignment or 4 bytes
lenght), but I just saw Felix sent 2 mac80211 patches that hopfully
do the right thing, so this code after appling mac80211 changes
and set TX_NEEDS_ALIGNED4_SKBS can be removed.
Stanislaw
^ permalink raw reply
* Re: [PATCH 2/4] mt76: mmio: move mt76_insert_hdr_pad in mt76_dma_tx_queue_skb
From: Lorenzo Bianconi @ 2019-03-11 14:25 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Lorenzo Bianconi, nbd, ryder.lee, roychl666, linux-wireless
In-Reply-To: <20190311133954.GD6089@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1482 bytes --]
On Mar 11, Stanislaw Gruszka wrote:
> On Mon, Mar 11, 2019 at 01:35:24PM +0100, Lorenzo Bianconi wrote:
> > Introduce tx_aligned4_skbs in mt76_driver_ops and move
> > mt76_insert_hdr_pad in mt76_dma_tx_queue_skb. This is a preliminary
> > patch in order to unify tx dma mapping for mt76x02 and new chipsets
> >
> > Signed-off-by: Felix Fietkau <nbd@nbd.name>
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > drivers/net/wireless/mediatek/mt76/dma.c | 3 +++
> > drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> > drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 +
> > drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 13 +++++--------
> > drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 1 +
> > 5 files changed, 11 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> > index a66832a02281..14dd6585bab4 100644
> > --- a/drivers/net/wireless/mediatek/mt76/dma.c
> > +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> > @@ -300,6 +300,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
> > }
> >
> > skb->prev = skb->next = NULL;
> > + if (dev->drv->tx_aligned4_skbs)
> > + mt76_insert_hdr_pad(skb);
>
> We need 4 bytes aligned skbs for mt76x02 or we just need header
> lenght be multiple of 4 ?
I think IV/LLC should be 4 byte aligned
Regards,
Lorenzo
>
> Stanislaw
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH RFC v2] mac80211: debugfs option to force TX status frames
From: Kalle Valo @ 2019-03-11 14:03 UTC (permalink / raw)
To: ga58taw
Cc: Julius Niedworok, linux-wireless, david, nc, Johannes Berg,
David S. Miller, netdev, linux-kernel
In-Reply-To: <20190307193045.a7awwn6mycloccq5@mission-control>
ga58taw@mytum.de writes:
> On Thu, Mar 07, 2019 at 05:42:04PM +0200, Kalle Valo wrote:
>> > + len = scnprintf(buf, sizeof(buf), "%d\n", (int)local->force_tx_status);
>>
>> I wonder about the cast, is it guaranteed that a bool is always of the
>> same size as an int?
>
> Why is this a problem? If a bool is smaller than an int, the compiler
> emits code that will prepend the value of force_tx_status with zeros.
Let's say that a bool is a byte and int is four bytes. If you use "%d" I
would guess that in that case scnprintf() writes 4 bytes, meaning that 3
bytes will be overwriting either padding or some other field in the
struct.
But I'm no compiler expert so I'm not going to argue about this anymore.
I just wanted to point out that that the cast looks dangerous and I
would not do it.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 1/4] mt76: move mt76x02_insert_hdr_pad in mt76-core module
From: Lorenzo Bianconi @ 2019-03-11 14:02 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Lorenzo Bianconi, nbd, ryder.lee, roychl666, linux-wireless
In-Reply-To: <20190311133058.GC6089@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 904 bytes --]
> On Mon, Mar 11, 2019 at 01:35:23PM +0100, Lorenzo Bianconi wrote:
> > +static inline int mt76_insert_hdr_pad(struct sk_buff *skb)
> > +{
> > + int len = ieee80211_get_hdrlen_from_skb(skb);
> > +
> > + if (len % 4 == 0)
> > + return 0;
> > +
> > + skb_push(skb, 2);
> > + memmove(skb->data, skb->data + 2, len);
> > +
> > + skb->data[len] = 0;
> > + skb->data[len + 1] = 0;
> > + return 2;
> > +}
> <snip>
> > @@ -165,7 +165,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
> > pid = mt76_tx_status_skb_add(mdev, wcid, skb);
> > txwi->pktid = pid;
> >
> > - ret = mt76x02_insert_hdr_pad(skb);
> > + ret = mt76_insert_hdr_pad(skb);
> > if (ret < 0)
> > return ret;
>
> Since you modify this you can make mt76_inser_hdr_pad() return
> void since we do not return error any longer.
ack, will do in v2
Regards,
Lorenzo
>
> Stanislaw
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v7 00/14] rtw88: mac80211 driver for Realtek 802.11ac wireless network chips
From: Stanislaw Gruszka @ 2019-03-11 13:58 UTC (permalink / raw)
To: yhchuang
Cc: kvalo, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <1552139302-20476-1-git-send-email-yhchuang@realtek.com>
On Sat, Mar 09, 2019 at 09:48:08PM +0800, yhchuang@realtek.com wrote:
> From: Yan-Hsuan Chuang <yhchuang@realtek.com>
>
> This is a new mac80211 driver for Realtek 802.11ac wireless network chips.
> rtw88 now supports RTL8822BE/RTL8822CE now, with basic station mode
> functionalities. The firmware for both can be found at linux-firmware.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
> For RTL8822BE: rtw88/rtw8822b_fw.bin
> For RTL8822CE: rtw88/rtw8822c_fw.bin
I have only some nitpicks for the last version and this queue stop/wake
rece is rather theoretical than practical. All of those can be fixed
by incremental patches, no need to resend new version IMO.
Overall the rtw88 driver looks great to me.
Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com>
Please keep this tag if you would eventually repost (also
Acked-by Greg for remove staging rtlwifi).
Stanislaw
^ permalink raw reply
* Re: [PATCH v7 00/14] rtw88: mac80211 driver for Realtek 802.11ac wireless network chips
From: Kalle Valo @ 2019-03-11 13:48 UTC (permalink / raw)
To: yhchuang
Cc: johannes, gregkh, linux-wireless, Larry.Finger, sgruszka, pkshih,
tehuang, briannorris
In-Reply-To: <1552139302-20476-1-git-send-email-yhchuang@realtek.com>
<yhchuang@realtek.com> writes:
> From: Yan-Hsuan Chuang <yhchuang@realtek.com>
>
> This is a new mac80211 driver for Realtek 802.11ac wireless network chips.
> rtw88 now supports RTL8822BE/RTL8822CE now, with basic station mode
> functionalities. The firmware for both can be found at linux-firmware.
>
[...]
> Yan-Hsuan Chuang (14):
> rtw88: main files
> rtw88: core files
> rtw88: hci files
> rtw88: trx files
> rtw88: mac files
> rtw88: fw and efuse files
> rtw88: phy files
> rtw88: debug files
> rtw88: chip files
> rtw88: 8822B init table
> rtw88: 8822C init table
> rtw88: Kconfig & Makefile
> rtw88: add MAINTAINERS entry
> staging: rtlwifi: remove staging rtlwifi driver
Do note that the staging driver was too big and didn't make it to the
list (and patchwork). But no need to resend or modify that patch, just
an observation.
Or would --find-renames help to make the patch smaller?
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 2/4] mt76: mmio: move mt76_insert_hdr_pad in mt76_dma_tx_queue_skb
From: Stanislaw Gruszka @ 2019-03-11 13:39 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: nbd, ryder.lee, roychl666, linux-wireless, lorenzo.bianconi
In-Reply-To: <e03a38968b3bca0a51a832bdb0dd9ff1beff314d.1552306908.git.lorenzo@kernel.org>
On Mon, Mar 11, 2019 at 01:35:24PM +0100, Lorenzo Bianconi wrote:
> Introduce tx_aligned4_skbs in mt76_driver_ops and move
> mt76_insert_hdr_pad in mt76_dma_tx_queue_skb. This is a preliminary
> patch in order to unify tx dma mapping for mt76x02 and new chipsets
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/dma.c | 3 +++
> drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 +
> drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 13 +++++--------
> drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 1 +
> 5 files changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> index a66832a02281..14dd6585bab4 100644
> --- a/drivers/net/wireless/mediatek/mt76/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> @@ -300,6 +300,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
> }
>
> skb->prev = skb->next = NULL;
> + if (dev->drv->tx_aligned4_skbs)
> + mt76_insert_hdr_pad(skb);
We need 4 bytes aligned skbs for mt76x02 or we just need header
lenght be multiple of 4 ?
Stanislaw
^ permalink raw reply
* Re: [PATCH v7 01/14] rtw88: main files
From: Kalle Valo @ 2019-03-11 13:32 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: yhchuang, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <20190311131939.GB6089@redhat.com>
Stanislaw Gruszka <sgruszka@redhat.com> writes:
> On Mon, Mar 11, 2019 at 03:14:38PM +0200, Kalle Valo wrote:
>> Stanislaw Gruszka <sgruszka@redhat.com> writes:
>>
>> >> +#define RA_MASK_VHT_RATES_1SS (0x3ff000 << 0)
>> >> +#define RA_MASK_VHT_RATES_2SS (0x3ff000 << 10)
>> >> +#define RA_MASK_VHT_RATES_3SS (0x3ff000 << 20)
>> >
>> > Result will not fit in 32 bit, ULL marker should be added.
>>
>> I haven't checked how these are used but IMHO using GENMASK() would be
>> so much better.
>
> GENMASK_ULL() in this case :-)
Good point :)
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 1/4] mt76: move mt76x02_insert_hdr_pad in mt76-core module
From: Stanislaw Gruszka @ 2019-03-11 13:30 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: nbd, ryder.lee, roychl666, linux-wireless, lorenzo.bianconi
In-Reply-To: <0ec618f40f6308f4da8c6a766519dfd66fa5ad57.1552306908.git.lorenzo@kernel.org>
On Mon, Mar 11, 2019 at 01:35:23PM +0100, Lorenzo Bianconi wrote:
> +static inline int mt76_insert_hdr_pad(struct sk_buff *skb)
> +{
> + int len = ieee80211_get_hdrlen_from_skb(skb);
> +
> + if (len % 4 == 0)
> + return 0;
> +
> + skb_push(skb, 2);
> + memmove(skb->data, skb->data + 2, len);
> +
> + skb->data[len] = 0;
> + skb->data[len + 1] = 0;
> + return 2;
> +}
<snip>
> @@ -165,7 +165,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
> pid = mt76_tx_status_skb_add(mdev, wcid, skb);
> txwi->pktid = pid;
>
> - ret = mt76x02_insert_hdr_pad(skb);
> + ret = mt76_insert_hdr_pad(skb);
> if (ret < 0)
> return ret;
Since you modify this you can make mt76_inser_hdr_pad() return
void since we do not return error any longer.
Stanislaw
^ permalink raw reply
* [PATCH v2] mt76: fix schedule while atomic in mt76x02_reset_state
From: Lorenzo Bianconi @ 2019-03-11 13:24 UTC (permalink / raw)
To: nbd; +Cc: linux-wireless
In-Reply-To: <cover.1552309862.git.lorenzo@kernel.org>
Fix following schedule while atomic in mt76x02_reset_state
since synchronize_rcu is run inside a RCU section
[44036.944222] mt76x2e 0000:06:00.0: MCU message 31 (seq 3) timed out
[44036.944281] BUG: sleeping function called from invalid context at kernel/rcu/tree_exp.h:818
[44036.944284] in_atomic(): 1, irqs_disabled(): 0, pid: 28066, name: kworker/u4:1
[44036.944287] INFO: lockdep is turned off.
[44036.944292] CPU: 1 PID: 28066 Comm: kworker/u4:1 Tainted: G W 5.0.0-rc7-wdn-t1+ #7
[44036.944294] Hardware name: Dell Inc. Studio XPS 1340/0K183D, BIOS A11 09/08/2009
[44036.944305] Workqueue: phy1 mt76x02_wdt_work [mt76x02_lib]
[44036.944308] Call Trace:
[44036.944317] dump_stack+0x67/0x90
[44036.944322] ___might_sleep.cold.88+0x9f/0xaf
[44036.944327] rcu_blocking_is_gp+0x13/0x50
[44036.944330] synchronize_rcu+0x17/0x80
[44036.944337] mt76_sta_state+0x138/0x1d0 [mt76]
[44036.944349] mt76x02_wdt_work+0x1c9/0x610 [mt76x02_lib]
[44036.944355] process_one_work+0x2a5/0x620
[44036.944361] worker_thread+0x35/0x3e0
[44036.944368] kthread+0x11c/0x140
[44036.944376] ret_from_fork+0x3a/0x50
[44036.944384] BUG: scheduling while atomic: kworker/u4:1/28066/0x00000002
[44036.944387] INFO: lockdep is turned off.
[44036.944389] Modules linked in: cmac ctr ccm af_packet snd_hda_codec_hdmi
Introduce __mt76_sta_remove in order to run sta_remove without holding dev->mutex.
Move __mt76_sta_remove outside of RCU section in mt76x02_reset_state
Fixes: e4ebb8b403d1 ("mt76: mt76x2: implement full device restart on watchdog reset")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes since v1:
- fix checkpatch warnings
- add lockdep_assert_held in mt76x02_reset_state
- access wcid pointer through rcu_dereference_protected()
---
drivers/net/wireless/mediatek/mt76/mac80211.c | 18 +++++++++++-------
drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++
.../net/wireless/mediatek/mt76/mt76x02_mmio.c | 19 ++++++++++---------
3 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index a033745adb2f..316167404729 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -679,19 +679,15 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
return ret;
}
-static void
-mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
- int idx = wcid->idx;
- int i;
+ int i, idx = wcid->idx;
rcu_assign_pointer(dev->wcid[idx], NULL);
synchronize_rcu();
- mutex_lock(&dev->mutex);
-
if (dev->drv->sta_remove)
dev->drv->sta_remove(dev, vif, sta);
@@ -699,7 +695,15 @@ mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
mt76_txq_remove(dev, sta->txq[i]);
mt76_wcid_free(dev->wcid_mask, idx);
+}
+EXPORT_SYMBOL_GPL(__mt76_sta_remove);
+static void
+mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ mutex_lock(&dev->mutex);
+ __mt76_sta_remove(dev, vif, sta);
mutex_unlock(&dev->mutex);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 477027bb9aaf..eb72e4bf3db6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -697,6 +697,8 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state);
+void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 6a34a6afcfe4..531779d8856e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -423,19 +423,23 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev)
{
int i;
+ lockdep_assert_held(&dev->mt76.mutex);
+
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
rcu_read_lock();
-
ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL);
+ rcu_read_unlock();
for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) {
- struct mt76_wcid *wcid = rcu_dereference(dev->mt76.wcid[i]);
- struct mt76x02_sta *msta;
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
+ struct mt76x02_sta *msta;
+ struct mt76_wcid *wcid;
void *priv;
+ wcid = rcu_dereference_protected(dev->mt76.wcid[i],
+ lockdep_is_held(&dev->mt76.mutex));
if (!wcid)
continue;
@@ -445,13 +449,10 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev)
priv = msta->vif;
vif = container_of(priv, struct ieee80211_vif, drv_priv);
- mt76_sta_state(dev->mt76.hw, vif, sta,
- IEEE80211_STA_NONE, IEEE80211_STA_NOTEXIST);
+ __mt76_sta_remove(&dev->mt76, vif, sta);
memset(msta, 0, sizeof(*msta));
}
- rcu_read_unlock();
-
dev->vif_mask = 0;
dev->beacon_mask = 0;
}
@@ -471,11 +472,11 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++)
napi_disable(&dev->mt76.napi[i]);
+ mutex_lock(&dev->mt76.mutex);
+
if (restart)
mt76x02_reset_state(dev);
- mutex_lock(&dev->mt76.mutex);
-
if (dev->beacon_mask)
mt76_clear(dev, MT_BEACON_TIME_CFG,
MT_BEACON_TIME_CFG_BEACON_TX |
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v7 01/14] rtw88: main files
From: Stanislaw Gruszka @ 2019-03-11 13:19 UTC (permalink / raw)
To: Kalle Valo
Cc: yhchuang, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <871s3da6yp.fsf@codeaurora.org>
On Mon, Mar 11, 2019 at 03:14:38PM +0200, Kalle Valo wrote:
> Stanislaw Gruszka <sgruszka@redhat.com> writes:
>
> >> +#define RA_MASK_VHT_RATES_1SS (0x3ff000 << 0)
> >> +#define RA_MASK_VHT_RATES_2SS (0x3ff000 << 10)
> >> +#define RA_MASK_VHT_RATES_3SS (0x3ff000 << 20)
> >
> > Result will not fit in 32 bit, ULL marker should be added.
>
> I haven't checked how these are used but IMHO using GENMASK() would be
> so much better.
GENMASK_ULL() in this case :-)
Stanislaw
^ permalink raw reply
* Re: [PATCH] mt76: mt7603: use the correct hweight8() function
From: Felix Fietkau @ 2019-03-11 13:17 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <87wol58s9i.fsf@codeaurora.org>
On 2019-03-11 14:17, Kalle Valo wrote:
> Felix Fietkau <nbd@nbd.name> writes:
>
>> __sw_hweight8() is only defined if CONFIG_GENERIC_HWEIGHT is enabled.
>> The function that works on all architectures is hweight8().
>>
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>
> This should go to 5.1, right?
Yes.
- Felix
^ permalink raw reply
* Re: [PATCH 0/4] move skb mapping before configuring txwi
From: Lorenzo Bianconi @ 2019-03-11 13:17 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: nbd, ryder.lee, roychl666, linux-wireless
In-Reply-To: <cover.1552306908.git.lorenzo@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 1506 bytes --]
> Move skb dma mapping before configuring txwi since new chipsets
> (e.g. mt7615) will need dma addresses to properly configure txwi.
> Introduce temporary tx_aligned4_skbs variable in order to tell mt76 layer
> if it is necessary to align the 802.11 header (it will be removed as soon
> as mac80211 will take care of it)
>
> Lorenzo Bianconi (4):
> mt76: move mt76x02_insert_hdr_pad in mt76-core module
> mt76: mmio: move mt76_insert_hdr_pad in mt76_dma_tx_queue_skb
> mt76: move skb dma mapping before running tx_prepare_skb
> mt76: introduce mt76_tx_info data structure
>
> drivers/net/wireless/mediatek/mt76/dma.c | 55 +++++++++----------
> drivers/net/wireless/mediatek/mt76/mt76.h | 25 ++++++++-
> .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +-
> .../wireless/mediatek/mt76/mt7603/mt7603.h | 2 +-
> .../net/wireless/mediatek/mt76/mt76x0/pci.c | 1 +
> drivers/net/wireless/mediatek/mt76/mt76x02.h | 3 +-
> .../net/wireless/mediatek/mt76/mt76x02_txrx.c | 21 +++----
> .../net/wireless/mediatek/mt76/mt76x02_usb.h | 2 +-
> .../wireless/mediatek/mt76/mt76x02_usb_core.c | 4 +-
> .../net/wireless/mediatek/mt76/mt76x02_util.c | 16 ------
> .../net/wireless/mediatek/mt76/mt76x2/pci.c | 1 +
> 11 files changed, 68 insertions(+), 64 deletions(-)
I forgot to mention this series is based on:
'introduce mt76_sw_queue data structure'
https://patchwork.kernel.org/cover/10836583/
Regards,
Lorenzo
>
> --
> 2.20.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] mt76: mt7603: use the correct hweight8() function
From: Kalle Valo @ 2019-03-11 13:17 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <20190311130953.61869-1-nbd@nbd.name>
Felix Fietkau <nbd@nbd.name> writes:
> __sw_hweight8() is only defined if CONFIG_GENERIC_HWEIGHT is enabled.
> The function that works on all architectures is hweight8().
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This should go to 5.1, right?
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v7 09/14] rtw88: chip files
From: Stanislaw Gruszka @ 2019-03-11 13:17 UTC (permalink / raw)
To: yhchuang
Cc: kvalo, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <1552139302-20476-10-git-send-email-yhchuang@realtek.com>
On Sat, Mar 09, 2019 at 09:48:17PM +0800, yhchuang@realtek.com wrote:
> + rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x57);
Using of 0xff00 would more readable for average developer than MASKBYTE1
IMHO all of those MASK* defines should be removed and replaced by hex
numbers or GENMASK() makro for non-standard masks like 0x3fe0 .
> + rtw_write32_mask(rtwdev, REG_CCASEL, MASKDWORD, reg82c);
MASKDWORD is 0xffffffff (all bits of 32 bit word), rtw_write32_mask()
can be just replaced by rtw_write32().
Stanislaw
^ permalink raw reply
* Re: [PATCH v7 01/14] rtw88: main files
From: Kalle Valo @ 2019-03-11 13:14 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: yhchuang, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <20190311131100.GA6482@redhat.com>
Stanislaw Gruszka <sgruszka@redhat.com> writes:
>> +#define RA_MASK_VHT_RATES_1SS (0x3ff000 << 0)
>> +#define RA_MASK_VHT_RATES_2SS (0x3ff000 << 10)
>> +#define RA_MASK_VHT_RATES_3SS (0x3ff000 << 20)
>
> Result will not fit in 32 bit, ULL marker should be added.
I haven't checked how these are used but IMHO using GENMASK() would be
so much better.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v7 01/14] rtw88: main files
From: Stanislaw Gruszka @ 2019-03-11 13:11 UTC (permalink / raw)
To: yhchuang
Cc: kvalo, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <1552139302-20476-2-git-send-email-yhchuang@realtek.com>
> +#define RA_MASK_VHT_RATES_1SS (0x3ff000 << 0)
> +#define RA_MASK_VHT_RATES_2SS (0x3ff000 << 10)
> +#define RA_MASK_VHT_RATES_3SS (0x3ff000 << 20)
Result will not fit in 32 bit, ULL marker should be added.
I would also check if the driver compile without warnings
on 32 bit cpus.
Stanislaw
^ permalink raw reply
* [PATCH] mt76: mt7603: use the correct hweight8() function
From: Felix Fietkau @ 2019-03-11 13:09 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo
__sw_hweight8() is only defined if CONFIG_GENERIC_HWEIGHT is enabled.
The function that works on all architectures is hweight8().
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | 3 +--
drivers/net/wireless/mediatek/mt76/mt7603/init.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
index afcd86f735b4..4dcb465095d1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
@@ -135,8 +135,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)
out:
mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false);
- if (dev->mt76.q_tx[MT_TXQ_BEACON].queued >
- __sw_hweight8(dev->beacon_mask))
+ if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > hweight8(dev->beacon_mask))
dev->beacon_check++;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index 15cc8f33b34d..d54dda67d036 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -112,7 +112,7 @@ static void
mt7603_phy_init(struct mt7603_dev *dev)
{
int rx_chains = dev->mt76.antenna_mask;
- int tx_chains = __sw_hweight8(rx_chains) - 1;
+ int tx_chains = hweight8(rx_chains) - 1;
mt76_rmw(dev, MT_WF_RMAC_RMCR,
(MT_WF_RMAC_RMCR_SMPS_MODE |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
index 4b0713f1fd5e..d06905ea8cc6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
@@ -433,7 +433,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)
{
struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
struct ieee80211_hw *hw = mt76_hw(dev);
- int n_chains = __sw_hweight8(dev->mt76.antenna_mask);
+ int n_chains = hweight8(dev->mt76.antenna_mask);
struct {
u8 control_chan;
u8 center_chan;
--
2.17.0
^ permalink raw reply related
* Re: [PATCH v7 03/14] rtw88: hci files
From: Johannes Berg @ 2019-03-11 12:52 UTC (permalink / raw)
To: Stanislaw Gruszka, yhchuang
Cc: kvalo, gregkh, linux-wireless, Larry.Finger, pkshih, tehuang,
briannorris
In-Reply-To: <20190311125054.GA5005@redhat.com>
On Mon, 2019-03-11 at 13:50 +0100, Stanislaw Gruszka wrote:
<snip almost 1000 lines>
> <snip>
yeah, well, that wasn't much snipping you did there. Please snip more.
johannes
^ permalink raw reply
* Re: [PATCH v7 03/14] rtw88: hci files
From: Stanislaw Gruszka @ 2019-03-11 12:50 UTC (permalink / raw)
To: yhchuang
Cc: kvalo, johannes, gregkh, linux-wireless, Larry.Finger, pkshih,
tehuang, briannorris
In-Reply-To: <1552139302-20476-4-git-send-email-yhchuang@realtek.com>
On Sat, Mar 09, 2019 at 09:48:11PM +0800, yhchuang@realtek.com wrote:
> From: Yan-Hsuan Chuang <yhchuang@realtek.com>
>
> hci files for Realtek 802.11ac wireless network chips
>
> For now there is only PCI bus supported by rtwlan, in the future it
> will also have USB/SDIO
>
> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> ---
> drivers/net/wireless/realtek/rtw88/hci.h | 211 ++++++
> drivers/net/wireless/realtek/rtw88/pci.c | 1211 ++++++++++++++++++++++++++++++
> drivers/net/wireless/realtek/rtw88/pci.h | 237 ++++++
> 3 files changed, 1659 insertions(+)
> create mode 100644 drivers/net/wireless/realtek/rtw88/hci.h
> create mode 100644 drivers/net/wireless/realtek/rtw88/pci.c
> create mode 100644 drivers/net/wireless/realtek/rtw88/pci.h
>
> diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h
> new file mode 100644
> index 0000000..91b15ef
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/hci.h
> @@ -0,0 +1,211 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright(c) 2018 Realtek Corporation.
> + */
> +
> +#ifndef __RTW_HCI_H__
> +#define __RTW_HCI_H__
> +
> +/* ops for PCI, USB and SDIO */
> +struct rtw_hci_ops {
> + int (*tx)(struct rtw_dev *rtwdev,
> + struct rtw_tx_pkt_info *pkt_info,
> + struct sk_buff *skb);
> + int (*setup)(struct rtw_dev *rtwdev);
> + int (*start)(struct rtw_dev *rtwdev);
> + void (*stop)(struct rtw_dev *rtwdev);
> +
> + int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
> + int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
> +
> + u8 (*read8)(struct rtw_dev *rtwdev, u32 addr);
> + u16 (*read16)(struct rtw_dev *rtwdev, u32 addr);
> + u32 (*read32)(struct rtw_dev *rtwdev, u32 addr);
> + void (*write8)(struct rtw_dev *rtwdev, u32 addr, u8 val);
> + void (*write16)(struct rtw_dev *rtwdev, u32 addr, u16 val);
> + void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val);
> +};
> +
> +static inline int rtw_hci_tx(struct rtw_dev *rtwdev,
> + struct rtw_tx_pkt_info *pkt_info,
> + struct sk_buff *skb)
> +{
> + return rtwdev->hci.ops->tx(rtwdev, pkt_info, skb);
> +}
> +
> +static inline int rtw_hci_setup(struct rtw_dev *rtwdev)
> +{
> + return rtwdev->hci.ops->setup(rtwdev);
> +}
> +
> +static inline int rtw_hci_start(struct rtw_dev *rtwdev)
> +{
> + return rtwdev->hci.ops->start(rtwdev);
> +}
> +
> +static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
> +{
> + rtwdev->hci.ops->stop(rtwdev);
> +}
> +
> +static inline int
> +rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
> +{
> + return rtwdev->hci.ops->write_data_rsvd_page(rtwdev, buf, size);
> +}
> +
> +static inline int
> +rtw_hci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
> +{
> + return rtwdev->hci.ops->write_data_h2c(rtwdev, buf, size);
> +}
> +
> +static inline u8 rtw_read8(struct rtw_dev *rtwdev, u32 addr)
> +{
> + return rtwdev->hci.ops->read8(rtwdev, addr);
> +}
> +
> +static inline u16 rtw_read16(struct rtw_dev *rtwdev, u32 addr)
> +{
> + return rtwdev->hci.ops->read16(rtwdev, addr);
> +}
> +
> +static inline u32 rtw_read32(struct rtw_dev *rtwdev, u32 addr)
> +{
> + return rtwdev->hci.ops->read32(rtwdev, addr);
> +}
> +
> +static inline void rtw_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
> +{
> + rtwdev->hci.ops->write8(rtwdev, addr, val);
> +}
> +
> +static inline void rtw_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
> +{
> + rtwdev->hci.ops->write16(rtwdev, addr, val);
> +}
> +
> +static inline void rtw_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
> +{
> + rtwdev->hci.ops->write32(rtwdev, addr, val);
> +}
> +
> +static inline void rtw_write8_set(struct rtw_dev *rtwdev, u32 addr, u8 bit)
> +{
> + u8 val;
> +
> + val = rtw_read8(rtwdev, addr);
> + rtw_write8(rtwdev, addr, val | bit);
> +}
> +
> +static inline void rtw_writ16_set(struct rtw_dev *rtwdev, u32 addr, u16 bit)
> +{
> + u16 val;
> +
> + val = rtw_read16(rtwdev, addr);
> + rtw_write16(rtwdev, addr, val | bit);
> +}
> +
> +static inline void rtw_write32_set(struct rtw_dev *rtwdev, u32 addr, u32 bit)
> +{
> + u32 val;
> +
> + val = rtw_read32(rtwdev, addr);
> + rtw_write32(rtwdev, addr, val | bit);
> +}
> +
> +static inline void rtw_write8_clr(struct rtw_dev *rtwdev, u32 addr, u8 bit)
> +{
> + u8 val;
> +
> + val = rtw_read8(rtwdev, addr);
> + rtw_write8(rtwdev, addr, val & ~bit);
> +}
> +
> +static inline void rtw_write16_clr(struct rtw_dev *rtwdev, u32 addr, u16 bit)
> +{
> + u16 val;
> +
> + val = rtw_read16(rtwdev, addr);
> + rtw_write16(rtwdev, addr, val & ~bit);
> +}
> +
> +static inline void rtw_write32_clr(struct rtw_dev *rtwdev, u32 addr, u32 bit)
> +{
> + u32 val;
> +
> + val = rtw_read32(rtwdev, addr);
> + rtw_write32(rtwdev, addr, val & ~bit);
> +}
> +
> +static inline u32
> +rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
> + u32 addr, u32 mask)
> +{
> + unsigned long flags;
> + u32 val;
> +
> + spin_lock_irqsave(&rtwdev->rf_lock, flags);
> + val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
> + spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
> +
> + return val;
> +}
> +
> +static inline void
> +rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
> + u32 addr, u32 mask, u32 data)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&rtwdev->rf_lock, flags);
> + rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
> + spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
> +}
> +
> +static inline u32
> +rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
> +{
> + u32 shift = __ffs(mask);
> + u32 orig;
> + u32 ret;
> +
> + orig = rtw_read32(rtwdev, addr);
> + ret = (orig & mask) >> shift;
> +
> + return ret;
> +}
> +
> +static inline void
> +rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
> +{
> + u32 shift = __ffs(mask);
> + u32 orig;
> + u32 set;
> +
> + WARN(addr & 0x3, "should be 4-byte aligned, addr = 0x%08x\n", addr);
> +
> + orig = rtw_read32(rtwdev, addr);
> + set = (orig & ~mask) | ((data << shift) & mask);
> + rtw_write32(rtwdev, addr, set);
> +}
> +
> +static inline void
> +rtw_write8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u8 data)
> +{
> + u32 shift;
> + u8 orig, set;
> +
> + mask &= 0xff;
> + shift = __ffs(mask);
> +
> + orig = rtw_read8(rtwdev, addr);
> + set = (orig & ~mask) | ((data << shift) & mask);
> + rtw_write8(rtwdev, addr, set);
> +}
> +
> +static inline enum rtw_hci_type rtw_hci_type(struct rtw_dev *rtwdev)
> +{
> + return rtwdev->hci.type;
> +}
> +
> +#endif
> diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
> new file mode 100644
> index 0000000..cf3bffb
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -0,0 +1,1211 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright(c) 2018 Realtek Corporation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include "main.h"
> +#include "pci.h"
> +#include "tx.h"
> +#include "rx.h"
> +#include "debug.h"
> +
> +static u32 rtw_pci_tx_queue_idx_addr[] = {
> + [RTW_TX_QUEUE_BK] = RTK_PCI_TXBD_IDX_BKQ,
> + [RTW_TX_QUEUE_BE] = RTK_PCI_TXBD_IDX_BEQ,
> + [RTW_TX_QUEUE_VI] = RTK_PCI_TXBD_IDX_VIQ,
> + [RTW_TX_QUEUE_VO] = RTK_PCI_TXBD_IDX_VOQ,
> + [RTW_TX_QUEUE_MGMT] = RTK_PCI_TXBD_IDX_MGMTQ,
> + [RTW_TX_QUEUE_HI0] = RTK_PCI_TXBD_IDX_HI0Q,
> + [RTW_TX_QUEUE_H2C] = RTK_PCI_TXBD_IDX_H2CQ,
> +};
> +
> +static u8 rtw_pci_get_tx_qsel(struct sk_buff *skb, u8 queue)
> +{
> + switch (queue) {
> + case RTW_TX_QUEUE_BCN:
> + return TX_DESC_QSEL_BEACON;
> + case RTW_TX_QUEUE_H2C:
> + return TX_DESC_QSEL_H2C;
> + case RTW_TX_QUEUE_MGMT:
> + return TX_DESC_QSEL_MGMT;
> + case RTW_TX_QUEUE_HI0:
> + return TX_DESC_QSEL_HIGH;
> + default:
> + return skb->priority;
> + }
> +};
> +
> +static u8 rtw_pci_read8(struct rtw_dev *rtwdev, u32 addr)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> + return readb(rtwpci->mmap + addr);
> +}
> +
> +static u16 rtw_pci_read16(struct rtw_dev *rtwdev, u32 addr)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> + return readw(rtwpci->mmap + addr);
> +}
> +
> +static u32 rtw_pci_read32(struct rtw_dev *rtwdev, u32 addr)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> + return readl(rtwpci->mmap + addr);
> +}
> +
> +static void rtw_pci_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> + writeb(val, rtwpci->mmap + addr);
> +}
> +
> +static void rtw_pci_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> + writew(val, rtwpci->mmap + addr);
> +}
> +
> +static void rtw_pci_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> + writel(val, rtwpci->mmap + addr);
> +}
> +
> +static inline void *rtw_pci_get_tx_desc(struct rtw_pci_tx_ring *tx_ring, u8 idx)
> +{
> + int offset = tx_ring->r.desc_size * idx;
> +
> + return tx_ring->r.head + offset;
> +}
> +
> +static void rtw_pci_free_tx_ring(struct rtw_dev *rtwdev,
> + struct rtw_pci_tx_ring *tx_ring)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + struct rtw_pci_tx_data *tx_data;
> + struct sk_buff *skb, *tmp;
> + dma_addr_t dma;
> + u8 *head = tx_ring->r.head;
> + u32 len = tx_ring->r.len;
> + int ring_sz = len * tx_ring->r.desc_size;
> +
> + /* free every skb remained in tx list */
> + skb_queue_walk_safe(&tx_ring->queue, skb, tmp) {
> + __skb_unlink(skb, &tx_ring->queue);
> + tx_data = rtw_pci_get_tx_data(skb);
> + dma = tx_data->dma;
> +
> + pci_unmap_single(pdev, dma, skb->len, PCI_DMA_TODEVICE);
> + dev_kfree_skb_any(skb);
> + }
> +
> + /* free the ring itself */
> + pci_free_consistent(pdev, ring_sz, head, tx_ring->r.dma);
> + tx_ring->r.head = NULL;
> +}
> +
> +static void rtw_pci_free_rx_ring(struct rtw_dev *rtwdev,
> + struct rtw_pci_rx_ring *rx_ring)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + struct sk_buff *skb;
> + dma_addr_t dma;
> + u8 *head = rx_ring->r.head;
> + int buf_sz = RTK_PCI_RX_BUF_SIZE;
> + int ring_sz = rx_ring->r.desc_size * rx_ring->r.len;
> + int i;
> +
> + for (i = 0; i < rx_ring->r.len; i++) {
> + skb = rx_ring->buf[i];
> + if (!skb)
> + continue;
> +
> + dma = *((dma_addr_t *)skb->cb);
> + pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE);
> + dev_kfree_skb(skb);
> + rx_ring->buf[i] = NULL;
> + }
> +
> + pci_free_consistent(pdev, ring_sz, head, rx_ring->r.dma);
> +}
> +
> +static void rtw_pci_free_trx_ring(struct rtw_dev *rtwdev)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + struct rtw_pci_tx_ring *tx_ring;
> + struct rtw_pci_rx_ring *rx_ring;
> + int i;
> +
> + for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) {
> + tx_ring = &rtwpci->tx_rings[i];
> + rtw_pci_free_tx_ring(rtwdev, tx_ring);
> + }
> +
> + for (i = 0; i < RTK_MAX_RX_QUEUE_NUM; i++) {
> + rx_ring = &rtwpci->rx_rings[i];
> + rtw_pci_free_rx_ring(rtwdev, rx_ring);
> + }
> +}
> +
> +static int rtw_pci_init_tx_ring(struct rtw_dev *rtwdev,
> + struct rtw_pci_tx_ring *tx_ring,
> + u8 desc_size, u32 len)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + int ring_sz = desc_size * len;
> + dma_addr_t dma;
> + u8 *head;
> +
> + head = pci_zalloc_consistent(pdev, ring_sz, &dma);
> + if (!head) {
> + rtw_err(rtwdev, "failed to allocate tx ring\n");
> + return -ENOMEM;
> + }
> +
> + skb_queue_head_init(&tx_ring->queue);
> + tx_ring->r.head = head;
> + tx_ring->r.dma = dma;
> + tx_ring->r.len = len;
> + tx_ring->r.desc_size = desc_size;
> + tx_ring->r.wp = 0;
> + tx_ring->r.rp = 0;
> +
> + return 0;
> +}
> +
> +static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
> + struct rtw_pci_rx_ring *rx_ring,
> + u32 idx, u32 desc_sz)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + struct rtw_pci_rx_buffer_desc *buf_desc;
> + int buf_sz = RTK_PCI_RX_BUF_SIZE;
> + dma_addr_t dma;
> +
> + if (!skb)
> + return -EINVAL;
> +
> + dma = pci_map_single(pdev, skb->data, buf_sz, PCI_DMA_FROMDEVICE);
> + if (pci_dma_mapping_error(pdev, dma))
> + return -EBUSY;
> +
> + *((dma_addr_t *)skb->cb) = dma;
> + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
> + idx * desc_sz);
> + memset(buf_desc, 0, sizeof(*buf_desc));
> + buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE);
> + buf_desc->dma = cpu_to_le32(dma);
> +
> + return 0;
> +}
> +
> +static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev,
> + struct rtw_pci_rx_ring *rx_ring,
> + u8 desc_size, u32 len)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + struct sk_buff *skb = NULL;
> + dma_addr_t dma;
> + u8 *head;
> + int ring_sz = desc_size * len;
> + int buf_sz = RTK_PCI_RX_BUF_SIZE;
> + int i, allocated;
> + int ret = 0;
> +
> + head = pci_zalloc_consistent(pdev, ring_sz, &dma);
> + if (!head) {
> + rtw_err(rtwdev, "failed to allocate rx ring\n");
> + return -ENOMEM;
> + }
> + rx_ring->r.head = head;
> +
> + for (i = 0; i < len; i++) {
> + skb = dev_alloc_skb(buf_sz);
> + if (!skb) {
> + allocated = i;
> + ret = -ENOMEM;
> + goto err_out;
> + }
> +
> + memset(skb->data, 0, buf_sz);
> + rx_ring->buf[i] = skb;
> + ret = rtw_pci_reset_rx_desc(rtwdev, skb, rx_ring, i, desc_size);
> + if (ret) {
> + allocated = i;
> + dev_kfree_skb_any(skb);
> + goto err_out;
> + }
> + }
> +
> + rx_ring->r.dma = dma;
> + rx_ring->r.len = len;
> + rx_ring->r.desc_size = desc_size;
> + rx_ring->r.wp = 0;
> + rx_ring->r.rp = 0;
> +
> + return 0;
> +
> +err_out:
> + for (i = 0; i < allocated; i++) {
> + skb = rx_ring->buf[i];
> + if (!skb)
> + continue;
> + dma = *((dma_addr_t *)skb->cb);
> + pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE);
> + dev_kfree_skb_any(skb);
> + rx_ring->buf[i] = NULL;
> + }
> + pci_free_consistent(pdev, ring_sz, head, dma);
> +
> + rtw_err(rtwdev, "failed to init rx buffer\n");
> +
> + return ret;
> +}
> +
> +static int rtw_pci_init_trx_ring(struct rtw_dev *rtwdev)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + struct rtw_pci_tx_ring *tx_ring;
> + struct rtw_pci_rx_ring *rx_ring;
> + struct rtw_chip_info *chip = rtwdev->chip;
> + int i = 0, j = 0, tx_alloced = 0, rx_alloced = 0;
> + int tx_desc_size, rx_desc_size;
> + u32 len;
> + int ret;
> +
> + tx_desc_size = chip->tx_buf_desc_sz;
> +
> + for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) {
> + tx_ring = &rtwpci->tx_rings[i];
> + len = max_num_of_tx_queue(i);
> + ret = rtw_pci_init_tx_ring(rtwdev, tx_ring, tx_desc_size, len);
> + if (ret)
> + goto out;
> + }
> +
> + rx_desc_size = chip->rx_buf_desc_sz;
> +
> + for (j = 0; j < RTK_MAX_RX_QUEUE_NUM; j++) {
> + rx_ring = &rtwpci->rx_rings[j];
> + ret = rtw_pci_init_rx_ring(rtwdev, rx_ring, rx_desc_size,
> + RTK_MAX_RX_DESC_NUM);
> + if (ret)
> + goto out;
> + }
> +
> + return 0;
> +
> +out:
> + tx_alloced = i;
> + for (i = 0; i < tx_alloced; i++) {
> + tx_ring = &rtwpci->tx_rings[i];
> + rtw_pci_free_tx_ring(rtwdev, tx_ring);
> + }
> +
> + rx_alloced = j;
> + for (j = 0; j < rx_alloced; j++) {
> + rx_ring = &rtwpci->rx_rings[j];
> + rtw_pci_free_rx_ring(rtwdev, rx_ring);
> + }
> +
> + return ret;
> +}
> +
> +static void rtw_pci_deinit(struct rtw_dev *rtwdev)
> +{
> + rtw_pci_free_trx_ring(rtwdev);
> +}
> +
> +static int rtw_pci_init(struct rtw_dev *rtwdev)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + int ret = 0;
> +
> + rtwpci->irq_mask[0] = IMR_HIGHDOK |
> + IMR_MGNTDOK |
> + IMR_BKDOK |
> + IMR_BEDOK |
> + IMR_VIDOK |
> + IMR_VODOK |
> + IMR_ROK |
> + IMR_BCNDMAINT_E |
> + 0;
> + rtwpci->irq_mask[1] = IMR_TXFOVW |
> + 0;
> + rtwpci->irq_mask[3] = IMR_H2CDOK |
> + 0;
> + spin_lock_init(&rtwpci->irq_lock);
> + ret = rtw_pci_init_trx_ring(rtwdev);
> +
> + return ret;
> +}
> +
> +static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + u32 len;
> + u8 tmp;
> + dma_addr_t dma;
> +
> + tmp = rtw_read8(rtwdev, RTK_PCI_CTRL + 3);
> + rtw_write8(rtwdev, RTK_PCI_CTRL + 3, tmp | 0xf7);
> +
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_BCN].r.dma;
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BCNQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_H2CQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BKQ, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BKQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BEQ, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BEQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VOQ, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VOQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VIQ, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VIQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_MGMTQ, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_MGMTQ, dma);
> +
> + len = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.len;
> + dma = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.dma;
> + rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.rp = 0;
> + rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_HI0Q, len);
> + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_HI0Q, dma);
> +
> + len = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.len;
> + dma = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.dma;
> + rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.rp = 0;
> + rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.wp = 0;
> + rtw_write16(rtwdev, RTK_PCI_RXBD_NUM_MPDUQ, len & 0xfff);
> + rtw_write32(rtwdev, RTK_PCI_RXBD_DESA_MPDUQ, dma);
> +
> + /* reset read/write point */
> + rtw_write32(rtwdev, RTK_PCI_TXBD_RWPTR_CLR, 0xffffffff);
> +
> + /* rest H2C Queue index */
> + rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HOST_IDX);
> + rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HW_IDX);
> +}
> +
> +static void rtw_pci_reset_trx_ring(struct rtw_dev *rtwdev)
> +{
> + rtw_pci_reset_buf_desc(rtwdev);
> +}
> +
> +static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev,
> + struct rtw_pci *rtwpci)
> +{
> + rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0]);
> + rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]);
> + rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]);
> + rtwpci->irq_enabled = true;
> +}
> +
> +static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev,
> + struct rtw_pci *rtwpci)
> +{
> + rtw_write32(rtwdev, RTK_PCI_HIMR0, 0);
> + rtw_write32(rtwdev, RTK_PCI_HIMR1, 0);
> + rtw_write32(rtwdev, RTK_PCI_HIMR3, 0);
> + rtwpci->irq_enabled = false;
> +}
> +
> +static int rtw_pci_setup(struct rtw_dev *rtwdev)
> +{
> + rtw_pci_reset_trx_ring(rtwdev);
> +
> + return 0;
> +}
> +
> +static void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci)
> +{
> + /* reset dma and rx tag */
> + rtw_write32_set(rtwdev, RTK_PCI_CTRL,
> + BIT_RST_TRXDMA_INTF | BIT_RX_TAG_EN);
> + rtwpci->rx_tag = 0;
> +}
> +
> +static int rtw_pci_start(struct rtw_dev *rtwdev)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + unsigned long flags;
> +
> + rtw_pci_dma_reset(rtwdev, rtwpci);
> +
> + spin_lock_irqsave(&rtwpci->irq_lock, flags);
> + rtw_pci_enable_interrupt(rtwdev, rtwpci);
> + spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
> +
> + return 0;
> +}
> +
> +static void rtw_pci_stop(struct rtw_dev *rtwdev)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&rtwpci->irq_lock, flags);
> + rtw_pci_disable_interrupt(rtwdev, rtwpci);
> + spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
> +}
> +
> +static u8 ac_to_hwq[] = {
> + [0] = RTW_TX_QUEUE_VO,
> + [1] = RTW_TX_QUEUE_VI,
> + [2] = RTW_TX_QUEUE_BE,
> + [3] = RTW_TX_QUEUE_BK,
> +};
> +
> +static u8 rtw_hw_queue_mapping(struct sk_buff *skb)
> +{
> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> + __le16 fc = hdr->frame_control;
> + u8 q_mapping = skb_get_queue_mapping(skb);
> + u8 queue;
> +
> + if (unlikely(ieee80211_is_beacon(fc)))
> + queue = RTW_TX_QUEUE_BCN;
> + else if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
> + queue = RTW_TX_QUEUE_MGMT;
> + else
> + queue = ac_to_hwq[q_mapping];
> +
> + return queue;
> +}
> +
> +static void rtw_pci_release_rsvd_page(struct rtw_pci *rtwpci,
> + struct rtw_pci_tx_ring *ring)
> +{
> + struct sk_buff *prev = skb_dequeue(&ring->queue);
> + struct rtw_pci_tx_data *tx_data;
> + dma_addr_t dma;
> +
> + if (!prev)
> + return;
> +
> + tx_data = rtw_pci_get_tx_data(prev);
> + dma = tx_data->dma;
> + pci_unmap_single(rtwpci->pdev, dma, prev->len,
> + PCI_DMA_TODEVICE);
> + dev_kfree_skb_any(prev);
> +}
> +
> +static void rtw_pci_dma_check(struct rtw_dev *rtwdev,
> + struct rtw_pci_rx_ring *rx_ring,
> + u32 idx)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + struct rtw_chip_info *chip = rtwdev->chip;
> + struct rtw_pci_rx_buffer_desc *buf_desc;
> + u32 desc_sz = chip->rx_buf_desc_sz;
> + u16 total_pkt_size;
> +
> + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
> + idx * desc_sz);
> + total_pkt_size = le16_to_cpu(buf_desc->total_pkt_size);
> +
> + /* rx tag mismatch, throw a warning */
> + if (total_pkt_size != rtwpci->rx_tag)
> + rtw_warn(rtwdev, "pci bus timeout, check dma status\n");
> +
> + rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX;
> +}
> +
> +static int rtw_pci_xmit(struct rtw_dev *rtwdev,
> + struct rtw_tx_pkt_info *pkt_info,
> + struct sk_buff *skb, u8 queue)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + struct rtw_chip_info *chip = rtwdev->chip;
> + struct rtw_pci_tx_ring *ring;
> + struct rtw_pci_tx_data *tx_data;
> + dma_addr_t dma;
> + u32 tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
> + u32 tx_buf_desc_sz = chip->tx_buf_desc_sz;
> + u32 size;
> + u32 psb_len;
> + u8 *pkt_desc;
> + struct rtw_pci_tx_buffer_desc *buf_desc;
> + u32 bd_idx;
> +
> + ring = &rtwpci->tx_rings[queue];
> +
> + size = skb->len;
> +
> + if (queue == RTW_TX_QUEUE_BCN)
> + rtw_pci_release_rsvd_page(rtwpci, ring);
> + else if (!avail_desc(ring->r.wp, ring->r.rp, ring->r.len))
> + return -ENOSPC;
> +
> + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
> + memset(pkt_desc, 0, tx_pkt_desc_sz);
> + pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue);
> + rtw_tx_fill_tx_desc(pkt_info, skb);
> + dma = pci_map_single(rtwpci->pdev, skb->data, skb->len,
> + PCI_DMA_TODEVICE);
> + if (pci_dma_mapping_error(rtwpci->pdev, dma))
> + return -EBUSY;
> +
> + /* after this we got dma mapped, there is no way back */
> + buf_desc = get_tx_buffer_desc(ring, tx_buf_desc_sz);
> + memset(buf_desc, 0, tx_buf_desc_sz);
> + psb_len = (skb->len - 1) / 128 + 1;
> + if (queue == RTW_TX_QUEUE_BCN)
> + psb_len |= 1 << RTK_PCI_TXBD_OWN_OFFSET;
> +
> + buf_desc[0].psb_len = cpu_to_le16(psb_len);
> + buf_desc[0].buf_size = cpu_to_le16(tx_pkt_desc_sz);
> + buf_desc[0].dma = cpu_to_le32(dma);
> + buf_desc[1].buf_size = cpu_to_le16(size);
> + buf_desc[1].dma = cpu_to_le32(dma + tx_pkt_desc_sz);
> +
> + tx_data = rtw_pci_get_tx_data(skb);
> + tx_data->dma = dma;
> + tx_data->sn = pkt_info->sn;
> + skb_queue_tail(&ring->queue, skb);
> +
> + /* kick off tx queue */
> + if (queue != RTW_TX_QUEUE_BCN) {
> + if (++ring->r.wp >= ring->r.len)
> + ring->r.wp = 0;
> + bd_idx = rtw_pci_tx_queue_idx_addr[queue];
> + rtw_write16(rtwdev, bd_idx, ring->r.wp & 0xfff);
> + } else {
> + u32 reg_bcn_work;
> +
> + reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK);
> + reg_bcn_work |= BIT_PCI_BCNQ_FLAG;
> + rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work);
> + }
> +
> + return 0;
> +}
> +
> +static int rtw_pci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf,
> + u32 size)
> +{
> + struct sk_buff *skb;
> + struct rtw_tx_pkt_info pkt_info;
> + u32 tx_pkt_desc_sz;
> + u32 length;
> +
> + tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz;
> + length = size + tx_pkt_desc_sz;
> + skb = dev_alloc_skb(length);
> + if (!skb)
> + return -ENOMEM;
> +
> + skb_reserve(skb, tx_pkt_desc_sz);
> + memcpy((u8 *)skb_put(skb, size), buf, size);
> + memset(&pkt_info, 0, sizeof(pkt_info));
> + pkt_info.tx_pkt_size = size;
> + pkt_info.offset = tx_pkt_desc_sz;
> +
> + return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN);
> +}
> +
> +static int rtw_pci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
> +{
> + struct sk_buff *skb;
> + struct rtw_tx_pkt_info pkt_info;
> + u32 tx_pkt_desc_sz;
> + u32 length;
> +
> + tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz;
> + length = size + tx_pkt_desc_sz;
> + skb = dev_alloc_skb(length);
> + if (!skb)
> + return -ENOMEM;
> +
> + skb_reserve(skb, tx_pkt_desc_sz);
> + memcpy((u8 *)skb_put(skb, size), buf, size);
> + memset(&pkt_info, 0, sizeof(pkt_info));
> + pkt_info.tx_pkt_size = size;
> +
> + return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C);
> +}
> +
> +static int rtw_pci_tx(struct rtw_dev *rtwdev,
> + struct rtw_tx_pkt_info *pkt_info,
> + struct sk_buff *skb)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + struct rtw_pci_tx_ring *ring;
> + u8 queue = rtw_hw_queue_mapping(skb);
> + int ret;
> +
> + ret = rtw_pci_xmit(rtwdev, pkt_info, skb, queue);
> + if (ret)
> + return ret;
> +
> + ring = &rtwpci->tx_rings[queue];
> + if (avail_desc(ring->r.wp, ring->r.rp, ring->r.len) < 2) {
> + ieee80211_stop_queue(rtwdev->hw, skb_get_queue_mapping(skb));
> + ring->queue_stopped = true;
> + }
<snip>
> +static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
> + u8 hw_queue)
> +{
<snip>
> + if (ring->queue_stopped &&
> + avail_desc(ring->r.wp, ring->r.rp, ring->r.len) > 4) {
> + q_map = skb_get_queue_mapping(skb);
> + ieee80211_wake_queue(hw, q_map);
> + ring->queue_stopped = false;
There is small race window between this and corresponding queue stop
code in rtw_pci_tx(). If interrupt came between:
if (avail_desc(ring->r.wp, ring->r.rp, ring->r.len) < 2) {
and
ieee80211_stop_queue(rtwdev->hw, skb_get_queue_mapping(skb));
ring->queue_stopped = true;
and we will process all frames (this can happen if except rtw88 interrupt,
interrupts of other devices will be processed and slow down return to
interrupted code), we will end up with stopped queue and no more interrupts
to wake queue. So I think we should take rtwpci->irq_locck around avail_desc
check in rtw_pci_tx().
Additionally thresholds of 2 and 4 looks a bit small.
Stanislaw
^ permalink raw reply
* [PATCH 4/4] mt76: introduce mt76_tx_info data structure
From: Lorenzo Bianconi @ 2019-03-11 12:35 UTC (permalink / raw)
To: nbd; +Cc: ryder.lee, roychl666, linux-wireless, lorenzo.bianconi
In-Reply-To: <cover.1552306908.git.lorenzo@kernel.org>
Add mt76_tx_info as auxiliary data structure to pass values
to tx_prepare_skb pointer. This is a preliminary patch to add
support for new chipsets (e.g. mt7615)
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/dma.c | 27 ++++++++++---------
drivers/net/wireless/mediatek/mt76/mt76.h | 9 ++++++-
.../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +-
.../wireless/mediatek/mt76/mt7603/mt7603.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 +-
.../net/wireless/mediatek/mt76/mt76x02_txrx.c | 8 +++---
.../net/wireless/mediatek/mt76/mt76x02_usb.h | 2 +-
.../wireless/mediatek/mt76/mt76x02_usb_core.c | 2 +-
8 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index a29b2aa95a51..e1ff31205b11 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -284,13 +284,12 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
struct ieee80211_sta *sta)
{
struct mt76_queue *q = dev->q_tx[qid].q;
+ struct mt76_tx_info tx_info = {};
+ int len, n = 0, ret = -ENOMEM;
struct mt76_queue_entry e;
struct mt76_txwi_cache *t;
- struct mt76_queue_buf buf[32];
- int len, n = 0, ret = -ENOMEM;
struct sk_buff *iter;
dma_addr_t addr;
- u32 tx_info = 0;
t = mt76_get_txwi(dev);
if (!t) {
@@ -307,13 +306,13 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
if (dma_mapping_error(dev->dev, addr))
goto free;
- buf[n].addr = t->dma_addr;
- buf[n++].len = dev->drv->txwi_size;
- buf[n].addr = addr;
- buf[n++].len = len;
+ tx_info.buf[n].addr = t->dma_addr;
+ tx_info.buf[n++].len = dev->drv->txwi_size;
+ tx_info.buf[n].addr = addr;
+ tx_info.buf[n++].len = len;
skb_walk_frags(skb, iter) {
- if (n == ARRAY_SIZE(buf))
+ if (n == ARRAY_SIZE(tx_info.buf))
goto unmap;
addr = dma_map_single(dev->dev, iter->data, iter->len,
@@ -321,9 +320,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
if (dma_mapping_error(dev->dev, addr))
goto unmap;
- buf[n].addr = addr;
- buf[n++].len = iter->len;
+ tx_info.buf[n].addr = addr;
+ tx_info.buf[n++].len = iter->len;
}
+ tx_info.nbuf = n;
if (q->queued + (n + 1) / 2 >= q->ndesc - 1)
goto unmap;
@@ -337,12 +337,13 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
if (ret < 0)
goto unmap;
- return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t);
+ return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
+ tx_info.info, skb, t);
unmap:
for (n--; n > 0; n--)
- dma_unmap_single(dev->dev, buf[n].addr, buf[n].len,
- DMA_TO_DEVICE);
+ dma_unmap_single(dev->dev, tx_info.buf[n].addr,
+ tx_info.buf[n].len, DMA_TO_DEVICE);
free:
e.skb = skb;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index dc505d55409c..9573a283e29f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -83,6 +83,12 @@ struct mt76_queue_buf {
int len;
};
+struct mt76_tx_info {
+ struct mt76_queue_buf buf[32];
+ int nbuf;
+ u32 info;
+};
+
struct mt76u_buf {
struct mt76_dev *dev;
struct urb *urb;
@@ -296,7 +302,8 @@ struct mt76_driver_ops {
int (*tx_prepare_skb)(struct mt76_dev *dev, void *txwi_ptr,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid,
- struct ieee80211_sta *sta, u32 *tx_info);
+ struct ieee80211_sta *sta,
+ struct mt76_tx_info *tx_info);
void (*tx_complete_skb)(struct mt76_dev *dev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index 1ff4c10b291c..5f800467c628 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -939,7 +939,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info)
+ struct mt76_tx_info *tx_info)
{
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 8bd00b97066a..f414ff2a5279 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -225,7 +225,7 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort);
int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info);
+ struct mt76_tx_info *tx_info);
void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 53ec8103a268..cb5792b41d2d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -174,7 +174,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info);
+ struct mt76_tx_info *tx_info);
void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac);
void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index 708f2c65d3fd..dd7d04b9b8db 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(mt76x02_tx_status_data);
int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info)
+ struct mt76_tx_info *tx_info)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -169,11 +169,11 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (pid >= MT_PACKET_ID_FIRST)
qsel = MT_QSEL_MGMT;
- *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
- MT_TXD_INFO_80211;
+ tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
+ MT_TXD_INFO_80211;
if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv)
- *tx_info |= MT_TXD_INFO_WIV;
+ tx_info->info |= MT_TXD_INFO_WIV;
return 0;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
index 98e647c8c7c7..8f98cc6ce094 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
@@ -28,7 +28,7 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags);
int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info);
+ struct mt76_tx_info *tx_info);
void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e);
#endif /* __MT76x02_USB_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 6c3fc4cea283..394dfe5b4a2e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -74,7 +74,7 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
struct sk_buff *skb, enum mt76_txq_id qid,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
- u32 *tx_info)
+ struct mt76_tx_info *tx_info)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
int pid, len = skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx);
--
2.20.1
^ permalink raw reply related
* [PATCH 3/4] mt76: move skb dma mapping before running tx_prepare_skb
From: Lorenzo Bianconi @ 2019-03-11 12:35 UTC (permalink / raw)
To: nbd; +Cc: ryder.lee, roychl666, linux-wireless, lorenzo.bianconi
In-Reply-To: <cover.1552306908.git.lorenzo@kernel.org>
Move skb dma mapping before configuring txwi since new chipsets (mt7615)
will need skb dma addresses in order to properly configure txwi
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/dma.c | 29 ++++++++++--------------
1 file changed, 12 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 14dd6585bab4..a29b2aa95a51 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -287,11 +287,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
struct mt76_queue_entry e;
struct mt76_txwi_cache *t;
struct mt76_queue_buf buf[32];
+ int len, n = 0, ret = -ENOMEM;
struct sk_buff *iter;
dma_addr_t addr;
- int len;
u32 tx_info = 0;
- int n, ret;
t = mt76_get_txwi(dev);
if (!t) {
@@ -303,23 +302,11 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
if (dev->drv->tx_aligned4_skbs)
mt76_insert_hdr_pad(skb);
- dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi),
- DMA_TO_DEVICE);
- ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, qid, wcid, sta,
- &tx_info);
- dma_sync_single_for_device(dev->dev, t->dma_addr, sizeof(t->txwi),
- DMA_TO_DEVICE);
- if (ret < 0)
- goto free;
-
- len = skb->len - skb->data_len;
+ len = skb_headlen(skb);
addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE);
- if (dma_mapping_error(dev->dev, addr)) {
- ret = -ENOMEM;
+ if (dma_mapping_error(dev->dev, addr))
goto free;
- }
- n = 0;
buf[n].addr = t->dma_addr;
buf[n++].len = dev->drv->txwi_size;
buf[n].addr = addr;
@@ -341,10 +328,18 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
if (q->queued + (n + 1) / 2 >= q->ndesc - 1)
goto unmap;
+ dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi),
+ DMA_TO_DEVICE);
+ ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, qid, wcid, sta,
+ &tx_info);
+ dma_sync_single_for_device(dev->dev, t->dma_addr, sizeof(t->txwi),
+ DMA_TO_DEVICE);
+ if (ret < 0)
+ goto unmap;
+
return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t);
unmap:
- ret = -ENOMEM;
for (n--; n > 0; n--)
dma_unmap_single(dev->dev, buf[n].addr, buf[n].len,
DMA_TO_DEVICE);
--
2.20.1
^ permalink raw reply related
* [PATCH 2/4] mt76: mmio: move mt76_insert_hdr_pad in mt76_dma_tx_queue_skb
From: Lorenzo Bianconi @ 2019-03-11 12:35 UTC (permalink / raw)
To: nbd; +Cc: ryder.lee, roychl666, linux-wireless, lorenzo.bianconi
In-Reply-To: <cover.1552306908.git.lorenzo@kernel.org>
Introduce tx_aligned4_skbs in mt76_driver_ops and move
mt76_insert_hdr_pad in mt76_dma_tx_queue_skb. This is a preliminary
patch in order to unify tx dma mapping for mt76x02 and new chipsets
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/dma.c | 3 +++
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 +
drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 13 +++++--------
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 1 +
5 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index a66832a02281..14dd6585bab4 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -300,6 +300,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,
}
skb->prev = skb->next = NULL;
+ if (dev->drv->tx_aligned4_skbs)
+ mt76_insert_hdr_pad(skb);
+
dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi),
DMA_TO_DEVICE);
ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, qid, wcid, sta,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 971d968c1b5f..dc505d55409c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -288,6 +288,7 @@ struct mt76_hw_cap {
};
struct mt76_driver_ops {
+ bool tx_aligned4_skbs;
u16 txwi_size;
void (*update_survey)(struct mt76_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index f302162036d0..e07a62246db7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -164,6 +164,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
+ .tx_aligned4_skbs = true,
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
.tx_complete_skb = mt76x02_tx_complete_skb,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index f574866c7e9d..708f2c65d3fd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -152,23 +152,20 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
u32 *tx_info)
{
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct mt76x02_txwi *txwi = txwi_ptr;
- int qsel = MT_QSEL_EDCA;
- int pid;
- int ret;
+ int hdrlen, len, pid, qsel = MT_QSEL_EDCA;
if (qid == MT_TXQ_PSD && wcid && wcid->idx < 128)
mt76x02_mac_wcid_set_drop(dev, wcid->idx, false);
- mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len);
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ len = skb->len - (hdrlen & 2);
+ mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
pid = mt76_tx_status_skb_add(mdev, wcid, skb);
txwi->pktid = pid;
- ret = mt76_insert_hdr_pad(skb);
- if (ret < 0)
- return ret;
-
if (pid >= MT_PACKET_ID_FIRST)
qsel = MT_QSEL_MGMT;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
index 6274655e1f7e..4747f782417a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
@@ -32,6 +32,7 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
+ .tx_aligned4_skbs = true,
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
.tx_complete_skb = mt76x02_tx_complete_skb,
--
2.20.1
^ permalink raw reply related
* [PATCH 1/4] mt76: move mt76x02_insert_hdr_pad in mt76-core module
From: Lorenzo Bianconi @ 2019-03-11 12:35 UTC (permalink / raw)
To: nbd; +Cc: ryder.lee, roychl666, linux-wireless, lorenzo.bianconi
In-Reply-To: <cover.1552306908.git.lorenzo@kernel.org>
Move mt76x02_insert_hdr_pad in m76-core and rename it in
mt76_insert_hdr_pad in order to be used in mt76_dma_tx_queue_skb.
This is a preliminary patch in order to properly support tx dma
mapping for new chipsets (e.g. mt7615)
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 15 +++++++++++++++
drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 -
.../net/wireless/mediatek/mt76/mt76x02_txrx.c | 2 +-
.../wireless/mediatek/mt76/mt76x02_usb_core.c | 2 +-
.../net/wireless/mediatek/mt76/mt76x02_util.c | 16 ----------------
5 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 57136073e1fa..971d968c1b5f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -653,6 +653,21 @@ static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb)
return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data);
}
+static inline int mt76_insert_hdr_pad(struct sk_buff *skb)
+{
+ int len = ieee80211_get_hdrlen_from_skb(skb);
+
+ if (len % 4 == 0)
+ return 0;
+
+ skb_push(skb, 2);
+ memmove(skb->data, skb->data + 2, len);
+
+ skb->data[len] = 0;
+ skb->data[len + 1] = 0;
+ return 2;
+}
+
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb);
void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
struct mt76_wcid *wcid, struct sk_buff *skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 392b96fcb520..53ec8103a268 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -163,7 +163,6 @@ void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
s16 coverage_class);
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
-int mt76x02_insert_hdr_pad(struct sk_buff *skb);
void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index ce9ace11339d..f574866c7e9d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -165,7 +165,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
pid = mt76_tx_status_skb_add(mdev, wcid, skb);
txwi->pktid = pid;
- ret = mt76x02_insert_hdr_pad(skb);
+ ret = mt76_insert_hdr_pad(skb);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 8ab63255ba6f..6c3fc4cea283 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -82,7 +82,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
enum mt76_qsel qsel;
u32 flags;
- mt76x02_insert_hdr_pad(skb);
+ mt76_insert_hdr_pad(skb);
txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi));
mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index b14a55737829..81d65319d3ea 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -566,22 +566,6 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(mt76x02_sta_rate_tbl_update);
-int mt76x02_insert_hdr_pad(struct sk_buff *skb)
-{
- int len = ieee80211_get_hdrlen_from_skb(skb);
-
- if (len % 4 == 0)
- return 0;
-
- skb_push(skb, 2);
- memmove(skb->data, skb->data + 2, len);
-
- skb->data[len] = 0;
- skb->data[len + 1] = 0;
- return 2;
-}
-EXPORT_SYMBOL_GPL(mt76x02_insert_hdr_pad);
-
void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len)
{
int hdrlen;
--
2.20.1
^ 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