* Re: [PATCH 05/11] mac80211_hwsim: set p2p device interface support indication
From: Arend Van Spriel @ 2019-03-18 10:56 UTC (permalink / raw)
To: Luca Coelho, johannes; +Cc: linux-wireless, Avraham Stern, Luca Coelho
In-Reply-To: <20190315153907.16192-6-luca@coelho.fi>
On 3/15/2019 4:39 PM, Luca Coelho wrote:
> From: Avraham Stern <avraham.stern@intel.com>
>
> P2P device interface type was not indicated in the supported
> interface types even when hwsim was configured with p2p device
> support. Fix it.
Just wondering. Doesn't this affect the hwsim-based tests in wpa_supp?
Or is that the intent behind this patch.
Regards,
Arend
> Signed-off-by: Avraham Stern <avraham.stern@intel.com>
> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
> ---
> drivers/net/wireless/mac80211_hwsim.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
> index 0838af04d681..d79f3ee2a741 100644
> --- a/drivers/net/wireless/mac80211_hwsim.c
> +++ b/drivers/net/wireless/mac80211_hwsim.c
> @@ -3894,6 +3894,8 @@ static int __init init_mac80211_hwsim(void)
> param.p2p_device = support_p2p_device;
> param.use_chanctx = channels > 1;
> param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
> + if (param.p2p_device)
> + param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
>
> err = mac80211_hwsim_new_radio(NULL, ¶m);
> if (err < 0)
>
^ permalink raw reply
* Re: [PATCH 4/6] mt76: store software PN/IV in wcid
From: Felix Fietkau @ 2019-03-18 10:37 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: linux-wireless
In-Reply-To: <20190318102134.GC3323@redhat.com>
On 2019-03-18 11:21, Stanislaw Gruszka wrote:
> On Sat, Mar 16, 2019 at 09:42:40PM +0100, Felix Fietkau wrote:
>> Avoids expensive 64-bit atomic access in the data path
> <snip>
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
>> index d6e260ca1423..fb1961ac9dc6 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
>> @@ -924,7 +924,11 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
>> txwi[3] = cpu_to_le32(val);
>>
>> if (key) {
>> - u64 pn = atomic64_inc_return(&key->tx_pn);
>> + u64 pn;
>> +
>> + spin_lock(&dev->mt76.lock);
>> + pn = ++wcid->tx_pn;
>> + spin_unlock(&dev->mt76.lock);
>
> It's interesting that atomic op is more expensive that taking spinlock
> and do the operation under spinlock protection. This should not be
> the case, atomic ops are provided exactly to avoid locking and should
> be faster than spin_lock. Perhaps on architecture where this happen
> (presumably MIPS 32bit) either atomic ops assembly code should be fixed
> or arch should switch generic lib/atomic64.c .
The fact that lib/atomic64.c is being used is the problem here.
The generic implementation takes a spin_lock_irqsave, which is more
expensive than the bh lock.
- Felix
^ permalink raw reply
* Re: [PATCH 4/6] mt76: store software PN/IV in wcid
From: Stanislaw Gruszka @ 2019-03-18 10:21 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <20190316204242.73560-4-nbd@nbd.name>
On Sat, Mar 16, 2019 at 09:42:40PM +0100, Felix Fietkau wrote:
> Avoids expensive 64-bit atomic access in the data path
<snip>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
> index d6e260ca1423..fb1961ac9dc6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
> @@ -924,7 +924,11 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
> txwi[3] = cpu_to_le32(val);
>
> if (key) {
> - u64 pn = atomic64_inc_return(&key->tx_pn);
> + u64 pn;
> +
> + spin_lock(&dev->mt76.lock);
> + pn = ++wcid->tx_pn;
> + spin_unlock(&dev->mt76.lock);
It's interesting that atomic op is more expensive that taking spinlock
and do the operation under spinlock protection. This should not be
the case, atomic ops are provided exactly to avoid locking and should
be faster than spin_lock. Perhaps on architecture where this happen
(presumably MIPS 32bit) either atomic ops assembly code should be fixed
or arch should switch generic lib/atomic64.c .
Stanislaw
^ permalink raw reply
* [PATCH v2] mt76: move mac_work in mt76_dev
From: Lorenzo Bianconi @ 2019-03-18 10:21 UTC (permalink / raw)
To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sgruszka
In-Reply-To: <cover.1552903068.git.lorenzo@kernel.org>
Move mac_work delayed work in mt76_dev data structure since
it is used by all drivers and it will be reused adding mac work to
mt7615
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes since v1:
- drop typecast in mt7603_mac_work/mt76x02_mac_work
- rebase on top of https://patchwork.kernel.org/patch/10856027/
---
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
drivers/net/wireless/mediatek/mt76/mt7603/init.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 10 +++++-----
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 1 -
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 -
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +-
14 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 54e1e50eb4d2..2128c82c413b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -458,6 +458,7 @@ struct mt76_dev {
int tx_dma_idx[4];
struct tasklet_struct tx_tasklet;
+ struct delayed_work mac_work;
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index e17b6b89dfe2..a25a13a39640 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -510,7 +510,7 @@ int mt7603_register_device(struct mt7603_dev *dev)
bus_ops->rmw = mt7603_rmw;
dev->mt76.bus = bus_ops;
- INIT_DELAYED_WORK(&dev->mac_work, mt7603_mac_work);
+ INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7603_mac_work);
tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet,
(unsigned long)dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index 2badfe527397..1d6e2ba5925e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -1696,7 +1696,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev)
void mt7603_mac_work(struct work_struct *work)
{
struct mt7603_dev *dev = container_of(work, struct mt7603_dev,
- mac_work.work);
+ mt76.mac_work.work);
bool reset = false;
mt76_tx_status_check(&dev->mt76, NULL, false);
@@ -1749,6 +1749,6 @@ void mt7603_mac_work(struct work_struct *work)
if (reset)
mt7603_mac_watchdog_reset(dev);
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
msecs_to_jiffies(MT7603_WATCHDOG_TIME));
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 3754723190d5..e5fca95193e9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -16,7 +16,7 @@ mt7603_start(struct ieee80211_hw *hw)
mt7603_mac_start(dev);
dev->survey_time = ktime_get_boottime();
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
- mt7603_mac_work(&dev->mac_work.work);
+ mt7603_mac_work(&dev->mt76.mac_work.work);
return 0;
}
@@ -27,7 +27,7 @@ mt7603_stop(struct ieee80211_hw *hw)
struct mt7603_dev *dev = hw->priv;
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
- cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->mt76.mac_work);
mt7603_mac_stop(dev);
}
@@ -132,7 +132,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
u8 bw = MT_BW_20;
bool failed = false;
- cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->mt76.mac_work);
mutex_lock(&dev->mt76.mutex);
set_bit(MT76_RESET, &dev->mt76.state);
@@ -171,7 +171,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
mt76_txq_schedule_all(&dev->mt76);
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
MT7603_WATCHDOG_TIME);
/* reset channel stats */
@@ -189,7 +189,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
mutex_unlock(&dev->mt76.mutex);
if (failed)
- mt7603_mac_work(&dev->mac_work.work);
+ mt7603_mac_work(&dev->mt76.mac_work.work);
return ret;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 3848a011105f..1559ca122b9a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -144,7 +144,6 @@ struct mt7603_dev {
unsigned int reset_cause[__RESET_CAUSE_MAX];
- struct delayed_work mac_work;
struct tasklet_struct pre_tbtt_tasklet;
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index e07a62246db7..b934a974df32 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -29,7 +29,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
mt76x02_mac_start(dev);
mt76x0_phy_calibrate(dev, true);
- ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mt76.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
@@ -43,7 +43,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
static void mt76x0e_stop_hw(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
- cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->mt76.mac_work);
if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,
0, 1000))
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index ff887454e51e..619fc3ecdd5d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -85,7 +85,7 @@ static void mt76x0u_mac_stop(struct mt76x02_dev *dev)
{
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
cancel_delayed_work_sync(&dev->cal_work);
- cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->mt76.mac_work);
mt76u_stop_stat_wk(&dev->mt76);
if (test_bit(MT76_REMOVED, &dev->mt76.state))
@@ -116,7 +116,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)
goto out;
mt76x0_phy_calibrate(dev, true);
- ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mt76.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index cb5792b41d2d..8e17fbb6fd04 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -85,7 +85,6 @@ struct mt76x02_dev {
struct tasklet_struct tx_tasklet;
struct tasklet_struct pre_tbtt_tasklet;
struct delayed_work cal_work;
- struct delayed_work mac_work;
struct delayed_work wdt_work;
u32 aggr_stats[32];
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 8e5f920deef1..ef9432a12302 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -1032,7 +1032,7 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev)
void mt76x02_mac_work(struct work_struct *work)
{
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
- mac_work.work);
+ mt76.mac_work.work);
int i, idx;
mutex_lock(&dev->mt76.mutex);
@@ -1055,7 +1055,7 @@ void mt76x02_mac_work(struct work_struct *work)
mt76_tx_status_check(&dev->mt76, NULL, false);
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
MT_MAC_WORK_INTERVAL);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 079ac265ef26..d76544834420 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -132,7 +132,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
struct ieee80211_hw *hw = mt76_hw(dev);
struct wiphy *wiphy = hw->wiphy;
- INIT_DELAYED_WORK(&dev->mac_work, mt76x02_mac_work);
+ INIT_DELAYED_WORK(&dev->mt76.mac_work, mt76x02_mac_work);
hw->queues = 4;
hw->max_rates = 1;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
index d3927a13e92e..9661e9ba734d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
@@ -291,7 +291,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev)
void mt76x2_stop_hardware(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
- cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->wdt_work);
mt76x02_mcu_set_radio_state(dev, false);
mt76x2_mac_stop(dev, false);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index 878ce92405ed..ef42743364e4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -32,7 +32,7 @@ mt76x2_start(struct ieee80211_hw *hw)
if (ret)
goto out;
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
MT_WATCHDOG_TIME);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
index 1da90e58d942..4bfd958b4334 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
@@ -246,7 +246,7 @@ void mt76x2u_stop_hw(struct mt76x02_dev *dev)
{
mt76u_stop_stat_wk(&dev->mt76);
cancel_delayed_work_sync(&dev->cal_work);
- cancel_delayed_work_sync(&dev->mac_work);
+ cancel_delayed_work_sync(&dev->mt76.mac_work);
mt76x2u_mac_stop(dev);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index 2ac78e4dc41a..5f746c8df906 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -27,7 +27,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw)
if (ret)
goto out;
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
MT_MAC_WORK_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v2] iommu/amd: fix sg->dma_address for sg->offset bigger than PAGE_SIZE
From: Joerg Roedel @ 2019-03-18 10:17 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Alexander Duyck, Rosen Penev, Lorenzo Bianconi, linux-wireless,
Samuel Sieb, iommu, linux-kernel, linux-nvme, jan.viktorin
In-Reply-To: <20190313090316.GA2663@redhat.com>
Hi Stanislaw,
thanks a lot for looking into this and tracking it down!
On Wed, Mar 13, 2019 at 10:03:17AM +0100, Stanislaw Gruszka wrote:
> - s->dma_address += address + s->offset;
> + /* Add in the remaining piece of the scatter-gather offset that
> + * was masked out when we were determining the physical address
> + * via (sg_phys(s) & PAGE_MASK) earlier.
> + */
> + s->dma_address += address + (s->offset & ~PAGE_MASK);
> s->dma_length = s->length;
Applied the patch for v5.1 (with an added Fixes-tag and a minor coding
style change) and will send it upstream soon.
Thanks again,
Joerg
^ permalink raw reply
* Re: [PATCH 08/11] mt76x02u: implement pre TBTT work for USB
From: Stanislaw Gruszka @ 2019-03-18 10:03 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi
In-Reply-To: <541c8464-7422-5045-217c-420ca074b36d@nbd.name>
On Mon, Mar 18, 2019 at 10:57:47AM +0100, Felix Fietkau wrote:
> On 2019-03-18 10:50, Stanislaw Gruszka wrote:
> > On Sat, Mar 16, 2019 at 08:44:21PM +0100, Felix Fietkau wrote:
> >> On 2019-03-04 10:48, Stanislaw Gruszka wrote:
> >> > Program beacons data and PS buffered frames on TBTT work for USB.
> >> > We do not have MT_TXQ_PSD queue available via USB endpoints. The way
> >> > we can send PS broadcast frames in timely manner before PS stations go
> >> > sleep again is program them in beacon data area. Hardware do not modify
> >> > those frames since TXWI is properly configured. mt76x02_mac_set_beacon()
> >> > already handle this and free no longer used frames.
> >> >
> >> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> >> I think it's a nice idea, but there is one problem with that approach:
> >> beacon slots only have 1024 bytes for TXWI + data.
> >> I think to support this properly, you probably need to adjust beacon
> >> offsets for USB dynamically and limit the number of frames to what you
> >> can fit in SRAM.
> > That would be good since we could sent more buffered frames (ARP frames
> > are small), but for now I would prefer simpler solution to enable
> > AP support for USB: increase slot size to 1600 and make only 5 slots
> > available.
> Then you should probably limit the number of AP interfaces for USB as
> well. Otherwise, people are going to do crazy things like bring up 4
> virtual AP interfaces and expect multicast to work :)
Yes, sure, for now only one is allowed. Multi vifs for USB is on my
TODO list.
Stanislaw
^ permalink raw reply
* Re: [PATCH 08/11] mt76x02u: implement pre TBTT work for USB
From: Felix Fietkau @ 2019-03-18 9:57 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: linux-wireless, Lorenzo Bianconi
In-Reply-To: <20190318095014.GA3323@redhat.com>
On 2019-03-18 10:50, Stanislaw Gruszka wrote:
> On Sat, Mar 16, 2019 at 08:44:21PM +0100, Felix Fietkau wrote:
>> On 2019-03-04 10:48, Stanislaw Gruszka wrote:
>> > Program beacons data and PS buffered frames on TBTT work for USB.
>> > We do not have MT_TXQ_PSD queue available via USB endpoints. The way
>> > we can send PS broadcast frames in timely manner before PS stations go
>> > sleep again is program them in beacon data area. Hardware do not modify
>> > those frames since TXWI is properly configured. mt76x02_mac_set_beacon()
>> > already handle this and free no longer used frames.
>> >
>> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
>> I think it's a nice idea, but there is one problem with that approach:
>> beacon slots only have 1024 bytes for TXWI + data.
>> I think to support this properly, you probably need to adjust beacon
>> offsets for USB dynamically and limit the number of frames to what you
>> can fit in SRAM.
> That would be good since we could sent more buffered frames (ARP frames
> are small), but for now I would prefer simpler solution to enable
> AP support for USB: increase slot size to 1600 and make only 5 slots
> available.
Then you should probably limit the number of AP interfaces for USB as
well. Otherwise, people are going to do crazy things like bring up 4
virtual AP interfaces and expect multicast to work :)
- Felix
^ permalink raw reply
* Re: [PATCH 08/11] mt76x02u: implement pre TBTT work for USB
From: Stanislaw Gruszka @ 2019-03-18 9:50 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi
In-Reply-To: <5844c0b8-3db9-d985-da75-a11318df37c5@nbd.name>
On Sat, Mar 16, 2019 at 08:44:21PM +0100, Felix Fietkau wrote:
> On 2019-03-04 10:48, Stanislaw Gruszka wrote:
> > Program beacons data and PS buffered frames on TBTT work for USB.
> > We do not have MT_TXQ_PSD queue available via USB endpoints. The way
> > we can send PS broadcast frames in timely manner before PS stations go
> > sleep again is program them in beacon data area. Hardware do not modify
> > those frames since TXWI is properly configured. mt76x02_mac_set_beacon()
> > already handle this and free no longer used frames.
> >
> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> I think it's a nice idea, but there is one problem with that approach:
> beacon slots only have 1024 bytes for TXWI + data.
> I think to support this properly, you probably need to adjust beacon
> offsets for USB dynamically and limit the number of frames to what you
> can fit in SRAM.
That would be good since we could sent more buffered frames (ARP frames
are small), but for now I would prefer simpler solution to enable
AP support for USB: increase slot size to 1600 and make only 5 slots
available.
I assume we can not increase beacon SRAM area to more than 8kB.
Stanislaw
^ permalink raw reply
* Re: [PATCH v2] fq: fix fq_tin tx bytes overflow
From: Yibo Zhao @ 2019-03-18 4:59 UTC (permalink / raw)
To: Johannes Berg
Cc: ath10k, linux-wireless, Toke Høiland-Jørgensen,
linux-wireless-owner
In-Reply-To: <13392e1203be4ddd97c4e0e6b6a6c48ce97aae6f.camel@sipsolutions.net>
On 2019-03-15 17:38, Johannes Berg wrote:
> On Wed, 2019-03-13 at 11:08 +0800, Yibo Zhao wrote:
>> Currently, we are using u32 for tx_bytes in fq_tin.
>> If the throughput stays more than 1.2Gbps, tx_bytes
>> statistics overflow in about 1 min.
>>
>> In order to allow us to trace the tx_bytes statistics
>> for longer time in high throughput, change its type
>> from u32 to u64.
>
> Hmm. 64-bit values are kinda expensive on 32-bit architectures. How
> badly do you need this? I mean ... worst case you just have to capture
> every 30 seconds or so if you're doing really high throughput with HE
> or
> something?
>
> johannes
Hi Johannes,
I understand your concern. Yes, I am using high end AP for throughput
test. I'd say 1.2 Gbps is not the worst case since we can achieve max
1.4Gbps according to our test. AFAIK, for most throughput cases, 1min is
the minimum requirement. And I think, with more and more high end
products(even higher throughput) on the ways to the market, it is highly
possible that 30s is not a safe time before overflow.
--
Yibo
^ permalink raw reply
* Re: [PATCH 5/5] mac80211_hwsim: Ext Key ID support (NATIVE)
From: Johannes Berg @ 2019-03-17 22:38 UTC (permalink / raw)
To: Alexander Wetzel; +Cc: linux-wireless
In-Reply-To: <20190316204208.16497-6-alexander@wetzel-home.de>
Since I'm travelling to netdev and all, I'm not sure I'll actually get
around to this patchset soon.
On Sat, 2019-03-16 at 21:42 +0100, Alexander Wetzel wrote:
> Driver is not supporting hardware encryption and therefore fully
> compatible with Extended Key ID.
On this particular patch now reading this I'm wondering if we shouldn't
just do that in mac80211 if there's no set_key callback? I suspect
that'd affect a few drivers that are otherwise more or less orphaned.
johannes
^ permalink raw reply
* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Toke Høiland-Jørgensen @ 2019-03-17 21:59 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
In-Reply-To: <2cc1f1d4-f07e-faa0-ede7-95dd2917a64a@nbd.name>
Felix Fietkau <nbd@nbd.name> writes:
> On 2019-03-17 12:32, Toke Høiland-Jørgensen wrote:
>> Felix Fietkau <nbd@nbd.name> writes:
>>
>>> On 2019-03-16 23:28, Toke Høiland-Jørgensen wrote:
>>>> Felix Fietkau <nbd@nbd.name> writes:
>>>>
>>>>> Performance improvement and preparation for adding airtime fairness
>>>>> support
>>>>
>>>> Great to see this! Do you have a plan for the airtime fairness part?
>>>> I.e., how to get the airtime information?
>>> Not yet. Still need to investigate what kind of information the hardware
>>> can provide. On a first glance it seems rather limited, so we may have
>>> to approximate based on tx status rates/retry and average packet size.
>>
>> OK, cool. A byte-based estimator can also be useful for preventing dumb
>> firmware from buffering too much. The Chromium guys did that for ath10k:
>>
>> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/588190/13/drivers/net/wireless-4.2/ath/ath10k/mac.c#3826
> Interesting, thanks. I can probably use some ideas from that.
>
>>>> The call to ieee80211_return_txq() is really meant to be unconditional.
>>>> The TXQ will only actually be scheduled if it still has packets queued.
>>>> I know it's slightly more expensive to have the check in mac80211, but
>>>> this is what makes it possible to change the implementation without
>>>> touching the drivers (such as in the RFC patch I sent earlier that
>>>> switches the scheduling algorithm)...
>>> I think this API needs to be extended to allow the driver to specify
>>> that it has buffered packets for a txq. Otherwise there's a small window
>>> where the driver has packets for a txq but mac80211 doesn't, and
>>> mac80211 won't schedule the queue in that case.
>>> I'll send a patch for this soon.
>>
>> Right, makes sense. As long as mac80211 is in control over how it will
>> react to that information (thus allowing to e.g., invert the logic if
>> needed), I have no objections to extending the API... :)I'm thinking of changing the code to make ieee80211_schedule_txq add the
> txq to the list, even if mac80211 does not have any frames buffered for it.
>
> I've looked at ath9k (the only user at the moment), and it seems to call
> the function in that way already: at PS wake or tx status time if it has
> frames in its internal retry queue.
> While it does not match the current documented behavior for that
> function, it nicely fits ath9k's currently unfulfilled expectations ;)
Heh, fair point :)
-Toke
^ permalink raw reply
* Re: [PATCH v2] mac80211: make ieee80211_schedule_txq schedule empty TXQs
From: Toke Høiland-Jørgensen @ 2019-03-17 22:00 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: johannes
In-Reply-To: <20190317170251.71185-1-nbd@nbd.name>
Felix Fietkau <nbd@nbd.name> writes:
> Currently there is no way for the driver to signal to mac80211 that it should
> schedule a TXQ even if there are no packets on the mac80211 part of that queue.
> This is problematic if the driver has an internal retry queue to deal with
> software A-MPDU retry.
>
> This patch changes the behavior of ieee80211_schedule_txq to always schedule
> the queue, as its only user (ath9k) seems to expect such behavior already:
> it calls this function on tx status and on powersave wakeup whenever its
> internal retry queue is not empty
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
> include/net/mac80211.h | 17 ++++++++++++++---
> net/mac80211/tx.c | 10 ++++++----
> 2 files changed, 20 insertions(+), 7 deletions(-)
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index 0de0aba580eb..630941e5a20e 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -6291,15 +6291,26 @@ static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
> {
> }
>
> +void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
> + struct ieee80211_txq *txq, bool force);
> +
So are you planning to also change return_txq() to take the 'force'
argument and wrap __ieee80211_schedule_txq()? Since that was the context
we originally started discussing this :)
-Toke
^ permalink raw reply
* [PATCH] mac80211: optimize skb resizing
From: Felix Fietkau @ 2019-03-17 18:18 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
When forwarding unicast packets from ethernet to batman-adv over 802.11s
(with forwarding disabled), the typical required headroom to transmit
encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) +
2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes.
On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head
for every packet, since mac80211 also tries to allocate 16 bytes status
headroom for radiotap headers.
This patch fixes these unnecessary reallocations by only requiring the extra
status headroom in ieee80211_tx_monitor()
If however a reallocation happens before that call, the status headroom gets
added there as well, in order to avoid double reallocation.
The patch also cleans up the code by moving the headroom calculation to
ieee80211_skb_resize.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/status.c | 5 ++
net/mac80211/tx.c | 96 ++++++++++++++++----------------------
3 files changed, 48 insertions(+), 55 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5b2626ca0e44..a36bfa1b43a9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1779,6 +1779,8 @@ void ieee80211_clear_fast_xmit(struct sta_info *sta);
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len,
const u8 *dest, __be16 proto, bool unencrypted);
+int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int hdrlen, int hdr_add);
/* HT */
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 0af1c7a99d6c..1452011d7e91 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -670,6 +670,11 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
}
}
+ if (ieee80211_skb_resize(NULL, skb, 0, 0)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
/* send frame to monitor interfaces now */
rtap_len = ieee80211_tx_radiotap_len(info);
if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 72279fb318e0..e22de40a7790 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1939,37 +1939,53 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
}
/* device xmit handlers */
-
-static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb,
- int head_need, bool may_encrypt)
+int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int hdr_len, int hdr_extra)
{
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
- bool enc_tailroom;
- int tail_need = 0;
+ int head_need, head_max;
+ int tail_need, tail_max;
+ bool enc_tailroom = false;
- hdr = (struct ieee80211_hdr *) skb->data;
- enc_tailroom = may_encrypt &&
- (sdata->crypto_tx_tailroom_needed_cnt ||
- ieee80211_is_mgmt(hdr->frame_control));
-
- if (enc_tailroom) {
- tail_need = IEEE80211_ENCRYPT_TAILROOM;
- tail_need -= skb_tailroom(skb);
- tail_need = max_t(int, tail_need, 0);
+ if (sdata && !hdr_len &&
+ !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
+ hdr = (struct ieee80211_hdr *) skb->data;
+ enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt ||
+ ieee80211_is_mgmt(hdr->frame_control));
+ hdr_len += sdata->encrypt_headroom;
+ }
+
+ head_need = head_max = hdr_len;
+ tail_need = tail_max = 0;
+ if (!sdata) {
+ head_need = head_max = local->tx_headroom;
+ } else {
+ head_max += hdr_extra;
+ head_max += max_t(int, local->tx_headroom,
+ local->hw.extra_tx_headroom);
+ head_need += local->hw.extra_tx_headroom;
+
+ tail_max = IEEE80211_ENCRYPT_TAILROOM;
+ if (enc_tailroom)
+ tail_need = tail_max;
}
if (skb_cloned(skb) &&
(!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
!skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
- else if (head_need || tail_need)
+ else if (head_need > skb_headroom(skb) ||
+ tail_need > skb_tailroom(skb))
I802_DEBUG_INC(local->tx_expand_skb_head);
else
return 0;
- if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
+ head_max = max_t(int, 0, head_max - skb_headroom(skb));
+ tail_max = max_t(int, 0, tail_max - skb_tailroom(skb));
+
+ if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) {
wiphy_debug(local->hw.wiphy,
"failed to reallocate TX buffer\n");
return -ENOMEM;
@@ -1985,18 +2001,8 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
- int headroom;
- bool may_encrypt;
-
- may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
- headroom = local->tx_headroom;
- if (may_encrypt)
- headroom += sdata->encrypt_headroom;
- headroom -= skb_headroom(skb);
- headroom = max_t(int, 0, headroom);
-
- if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
+ if (ieee80211_skb_resize(sdata, skb, 0, 0)) {
ieee80211_free_txskb(&local->hw, skb);
return;
}
@@ -2765,30 +2771,14 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
skb_pull(skb, skip_header_bytes);
padsize = ieee80211_hdr_padsize(&local->hw, hdrlen);
- head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
+ head_need = hdrlen + encaps_len + meshhdrlen;
head_need += padsize;
- /*
- * So we need to modify the skb header and hence need a copy of
- * that. The head_need variable above doesn't, so far, include
- * the needed header space that we don't need right away. If we
- * can, then we don't reallocate right now but only after the
- * frame arrives at the master device (if it does...)
- *
- * If we cannot, however, then we will reallocate to include all
- * the ever needed space. Also, if we need to reallocate it anyway,
- * make it big enough for everything we may ever need.
- */
-
- if (head_need > 0 || skb_cloned(skb)) {
- head_need += sdata->encrypt_headroom;
- head_need += local->tx_headroom;
- head_need = max_t(int, 0, head_need);
- if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
- ieee80211_free_txskb(&local->hw, skb);
- skb = NULL;
- return ERR_PTR(-ENOMEM);
- }
+ if (ieee80211_skb_resize(sdata, skb, head_need,
+ sdata->encrypt_headroom)) {
+ ieee80211_free_txskb(&local->hw, skb);
+ skb = NULL;
+ return ERR_PTR(-ENOMEM);
}
if (encaps_data)
@@ -3414,7 +3404,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
u16 ethertype = (skb->data[12] << 8) | skb->data[13];
int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
- int hw_headroom = sdata->local->hw.extra_tx_headroom;
struct ethhdr eth;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
@@ -3466,10 +3455,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
* as the may-encrypt argument for the resize to not account for
* more room than we already have in 'extra_head'
*/
- if (unlikely(ieee80211_skb_resize(sdata, skb,
- max_t(int, extra_head + hw_headroom -
- skb_headroom(skb), 0),
- false))) {
+ if (unlikely(ieee80211_skb_resize(sdata, skb, extra_head, 0))) {
kfree_skb(skb);
return true;
}
--
2.17.0
^ permalink raw reply related
* [PATCH v2] mac80211: make ieee80211_schedule_txq schedule empty TXQs
From: Felix Fietkau @ 2019-03-17 17:02 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, Toke Høiland-Jørgensen
Currently there is no way for the driver to signal to mac80211 that it should
schedule a TXQ even if there are no packets on the mac80211 part of that queue.
This is problematic if the driver has an internal retry queue to deal with
software A-MPDU retry.
This patch changes the behavior of ieee80211_schedule_txq to always schedule
the queue, as its only user (ath9k) seems to expect such behavior already:
it calls this function on tx status and on powersave wakeup whenever its
internal retry queue is not empty
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/mac80211.h | 17 ++++++++++++++---
net/mac80211/tx.c | 10 ++++++----
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0de0aba580eb..630941e5a20e 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6291,15 +6291,26 @@ static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
{
}
+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq, bool force);
+
/**
* ieee80211_schedule_txq - schedule a TXQ for transmission
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @txq: pointer obtained from station or virtual interface
*
- * Schedules a TXQ for transmission if it is not already scheduled.
+ * Schedules a TXQ for transmission if it is not already scheduled,
+ * even if mac80211 does not have any packets buffered.
+ *
+ * The driver may call this function if it has buffered packets for
+ * this TXQ internally.
*/
-void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
+static inline void
+ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
+{
+ __ieee80211_schedule_txq(hw, txq, true);
+}
/**
* ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
@@ -6310,7 +6321,7 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
static inline void
ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
{
- ieee80211_schedule_txq(hw, txq);
+ __ieee80211_schedule_txq(hw, txq, false);
}
/**
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index f85344c9af62..72279fb318e0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3706,8 +3706,9 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
}
EXPORT_SYMBOL(ieee80211_next_txq);
-void ieee80211_schedule_txq(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq,
+ bool force)
{
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = to_txq_info(txq);
@@ -3715,7 +3716,8 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw,
spin_lock_bh(&local->active_txq_lock[txq->ac]);
if (list_empty(&txqi->schedule_order) &&
- (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
+ (force || !skb_queue_empty(&txqi->frags) ||
+ txqi->tin.backlog_packets)) {
/* If airtime accounting is active, always enqueue STAs at the
* head of the list to ensure that they only get moved to the
* back by the airtime DRR scheduler once they have a negative
@@ -3735,7 +3737,7 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw,
spin_unlock_bh(&local->active_txq_lock[txq->ac]);
}
-EXPORT_SYMBOL(ieee80211_schedule_txq);
+EXPORT_SYMBOL(__ieee80211_schedule_txq);
bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
--
2.17.0
^ permalink raw reply related
* Re: [PATCH] mac80211: make ieee80211_schedule_txq schedule empty TXQs
From: Felix Fietkau @ 2019-03-17 14:43 UTC (permalink / raw)
To: linux-wireless; +Cc: Toke Høiland-Jørgensen, johannes
In-Reply-To: <20190317135010.19198-1-nbd@nbd.name>
On 2019-03-17 14:50, Felix Fietkau wrote:
> Currently there is no way for the driver to signal to mac80211 that it should
> schedule a TXQ even if there are no packets on the mac80211 part of that queue.
> This is problematic if the driver has an internal retry queue to deal with
> software A-MPDU retry.
>
> This patch changes the behavior of ieee80211_schedule_txq to always schedule
> the queue, as its only user (ath9k) seems to expect such behavior already:
> it calls this function on tx status and on powersave wakeup whenever its
> internal retry queue is not empty
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Sorry, missing a chunk that renames the EXPORT_SYMBOL as well.
Will send v2.
- Felix
^ permalink raw reply
* [PATCH] mac80211: make ieee80211_schedule_txq schedule empty TXQs
From: Felix Fietkau @ 2019-03-17 13:50 UTC (permalink / raw)
To: linux-wireless; +Cc: Toke Høiland-Jørgensen, johannes
Currently there is no way for the driver to signal to mac80211 that it should
schedule a TXQ even if there are no packets on the mac80211 part of that queue.
This is problematic if the driver has an internal retry queue to deal with
software A-MPDU retry.
This patch changes the behavior of ieee80211_schedule_txq to always schedule
the queue, as its only user (ath9k) seems to expect such behavior already:
it calls this function on tx status and on powersave wakeup whenever its
internal retry queue is not empty
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/mac80211.h | 17 ++++++++++++++---
net/mac80211/tx.c | 8 +++++---
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0de0aba580eb..630941e5a20e 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6291,15 +6291,26 @@ static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
{
}
+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq, bool force);
+
/**
* ieee80211_schedule_txq - schedule a TXQ for transmission
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @txq: pointer obtained from station or virtual interface
*
- * Schedules a TXQ for transmission if it is not already scheduled.
+ * Schedules a TXQ for transmission if it is not already scheduled,
+ * even if mac80211 does not have any packets buffered.
+ *
+ * The driver may call this function if it has buffered packets for
+ * this TXQ internally.
*/
-void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
+static inline void
+ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
+{
+ __ieee80211_schedule_txq(hw, txq, true);
+}
/**
* ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
@@ -6310,7 +6321,7 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
static inline void
ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
{
- ieee80211_schedule_txq(hw, txq);
+ __ieee80211_schedule_txq(hw, txq, false);
}
/**
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index f85344c9af62..8b6e4f609d5c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3706,8 +3706,9 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
}
EXPORT_SYMBOL(ieee80211_next_txq);
-void ieee80211_schedule_txq(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq,
+ bool force)
{
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = to_txq_info(txq);
@@ -3715,7 +3716,8 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw,
spin_lock_bh(&local->active_txq_lock[txq->ac]);
if (list_empty(&txqi->schedule_order) &&
- (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
+ (force || !skb_queue_empty(&txqi->frags) ||
+ txqi->tin.backlog_packets)) {
/* If airtime accounting is active, always enqueue STAs at the
* head of the list to ensure that they only get moved to the
* back by the airtime DRR scheduler once they have a negative
--
2.17.0
^ permalink raw reply related
* Re: [PATCH] mt76: Use the correct hweight8() function again
From: Felix Fietkau @ 2019-03-17 13:01 UTC (permalink / raw)
To: Masahiro Yamada, linux-wireless
Cc: Ben Hutchings, Kalle Valo, David S. Miller, netdev, linux-kernel,
Lorenzo Bianconi, linux-mediatek, linux-arm-kernel,
Matthias Brugger
In-Reply-To: <1552789948-31564-1-git-send-email-yamada.masahiro@socionext.com>
On 2019-03-17 03:32, Masahiro Yamada wrote:
> Commit d0ff23c1107e ("mt76: Use the correct hweight8() function")
> fixed the wrong use of __sw_hweight8().
>
> Just a week later, commit c8846e101502 ("mt76: add driver for MT7603E
> and MT7628/7688") was applid, introducing __sw_hweight8() again.
>
> Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
I've already sent the same patch to Kalle for 5.1 about a week ago.
- Felix
^ permalink raw reply
* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Felix Fietkau @ 2019-03-17 12:32 UTC (permalink / raw)
To: Toke Høiland-Jørgensen, linux-wireless
In-Reply-To: <875zshviqg.fsf@toke.dk>
On 2019-03-17 12:32, Toke Høiland-Jørgensen wrote:
> Felix Fietkau <nbd@nbd.name> writes:
>
>> On 2019-03-16 23:28, Toke Høiland-Jørgensen wrote:
>>> Felix Fietkau <nbd@nbd.name> writes:
>>>
>>>> Performance improvement and preparation for adding airtime fairness
>>>> support
>>>
>>> Great to see this! Do you have a plan for the airtime fairness part?
>>> I.e., how to get the airtime information?
>> Not yet. Still need to investigate what kind of information the hardware
>> can provide. On a first glance it seems rather limited, so we may have
>> to approximate based on tx status rates/retry and average packet size.
>
> OK, cool. A byte-based estimator can also be useful for preventing dumb
> firmware from buffering too much. The Chromium guys did that for ath10k:
>
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/588190/13/drivers/net/wireless-4.2/ath/ath10k/mac.c#3826
Interesting, thanks. I can probably use some ideas from that.
>>> The call to ieee80211_return_txq() is really meant to be unconditional.
>>> The TXQ will only actually be scheduled if it still has packets queued.
>>> I know it's slightly more expensive to have the check in mac80211, but
>>> this is what makes it possible to change the implementation without
>>> touching the drivers (such as in the RFC patch I sent earlier that
>>> switches the scheduling algorithm)...
>> I think this API needs to be extended to allow the driver to specify
>> that it has buffered packets for a txq. Otherwise there's a small window
>> where the driver has packets for a txq but mac80211 doesn't, and
>> mac80211 won't schedule the queue in that case.
>> I'll send a patch for this soon.
>
> Right, makes sense. As long as mac80211 is in control over how it will
> react to that information (thus allowing to e.g., invert the logic if
> needed), I have no objections to extending the API... :)I'm thinking of changing the code to make ieee80211_schedule_txq add the
txq to the list, even if mac80211 does not have any frames buffered for it.
I've looked at ath9k (the only user at the moment), and it seems to call
the function in that way already: at PS wake or tx status time if it has
frames in its internal retry queue.
While it does not match the current documented behavior for that
function, it nicely fits ath9k's currently unfulfilled expectations ;)
- Felix
^ permalink raw reply
* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Toke Høiland-Jørgensen @ 2019-03-17 11:32 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
In-Reply-To: <7b9a0a24-14b0-9b96-0010-ce9f96308ad0@nbd.name>
Felix Fietkau <nbd@nbd.name> writes:
> On 2019-03-16 23:28, Toke Høiland-Jørgensen wrote:
>> Felix Fietkau <nbd@nbd.name> writes:
>>
>>> Performance improvement and preparation for adding airtime fairness
>>> support
>>
>> Great to see this! Do you have a plan for the airtime fairness part?
>> I.e., how to get the airtime information?
> Not yet. Still need to investigate what kind of information the hardware
> can provide. On a first glance it seems rather limited, so we may have
> to approximate based on tx status rates/retry and average packet size.
OK, cool. A byte-based estimator can also be useful for preventing dumb
firmware from buffering too much. The Chromium guys did that for ath10k:
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/588190/13/drivers/net/wireless-4.2/ath/ath10k/mac.c#3826
>> The call to ieee80211_return_txq() is really meant to be unconditional.
>> The TXQ will only actually be scheduled if it still has packets queued.
>> I know it's slightly more expensive to have the check in mac80211, but
>> this is what makes it possible to change the implementation without
>> touching the drivers (such as in the RFC patch I sent earlier that
>> switches the scheduling algorithm)...
> I think this API needs to be extended to allow the driver to specify
> that it has buffered packets for a txq. Otherwise there's a small window
> where the driver has packets for a txq but mac80211 doesn't, and
> mac80211 won't schedule the queue in that case.
> I'll send a patch for this soon.
Right, makes sense. As long as mac80211 is in control over how it will
react to that information (thus allowing to e.g., invert the logic if
needed), I have no objections to extending the API... :)
-Toke
^ permalink raw reply
* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Felix Fietkau @ 2019-03-17 10:44 UTC (permalink / raw)
To: Toke Høiland-Jørgensen, linux-wireless
In-Reply-To: <87muluv4hd.fsf@toke.dk>
On 2019-03-16 23:28, Toke Høiland-Jørgensen wrote:
> Felix Fietkau <nbd@nbd.name> writes:
>
>> Performance improvement and preparation for adding airtime fairness
>> support
>
> Great to see this! Do you have a plan for the airtime fairness part?
> I.e., how to get the airtime information?
Not yet. Still need to investigate what kind of information the hardware
can provide. On a first glance it seems rather limited, so we may have
to approximate based on tx status rates/retry and average packet size.
> The call to ieee80211_return_txq() is really meant to be unconditional.
> The TXQ will only actually be scheduled if it still has packets queued.
> I know it's slightly more expensive to have the check in mac80211, but
> this is what makes it possible to change the implementation without
> touching the drivers (such as in the RFC patch I sent earlier that
> switches the scheduling algorithm)...
I think this API needs to be extended to allow the driver to specify
that it has buffered packets for a txq. Otherwise there's a small window
where the driver has packets for a txq but mac80211 doesn't, and
mac80211 won't schedule the queue in that case.
I'll send a patch for this soon.
- Felix
^ permalink raw reply
* [PATCH] mt76: Use the correct hweight8() function again
From: Masahiro Yamada @ 2019-03-17 2:32 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
Cc: Ben Hutchings, Kalle Valo, Masahiro Yamada, David S. Miller,
netdev, linux-kernel, Lorenzo Bianconi, linux-mediatek,
linux-arm-kernel, Matthias Brugger
Commit d0ff23c1107e ("mt76: Use the correct hweight8() function")
fixed the wrong use of __sw_hweight8().
Just a week later, commit c8846e101502 ("mt76: add driver for MT7603E
and MT7628/7688") was applid, introducing __sw_hweight8() again.
Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
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 afcd86f..4dcb465 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 15cc8f3..d54dda6 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 4b0713f..d06905e 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.7.4
^ permalink raw reply related
* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Toke Høiland-Jørgensen @ 2019-03-16 22:28 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
In-Reply-To: <20190316204242.73560-1-nbd@nbd.name>
Felix Fietkau <nbd@nbd.name> writes:
> Performance improvement and preparation for adding airtime fairness
> support
Great to see this! Do you have a plan for the airtime fairness part?
I.e., how to get the airtime information?
Only one other comment, below.
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
> drivers/net/wireless/mediatek/mt76/dma.c | 6 +-
> drivers/net/wireless/mediatek/mt76/mt76.h | 3 +-
> drivers/net/wireless/mediatek/mt76/tx.c | 98 ++++++++++-------------
> drivers/net/wireless/mediatek/mt76/usb.c | 3 +-
> 4 files changed, 50 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> index 7b8a998103d7..09978757e7d1 100644
> --- a/drivers/net/wireless/mediatek/mt76/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> @@ -184,9 +184,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
> last = ioread32(&q->regs->dma_idx);
> }
>
> - if (!flush)
> - mt76_txq_schedule(dev, sq);
> - else
> + if (flush)
> mt76_dma_sync_idx(dev, q);
>
> wake = wake && q->stopped &&
> @@ -199,6 +197,8 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)
>
> spin_unlock_bh(&q->lock);
>
> + if (!flush)
> + mt76_txq_schedule(dev, qid);
> if (wake)
> ieee80211_wake_queue(dev->hw, qid);
> }
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index edff44f32c8e..5d44f721d184 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -224,7 +224,6 @@ struct mt76_wcid {
> };
>
> struct mt76_txq {
> - struct list_head list;
> struct mt76_sw_queue *swq;
> struct mt76_wcid *wcid;
>
> @@ -683,7 +682,7 @@ void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq);
> void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
> void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta,
> bool send_bar);
> -void mt76_txq_schedule(struct mt76_dev *dev, struct mt76_sw_queue *sq);
> +void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid);
> void mt76_txq_schedule_all(struct mt76_dev *dev);
> void mt76_release_buffered_frames(struct ieee80211_hw *hw,
> struct ieee80211_sta *sta,
> diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
> index 2c82db0b5834..ef9a0bbd64c1 100644
> --- a/drivers/net/wireless/mediatek/mt76/tx.c
> +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> @@ -479,23 +479,37 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq,
> }
>
> static int
> -mt76_txq_schedule_list(struct mt76_dev *dev, struct mt76_sw_queue *sq)
> +mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid)
> {
> + struct mt76_sw_queue *sq = &dev->q_tx[qid];
> struct mt76_queue *hwq = sq->q;
> - struct mt76_txq *mtxq, *mtxq_last;
> - int len = 0;
> + struct ieee80211_txq *txq;
> + struct mt76_txq *mtxq;
> + struct mt76_wcid *wcid;
> + int ret = 0;
>
> -restart:
> - mtxq_last = list_last_entry(&sq->swq, struct mt76_txq, list);
> - while (!list_empty(&sq->swq)) {
> + spin_lock_bh(&hwq->lock);
> + while (1) {
> bool empty = false;
> - int cur;
> +
> + if (sq->swq_queued >= 4)
> + break;
>
> if (test_bit(MT76_OFFCHANNEL, &dev->state) ||
> - test_bit(MT76_RESET, &dev->state))
> - return -EBUSY;
> + test_bit(MT76_RESET, &dev->state)) {
> + ret = -EBUSY;
> + break;
> + }
> +
> + txq = ieee80211_next_txq(dev->hw, qid);
> + if (!txq)
> + break;
> +
> + mtxq = (struct mt76_txq *)txq->drv_priv;
> + wcid = mtxq->wcid;
> + if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags))
> + continue;
>
> - mtxq = list_first_entry(&sq->swq, struct mt76_txq, list);
> if (mtxq->send_bar && mtxq->aggr) {
> struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
> struct ieee80211_sta *sta = txq->sta;
> @@ -507,38 +521,36 @@ mt76_txq_schedule_list(struct mt76_dev *dev, struct mt76_sw_queue *sq)
> spin_unlock_bh(&hwq->lock);
> ieee80211_send_bar(vif, sta->addr, tid, agg_ssn);
> spin_lock_bh(&hwq->lock);
> - goto restart;
> }
>
> - list_del_init(&mtxq->list);
> -
> - cur = mt76_txq_send_burst(dev, sq, mtxq, &empty);
> + ret += mt76_txq_send_burst(dev, sq, mtxq, &empty);
> if (!empty)
> - list_add_tail(&mtxq->list, &sq->swq);
> -
> - if (cur < 0)
> - return cur;
> -
> - len += cur;
> -
> - if (mtxq == mtxq_last)
> - break;
> + ieee80211_return_txq(dev->hw, txq);
The call to ieee80211_return_txq() is really meant to be unconditional.
The TXQ will only actually be scheduled if it still has packets queued.
I know it's slightly more expensive to have the check in mac80211, but
this is what makes it possible to change the implementation without
touching the drivers (such as in the RFC patch I sent earlier that
switches the scheduling algorithm)...
-Toke
^ permalink raw reply
* [PATCH] mac80211: Optimize tailroom_needed update checks
From: Alexander Wetzel @ 2019-03-16 20:44 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
Optimize/cleanup the delay tailroom checks and adds one missing tailroom
update.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
net/mac80211/key.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 37e372896230..b9f2bfc00263 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -140,6 +140,12 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
* so clear that flag now to avoid trying to remove
* it again later.
*/
+ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
+ !(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ increment_tailroom_need_count(sdata);
+
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
return -EINVAL;
}
@@ -179,9 +185,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
if (!ret) {
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
- if (!((key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE)) ||
- (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
decrease_tailroom_need_count(sdata, 1);
WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
@@ -242,9 +248,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta = key->sta;
sdata = key->sdata;
- if (!((key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE)) ||
- (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
increment_tailroom_need_count(sdata);
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
@@ -1187,9 +1193,9 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
- if (!((key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE)) ||
- (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
increment_tailroom_need_count(key->sdata);
}
--
2.21.0
^ permalink raw reply related
* [PATCH 1/5] nl80211/cfg80211: Extended Key ID support
From: Alexander Wetzel @ 2019-03-16 20:42 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190316204208.16497-1-alexander@wetzel-home.de>
Add support for IEEE 802.11-2016 "Extended Key ID for Individually
Addressed Frames".
Extend cfg80211 and nl80211 to allow pairwise keys to be installed for
Rx only, enable Tx separately and allow Key ID 1 for pairwise keys.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 28 ++++++++++++++++++++++++++++
net/wireless/nl80211.c | 32 ++++++++++++++++++++++++++++----
net/wireless/rdev-ops.h | 3 ++-
net/wireless/trace.h | 31 ++++++++++++++++++++++++++-----
net/wireless/util.c | 21 +++++++++++++++------
6 files changed, 101 insertions(+), 16 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bb307a11ee63..d89053de2fbb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -485,6 +485,7 @@ struct vif_params {
* with the get_key() callback, must be in little endian,
* length given by @seq_len.
* @seq_len: length of @seq.
+ * @mode: key install mode (RX_TX, NO_TX or SET_TX)
*/
struct key_params {
const u8 *key;
@@ -492,6 +493,7 @@ struct key_params {
int key_len;
int seq_len;
u32 cipher;
+ enum nl80211_key_mode mode;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index dd4f86ee286e..098534d8a573 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4134,6 +4134,27 @@ enum nl80211_channel_type {
NL80211_CHAN_HT40PLUS
};
+/**
+ * enum nl80211_key_mode - Key mode
+ *
+ * @NL80211_KEY_RX_TX: (Default)
+ * Key can be used for Rx and Tx immediately
+ *
+ * The following modes can only be selected for unicast keys and when the
+ * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID:
+ *
+ * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY:
+ * Unicast key can only be used for Rx, Tx not allowed, yet
+ * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY:
+ * The unicast key identified by idx and mac is cleared for Tx and becomes
+ * the preferred Tx key for the station.
+ */
+enum nl80211_key_mode {
+ NL80211_KEY_RX_TX,
+ NL80211_KEY_NO_TX,
+ NL80211_KEY_SET_TX
+};
+
/**
* enum nl80211_chan_width - channel width definitions
*
@@ -4377,6 +4398,9 @@ enum nl80211_key_default_types {
* @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
* attributes, specifying what a key should be set as default as.
* See &enum nl80211_key_default_types.
+ * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode.
+ * Defaults to @NL80211_KEY_RX_TX.
+ *
* @__NL80211_KEY_AFTER_LAST: internal
* @NL80211_KEY_MAX: highest key attribute
*/
@@ -4390,6 +4414,7 @@ enum nl80211_key_attributes {
NL80211_KEY_DEFAULT_MGMT,
NL80211_KEY_TYPE,
NL80211_KEY_DEFAULT_TYPES,
+ NL80211_KEY_MODE,
/* keep last */
__NL80211_KEY_AFTER_LAST,
@@ -5335,6 +5360,8 @@ enum nl80211_feature_flags {
* able to rekey an in-use key correctly. Userspace must not rekey PTK keys
* if this flag is not set. Ignoring this can leak clear text packets and/or
* freeze the connection.
+ * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for
+ * Individually Addressed Frames" from IEEE802.11-2016.
*
* @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime
* fairness for transmitted packets and has enabled airtime fairness
@@ -5384,6 +5411,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+ NL80211_EXT_FEATURE_EXT_KEY_ID,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25a9e3b5c154..4167dcdf516e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -553,6 +553,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
[NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
[NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
+ [NL80211_KEY_MODE] = { .type = NLA_U8 },
};
/* policy for the key default flags */
@@ -958,6 +959,9 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
}
+ if (tb[NL80211_KEY_MODE])
+ k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
+
return 0;
}
@@ -3634,8 +3638,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
if (key.idx < 0)
return -EINVAL;
- /* only support setting default key */
- if (!key.def && !key.defmgmt)
+ /* Only support setting default key and
+ * Extended Key ID action NL80211_KEY_SET_TX.
+ */
+ if (!key.def && !key.defmgmt &&
+ !(key.p.mode == NL80211_KEY_SET_TX))
return -EINVAL;
wdev_lock(dev->ieee80211_ptr);
@@ -3659,7 +3666,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
dev->ieee80211_ptr->wext.default_key = key.idx;
#endif
- } else {
+ } else if (key.defmgmt) {
if (key.def_uni || !key.def_multi) {
err = -EINVAL;
goto out;
@@ -3681,8 +3688,25 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
#endif
- }
+ } else if (key.p.mode == NL80211_KEY_SET_TX &&
+ wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID)) {
+ u8 *mac_addr = NULL;
+ if (info->attrs[NL80211_ATTR_MAC])
+ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+ if (!mac_addr || key.idx < 0 || key.idx > 1) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = rdev_add_key(rdev, dev, key.idx,
+ NL80211_KEYTYPE_PAIRWISE,
+ mac_addr, &key.p);
+ } else {
+ err = -EINVAL;
+ }
out:
wdev_unlock(dev->ieee80211_ptr);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 5cb48d135fab..5044e634a455 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -77,7 +77,8 @@ static inline int rdev_add_key(struct cfg80211_registered_device *rdev,
struct key_params *params)
{
int ret;
- trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+ trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise,
+ mac_addr, params->mode);
ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise,
mac_addr, params);
trace_rdev_return_int(&rdev->wiphy, ret);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 44b2ce1bb13a..0876f3eb3b3b 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -430,22 +430,43 @@ DECLARE_EVENT_CLASS(key_handle,
BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
);
-DEFINE_EVENT(key_handle, rdev_add_key,
+DEFINE_EVENT(key_handle, rdev_get_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
bool pairwise, const u8 *mac_addr),
TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
);
-DEFINE_EVENT(key_handle, rdev_get_key,
+DEFINE_EVENT(key_handle, rdev_del_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
bool pairwise, const u8 *mac_addr),
TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
);
-DEFINE_EVENT(key_handle, rdev_del_key,
+TRACE_EVENT(rdev_add_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
- bool pairwise, const u8 *mac_addr),
- TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+ bool pairwise, const u8 *mac_addr, u8 mode),
+ TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr, mode),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(mac_addr)
+ __field(u8, key_index)
+ __field(bool, pairwise)
+ __field(u8, mode)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(mac_addr, mac_addr);
+ __entry->key_index = key_index;
+ __entry->pairwise = pairwise;
+ __entry->mode = mode;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, "
+ "mode: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
+ __entry->mode, BOOL_TO_STR(__entry->pairwise),
+ MAC_PR_ARG(mac_addr))
);
TRACE_EVENT(rdev_set_default_key,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index e4b8db5e81ec..6c02c9cf7aa9 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -237,14 +237,23 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- /* Disallow pairwise keys with non-zero index unless it's WEP
- * or a vendor specific cipher (because current deployments use
- * pairwise WEP keys with non-zero indices and for vendor
- * specific ciphers this should be validated in the driver or
- * hardware level - but 802.11i clearly specifies to use zero)
+ /* IEEE802.11-2016 allows only 0 and - when using Extended Key
+ * ID - 1 as index for pairwise keys.
+ * @NL80211_KEY_NO_TX is only allowed for pairwise keys when
+ * the driver supports Extended Key ID.
+ * @NL80211_KEY_SET_TX can't be set when installing and
+ * validating a key.
*/
- if (pairwise && key_idx)
+ if (params->mode == NL80211_KEY_NO_TX) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID))
+ return -EINVAL;
+ else if (!pairwise || key_idx < 0 || key_idx > 1)
+ return -EINVAL;
+ } else if ((pairwise && key_idx) ||
+ params->mode == NL80211_KEY_SET_TX) {
return -EINVAL;
+ }
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
--
2.21.0
^ permalink raw reply related
* [PATCH 4/5] mac80211: Mark A-MPDU keyid borders for drivers
From: Alexander Wetzel @ 2019-03-16 20:42 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190316204208.16497-1-alexander@wetzel-home.de>
IEEE 802.11-2016 "9.7.3 A-MPDU contents" forbids aggregating MPDUs with
different keyids. Without Extended Key ID support this can't happen,
since we only aggregate unicast frames using either no key or key ID 0.
Extended Key ID support can also use key ID 1 for unicast frames and a
rekey with A-MPDU active will therefore need special handling to not
violate the above requirement.
To support drivers handling the key ID borders in A-MPDUs mac80211 will
set the new @IEEE80211_TX_CTRL_AMPDU_FLUSH flag for the last MPDU using
the current keyid. Drivers should then aggregate the MPDU and send out
all A-MPDUs with one or more MPDUs aggregated for all affected TIDs
immediately.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
Bugs fixed compared to last RFC patch:
- Initial key install is directly used for Tx (last RFC patch hung for
10s).
- Always activating Rx accel for correct key in COMPAT mode.
include/net/mac80211.h | 4 +++
net/mac80211/key.c | 21 ++++++++++++---
net/mac80211/sta_info.c | 1 +
net/mac80211/sta_info.h | 4 ++-
net/mac80211/tx.c | 60 +++++++++++++++++++++++++++++++++++------
5 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 63bd3d5aa707..922239a451c0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -807,6 +807,9 @@ enum mac80211_tx_info_flags {
* @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
* @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
* @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
+ * @IEEE80211_TX_CTRL_AMPDU_FLUSH: This frame is the last one allowed to be
+ * aggregated with previous frames to an A-MPDU. Driver has to flush all
+ * running A-MPDU aggreagations (TIDs) for sta.
*
* These flags are used in tx_info->control.flags.
*/
@@ -816,6 +819,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
IEEE80211_TX_CTRL_AMSDU = BIT(3),
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
+ IEEE80211_TX_CTRL_AMPDU_FLUSH = BIT(5),
};
/*
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index bd38167916ad..c174f102f72b 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -294,9 +294,17 @@ int ieee80211_set_tx_key(struct ieee80211_key *key)
assert_key_lock(local);
+ /* Two key activations must not overlap */
+ if (WARN_ON(sta->ptk_idx_next != INVALID_PTK_KEYIDX))
+ return -EOPNOTSUPP;
+
old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
- sta->ptk_idx = key->conf.keyidx;
- ieee80211_check_fast_xmit(sta);
+
+ /* The initial key still must be used immediately */
+ if (sta->ptk_idx == INVALID_PTK_KEYIDX)
+ sta->ptk_idx = key->conf.keyidx;
+ else
+ sta->ptk_idx_next = key->conf.keyidx;
if (ieee80211_hw_check(&local->hw, EXT_KEY_ID_COMPAT) &&
key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
@@ -1102,13 +1110,20 @@ void delayed_rx_accel_work(struct work_struct *wk)
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_key *key;
+ int keyid;
sta = container_of(wk, struct sta_info, delayed_rx_accel_wk);
local = sta->local;
sdata = sta->sdata;
+ /* sta->ptk_idx_next is the new key if not set to INVALID_PTK_KEYIDX */
+ if (sta->ptk_idx_next != INVALID_PTK_KEYIDX)
+ keyid = sta->ptk_idx_next;
+ else
+ keyid = sta->ptk_idx;
+
mutex_lock(&local->key_mtx);
- key = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
+ key = key_mtx_dereference(local, sta->ptk[keyid]);
drv_set_key(local, ENABLE_KEY_RX, sdata, &sta->sta, &key->conf);
mutex_unlock(&local->key_mtx);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 41ea1d05a946..7aa85cc7a667 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -357,6 +357,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
*/
BUILD_BUG_ON(ARRAY_SIZE(sta->ptk) <= INVALID_PTK_KEYIDX);
sta->ptk_idx = INVALID_PTK_KEYIDX;
+ sta->ptk_idx_next = INVALID_PTK_KEYIDX;
sta->local = local;
sta->sdata = sdata;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 45f7cbfe9698..271c0075f4e2 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -449,7 +449,8 @@ struct ieee80211_sta_rx_stats {
* @local: pointer to the global information
* @sdata: virtual interface this station belongs to
* @ptk: peer keys negotiated with this station, if any
- * @ptk_idx: last installed peer key index
+ * @ptk_idx: activated peer key index
+ * @ptk_idx_next: peer key index in activation (Extended Key ID only)
* @delayed_rx_accel_wk: Used to activate Rx crypto offload only after
* we have seen one MPDU encrypted with the key.
* @gtk: group keys negotiated with this station, if any
@@ -534,6 +535,7 @@ struct sta_info {
struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
struct work_struct delayed_rx_accel_wk;
u8 ptk_idx;
+ u8 ptk_idx_next;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
spinlock_t rate_ctrl_lock;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 111bd6c490a6..c3ea5107d8f9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -586,6 +586,47 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}
+static struct ieee80211_key debug_noinline
+*ieee80211_select_sta_key(struct ieee80211_tx_data *tx)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+ struct sta_info *sta = tx->sta;
+ struct ieee80211_key *key;
+ struct ieee80211_key *next_key;
+
+ key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]);
+
+ if (likely(sta->ptk_idx_next == INVALID_PTK_KEYIDX))
+ return key;
+
+ /* Only when using Extended Key ID the code below can be executed */
+
+ if (!ieee80211_is_data_present(hdr->frame_control))
+ return key;
+
+ if (sta->ptk_idx_next == sta->ptk_idx) {
+ /* First packet using new key with A-MPDU active */
+ sta->ptk_idx_next = INVALID_PTK_KEYIDX;
+ ieee80211_check_fast_xmit(tx->sta);
+ return key;
+ }
+
+ next_key = rcu_dereference(sta->ptk[sta->ptk_idx_next]);
+ sta->ptk_idx = sta->ptk_idx_next;
+
+ if (key && info->flags & IEEE80211_TX_CTL_AMPDU) {
+ /* Last packet with old key with A-MPDU active */
+ info->control.flags |= IEEE80211_TX_CTRL_AMPDU_FLUSH;
+ return key;
+ }
+
+ /* No A-MPDU active or no encryption, just use the new key */
+ sta->ptk_idx_next = INVALID_PTK_KEYIDX;
+ ieee80211_check_fast_xmit(tx->sta);
+ return next_key;
+}
+
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
@@ -595,9 +636,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
tx->key = NULL;
- else if (tx->sta &&
- (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
- tx->key = key;
+ else if (tx->sta)
+ tx->key = ieee80211_select_sta_key(tx);
else if (ieee80211_is_group_privacy_action(tx->skb) &&
(key = rcu_dereference(tx->sdata->default_multicast_key)))
tx->key = key;
@@ -3414,6 +3454,10 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
return false;
+ /* ieee80211_key_activate() requests to change key */
+ if (unlikely(sta->ptk_idx_next != INVALID_PTK_KEYIDX))
+ return false;
+
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
@@ -3556,6 +3600,11 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
if (txq->sta)
tx.sta = container_of(txq->sta, struct sta_info, sta);
+ if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
+ info->flags |= IEEE80211_TX_CTL_AMPDU;
+ else
+ info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+
/*
* The key can be removed while the packet was queued, so need to call
* this here to get the current key.
@@ -3566,11 +3615,6 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
goto begin;
}
- if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
- info->flags |= IEEE80211_TX_CTL_AMPDU;
- else
- info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
struct sta_info *sta = container_of(txq->sta, struct sta_info,
sta);
--
2.21.0
^ 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