2016-10-19 15:18:13

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 00/10] iwlwifi: updates intended for v4.10 2016-10-19

From: Luca Coelho <[email protected]>

Hi,

Here's my first series for v4.10. These are the changes:

* Finalize and enable dynamic queue allocation;
* Use dev_coredumpmsg() to prevent locking the driver;
* Small fix to pass the AID to the FW;
* Use FW PS decisions with multi-queue;

As usual, I'm pushing this to a pending branch, for kbuild bot, and
will send a pull-request later.

Please review.

Cheers,
Luca.


Aviya Erenfeld (1):
iwlwifi: mvm: use dev_coredumpsg()

Emmanuel Grumbach (1):
iwlwifi: mvm: tell the firmware about the AID of the peer

Johannes Berg (1):
iwlwifi: mvm: use firmware station PM notification for AP_LINK_PS

Liad Kaufman (5):
iwlwifi: mvm: update txq metadata to current owner
iwlwifi: mvm: fix reserved txq freeing
iwlwifi: mvm: support MONITOR vif in DQA mode
iwlwifi: mvm: fix dqa deferred frames marking
iwlwifi: mvm: operate in dqa mode

Sara Sharon (1):
iwlwifi: mvm: assign cab queue to the correct station

Sharon Dvir (1):
iwlwifi: pcie: give a meaningful name to interrupt request

drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 26 ++++++
.../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 9 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 100 +++++++++++----------
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 24 ++---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 86 +++++++++++++++++-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 37 ++++++--
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 1 +
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 29 +++++-
12 files changed, 249 insertions(+), 75 deletions(-)

--
2.9.3


2016-10-19 15:18:22

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 04/10] iwlwifi: mvm: fix dqa deferred frames marking

From: Liad Kaufman <[email protected]>

When a STA has deferred traffic to TX, an appropriate bit
is turned on in %deferred_tx_frames to indicate deferred
traffic. This marking is never turned off, resulting in
iterating over TIDs with no deferred traffic.

Although this didn't cause any failures/errors/bugs, there
is still no point of iterating over these TIDs when not
needed.

Signed-off-by: Liad Kaufman <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index c9dcb70..5ec1b96 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1015,6 +1015,7 @@ static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm,
local_bh_disable();
spin_lock(&mvmsta->lock);
skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx);
+ mvmsta->deferred_traffic_tid_map &= ~BIT(tid);
spin_unlock(&mvmsta->lock);

while ((skb = __skb_dequeue(&deferred_tx)))
--
2.9.3

2016-10-19 15:18:30

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 10/10] iwlwifi: mvm: use dev_coredumpsg()

From: Aviya Erenfeld <[email protected]>

iwlmvm currently uses dev_coredumpm() to collect multiple
buffers, but this has the downside of pinning the module
until the coredump expires, if the data isn't read by any
userspace.

Avoid this by using the new dev_coredumpsg() method. We
still copy the data from the old way of generating it, but
neither hold on to vmalloc'ed data for a long time, nor do
we pin the module now.

Signed-off-by: Aviya Erenfeld <[email protected]>
[rewrite commit message]
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 100 +++++++++++++-----------
1 file changed, 55 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index d89d0a1..2e8e3e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -70,49 +70,6 @@
#include "iwl-prph.h"
#include "iwl-csr.h"

-static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
- void *data, size_t datalen)
-{
- const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
- ssize_t bytes_read;
- ssize_t bytes_read_trans;
-
- if (offset < dump_ptrs->op_mode_len) {
- bytes_read = min_t(ssize_t, count,
- dump_ptrs->op_mode_len - offset);
- memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
- bytes_read);
- offset += bytes_read;
- count -= bytes_read;
-
- if (count == 0)
- return bytes_read;
- } else {
- bytes_read = 0;
- }
-
- if (!dump_ptrs->trans_ptr)
- return bytes_read;
-
- offset -= dump_ptrs->op_mode_len;
- bytes_read_trans = min_t(ssize_t, count,
- dump_ptrs->trans_ptr->len - offset);
- memcpy(buffer + bytes_read,
- (u8 *)dump_ptrs->trans_ptr->data + offset,
- bytes_read_trans);
-
- return bytes_read + bytes_read_trans;
-}
-
-static void iwl_mvm_free_coredump(void *data)
-{
- const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
-
- vfree(fw_error_dump->op_mode_ptr);
- vfree(fw_error_dump->trans_ptr);
- kfree(fw_error_dump);
-}
-
#define RADIO_REG_MAX_READ 0x2ad
static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm,
struct iwl_fw_error_dump_data **dump_data)
@@ -491,6 +448,43 @@ static u32 iwl_dump_prph(struct iwl_trans *trans,
return prph_len;
}

+/*
+ * alloc_sgtable - allocates scallerlist table in the given size,
+ * fills it with pages and returns it
+ * @size: the size (in bytes) of the table
+*/
+static struct scatterlist *alloc_sgtable(int size)
+{
+ int alloc_size, nents, i;
+ struct page *new_page;
+ struct scatterlist *iter;
+ struct scatterlist *table;
+
+ nents = DIV_ROUND_UP(size, PAGE_SIZE);
+ table = kcalloc(nents, sizeof(*table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+ sg_init_table(table, nents);
+ iter = table;
+ for_each_sg(table, iter, sg_nents(table), i) {
+ new_page = alloc_page(GFP_KERNEL);
+ if (!new_page) {
+ /* release all previous allocated pages in the table */
+ iter = table;
+ for_each_sg(table, iter, sg_nents(table), i) {
+ new_page = sg_page(iter);
+ if (new_page)
+ __free_page(new_page);
+ }
+ return NULL;
+ }
+ alloc_size = min_t(int, size, PAGE_SIZE);
+ size -= PAGE_SIZE;
+ sg_set_page(iter, new_page, alloc_size, 0);
+ }
+ return table;
+}
+
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
{
struct iwl_fw_error_dump_file *dump_file;
@@ -499,6 +493,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_mem *dump_mem;
struct iwl_fw_error_dump_trigger_desc *dump_trig;
struct iwl_mvm_dump_ptrs *fw_error_dump;
+ struct scatterlist *sg_dump_data;
u32 sram_len, sram_ofs;
struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem =
mvm->fw->dbg_mem_tlv;
@@ -815,8 +810,23 @@ dump_trans_data:
file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);

- dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
- GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
+ sg_dump_data = alloc_sgtable(file_len);
+ if (sg_dump_data) {
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump->op_mode_ptr,
+ fw_error_dump->op_mode_len, 0);
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump->trans_ptr->data,
+ fw_error_dump->trans_ptr->len,
+ fw_error_dump->op_mode_len);
+ dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len,
+ GFP_KERNEL);
+ }
+ vfree(fw_error_dump->op_mode_ptr);
+ vfree(fw_error_dump->trans_ptr);
+ kfree(fw_error_dump);

out:
iwl_mvm_free_fw_dump_desc(mvm);
--
2.9.3

2016-10-19 15:18:19

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 03/10] iwlwifi: mvm: support MONITOR vif in DQA mode

From: Liad Kaufman <[email protected]>

In DQA mode the TXQs are allocated on demand, so make
sure the sniffer STA tfd_queue_msk isn't set.

Signed-off-by: Liad Kaufman <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 6b962d6..9a91203 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -899,9 +899,11 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,

iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);

- for (i = 0; i < IEEE80211_NUM_ACS; i++)
- if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
- tfd_queue_msk |= BIT(vif->hw_queue[i]);
+ if (!iwl_mvm_is_dqa_supported(mvm)) {
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
+ tfd_queue_msk |= BIT(vif->hw_queue[i]);
+ }

cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
MAC_FILTER_IN_CONTROL_AND_MGMT |
--
2.9.3

2016-10-26 06:44:48

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 09/10] iwlwifi: mvm: operate in dqa mode

SGkgS2FsbGUsDQoNCk9uIFdlZCwgMjAxNi0xMC0yNiBhdCAwOTozMiArMDMwMCwgS2FsbGUgVmFs
byB3cm90ZToNCj4gTHVjYSBDb2VsaG8gPGx1Y2FAY29lbGhvLmZpPiB3cml0ZXM6DQo+IA0KPiA+
IEZyb206IExpYWQgS2F1Zm1hbiA8bGlhZC5rYXVmbWFuQGludGVsLmNvbT4NCj4gPiANCj4gPiBS
dW4gRFFBIGZsb3dzIGJ5IGRlZmF1bHQsIGFzIGxvbmcgYXMgdGhlIEZXIHN1cHBvcnRzIGl0Lg0K
PiA+IA0KPiA+IFNpZ25lZC1vZmYtYnk6IExpYWQgS2F1Zm1hbiA8bGlhZC5rYXVmbWFuQGludGVs
LmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBMdWNhIENvZWxobyA8bHVjaWFuby5jb2VsaG9AaW50
ZWwuY29tPg0KPiANCj4gV2hhdCdzIHRoaXMgRFFBIG1vZGU/IEEgc2hvcnQgc3VtbWFyeSB3b3Vs
ZCBoYXZlIGJlZW4gbmljZSB3aHkgaXQncw0KPiB1c2VmdWwuDQoNCkRRQSBpcyBEeW5hbWljIFF1
ZXVlIEFsbG9jYXRpb24uIMKgV2UgaGF2ZSBiZWVuIHdvcmtpbmcgb24gdGhpcyBmb3INCnF1aXRl
IGEgd2hpbGUgbm93IChzaW5jZSB2NC43KSBhbmQgaGF2ZSBtYW55IHBhdGNoZXMgbWVudGlvbmlu
ZyB0aGF0DQphcmUgYWxyZWFkeSBtZXJnZWQuICBUaGUgZmlyc3QgcGF0Y2ggaXMgdGhpczoNCg0K
Y29tbWl0IDI0YWZiYTc2OTBlNCAoIml3bHdpZmk6IG12bTogc3VwcG9ydCBic3MgZHluYW1pYyBh
bGxvYy9kZWFsbG9jDQpvZiBxdWV1ZXMiKQ0KDQpJdHMgY29tbWl0IG1lc3NhZ2UgaGFzIHNvbWUg
ZXhwbGFuYXRpb24gYW5kIHdlIGFsc28gaGF2ZSBhIERPQyBzZWN0aW9uDQppbiBvdXIgZHJpdmVy
IHRoYXQgZXhwbGFpbnMgaXQgaW4gZnVydGhlciBkZXRhaWxzOg0KDQpodHRwczovL2dpdC5rZXJu
ZWwub3JnL2NnaXQvbGludXgva2VybmVsL2dpdC9rdmFsby93aXJlbGVzcy1kcml2ZXJzLW5leHQu
Z2l0L3RyZWUvZHJpdmVycy9uZXQvd2lyZWxlc3MvaW50ZWwvaXdsd2lmaS9tdm0vc3RhLmgjbjgy
DQoNClNpbmNlIHdlJ3ZlIGJlZW4gd29ya2luZyBvbiB0aGlzIGZvciBzbyBsb25nIGFuZCBhbHJl
YWR5IHVzZSB0aGUgdGVybQ0KRFFBIGJyb2FkbHksIHdlIHRob3VnaHQgaXQgd291bGRuJ3QgYmUg
bmVjZXNzYXJ5IHRvIGV4cGxhaW4gbW9yZSB3aGVuDQp3ZSBhcmUgZmluYWxseSBlbmFibGluZyBp
dCBieSBkZWZhdWx0LiAgQnV0IG9mIGNvdXJzZSBJIGNhbiBjaGFuZ2UgdGhhdA0KaWYgeW91IHBy
ZWZlci4NCg0KLS0NCkNoZWVycywNCkx1Y2Eu

2016-10-26 07:14:41

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 09/10] iwlwifi: mvm: operate in dqa mode

"Coelho, Luciano" <[email protected]> writes:

> Hi Kalle,
>
> On Wed, 2016-10-26 at 09:32 +0300, Kalle Valo wrote:
>> Luca Coelho <[email protected]> writes:
>>=20
>> > From: Liad Kaufman <[email protected]>
>> >=20
>> > Run DQA flows by default, as long as the FW supports it.
>> >=20
>> > Signed-off-by: Liad Kaufman <[email protected]>
>> > Signed-off-by: Luca Coelho <[email protected]>
>>=20
>> What's this DQA mode? A short summary would have been nice why it's
>> useful.
>
> DQA is Dynamic Queue Allocation. =C2=A0We have been working on this for
> quite a while now (since v4.7) and have many patches mentioning that
> are already merged. The first patch is this:
>
> commit 24afba7690e4 ("iwlwifi: mvm: support bss dynamic alloc/dealloc
> of queues")

Yeah, but that's commited over six month ago.

> Its commit message has some explanation and we also have a DOC section
> in our driver that explains it in further details:
>
> https://git.kernel.org/cgit/linux/kernel/git/kvalo/wireless-drivers-next.=
git/tree/drivers/net/wireless/intel/iwlwifi/mvm/sta.h#n82

And that's too detailed. I was hoping more like an executive summary in
few sentences.

> Since we've been working on this for so long and already use the term
> DQA broadly, we thought it wouldn't be necessary to explain more when
> we are finally enabling it by default. But of course I can change that
> if you prefer.

I guessed I could find more information from the history and I know this
is obvious to your team, but it's not obvious to everyone. The commit
log should always answer the questions "Why?" and this isn't answering
that. For example, I need this information when sending pull requests to
Dave and I'm sure lots of other people find it useful as well,
especially when enabling a new feature.

So I'm not asking for a long essay, something like this would be
adequate:

"Run DQA flows by default, as long as the FW supports it. It's currently
supported on 1234, 3456 and 7654, maybe more in the future. DQA improves
latency when X is used or throughput when Y is disabled. On the downside
it sometimes slows down throughput when using Z but that's still
accetable as it's so rarely used."

But no need to change anything for this commit, but just keep in mind
for the future.

--=20
Kalle Valo

2016-10-19 15:18:24

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 01/10] iwlwifi: mvm: update txq metadata to current owner

From: Liad Kaufman <[email protected]>

When a TXQ's owner is changed, the FW is indeed notified, but
the driver doesn't update the current metadata to reflect the
owner change. Fix that.

Signed-off-by: Liad Kaufman <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index fc77188..a65030f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -875,12 +875,17 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];

ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd);
- if (ret)
+ if (ret) {
IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n",
queue, ret);
- else
- IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
- queue, tid);
+ return;
+ }
+
+ spin_lock_bh(&mvm->queue_info_lock);
+ mvm->queue_info[queue].txq_tid = tid;
+ spin_unlock_bh(&mvm->queue_info_lock);
+ IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
+ queue, tid);
}

static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
--
2.9.3

2016-10-26 07:23:44

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 09/10] iwlwifi: mvm: operate in dqa mode

Kalle Valo <[email protected]> writes:

>> Since we've been working on this for so long and already use the term
>> DQA broadly, we thought it wouldn't be necessary to explain more when
>> we are finally enabling it by default. But of course I can change that
>> if you prefer.
>
> I guessed I could find more information from the history and I know this
> is obvious to your team, but it's not obvious to everyone. The commit
> log should always answer the questions "Why?" and this isn't answering
> that. For example, I need this information when sending pull requests to
> Dave and I'm sure lots of other people find it useful as well,
> especially when enabling a new feature.
>
> So I'm not asking for a long essay, something like this would be
> adequate:
>
> "Run DQA flows by default, as long as the FW supports it. It's currently
> supported on 1234, 3456 and 7654, maybe more in the future. DQA improves
> latency when X is used or throughput when Y is disabled. On the downside
> it sometimes slows down throughput when using Z but that's still
> accetable as it's so rarely used."

Oh, I forgot that the acronym should be also spelled out in the commit
log.

--=20
Kalle Valo=

2016-10-19 15:18:26

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 07/10] iwlwifi: mvm: tell the firmware about the AID of the peer

From: Emmanuel Grumbach <[email protected]>

When a peer associates, the firmware will soon want to know
its AID to be able to compute the TIM IE by itself.
In DQA, the firmware has all the information it needs to
update the TIM internally. The only missing part is the
AID.

Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 82ee786..636c8b0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -202,6 +202,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
add_sta_cmd.station_flags |=
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
+ add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);

if (sta->wme) {
add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
--
2.9.3

2016-10-26 08:09:56

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2] iwlwifi: mvm: enable dynamic queue allocation mode

From: Liad Kaufman <[email protected]>

New firmwares support dynamic queue allocation (DQA), which enables
on-demand allocation of queues per RA/TID, instead of allocating them
statically per vif. This allows an AP to send, for instance, BE
traffic to STA2 even if it also needs to send traffic to a sleeping
STA1, without being blocked by the sleeping station.

The implementation in the driver is now ready, so we can enable this
feature by default when running firmwares that support it.

Signed-off-by: Liad Kaufman <[email protected]>
[reworded the commit message]
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 726ba48..cde8c6c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1111,9 +1111,8 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)

static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
{
- /* Make sure DQA isn't allowed in driver until feature is complete */
- return false && fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
+ return fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
}

static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
--
2.9.3

2016-10-19 15:18:28

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 05/10] iwlwifi: mvm: use firmware station PM notification for AP_LINK_PS

From: Johannes Berg <[email protected]>

When using RSS on 9000 series devices, we can't rely on processing the
received frames for station powersave handling, since they could be
processed on different CPUs and out of order.

In order to still manage the powersave of stations, the firmware sends
a notification on sleep->wake, wake->sleep and - for U-APSD - frames
received with PM while already sleeping (with the TID.)

With this, the driver can set AP_LINK_PS, which is required for real
parallel RX. In addition, this requires checking for PS-Poll frames
and calling ieee80211_sta_pspoll() appropriately.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 26 ++++++++
.../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 9 ++-
drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 70 ++++++++++++++++++++--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 ++++
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 1 +
9 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index ceec5ca..1ad0ec1 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -293,6 +293,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
* is supported.
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
+ * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@@ -342,6 +343,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
+ IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
index acc5cd5..b530fa4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
@@ -474,4 +474,30 @@ struct iwl_mvm_internal_rxq_notif {
u8 data[];
} __packed;

+/**
+ * enum iwl_mvm_pm_event - type of station PM event
+ * @IWL_MVM_PM_EVENT_AWAKE: station woke up
+ * @IWL_MVM_PM_EVENT_ASLEEP: station went to sleep
+ * @IWL_MVM_PM_EVENT_UAPSD: station sent uAPSD trigger
+ * @IWL_MVM_PM_EVENT_PS_POLL: station sent PS-Poll
+ */
+enum iwl_mvm_pm_event {
+ IWL_MVM_PM_EVENT_AWAKE,
+ IWL_MVM_PM_EVENT_ASLEEP,
+ IWL_MVM_PM_EVENT_UAPSD,
+ IWL_MVM_PM_EVENT_PS_POLL,
+}; /* PEER_PM_NTFY_API_E_VER_1 */
+
+/**
+ * struct iwl_mvm_pm_state_notification - station PM state notification
+ * @sta_id: station ID of the station changing state
+ * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above
+ */
+struct iwl_mvm_pm_state_notification {
+ u8 sta_id;
+ u8 type;
+ /* private: */
+ u16 reserved;
+} __packed; /* PEER_PM_NTFY_API_S_VER_1 */
+
#endif /* __fw_api_rx_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 6c8e3ca..3b5150e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -179,7 +179,7 @@ enum iwl_sta_key_flag {
* enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
* @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue
* @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
- * @STA_MODIFY_TX_RATE: unused
+ * @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_trigger_acs
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
@@ -189,7 +189,7 @@ enum iwl_sta_key_flag {
enum iwl_sta_modify_flag {
STA_MODIFY_QUEUE_REMOVAL = BIT(0),
STA_MODIFY_TID_DISABLE_TX = BIT(1),
- STA_MODIFY_TX_RATE = BIT(2),
+ STA_MODIFY_UAPSD_ACS = BIT(2),
STA_MODIFY_ADD_BA_TID = BIT(3),
STA_MODIFY_REMOVE_BA_TID = BIT(4),
STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
@@ -353,6 +353,8 @@ struct iwl_mvm_add_sta_cmd_v7 {
* @beamform_flags: beam forming controls
* @tfd_queue_msk: tfd queues used by this station
* @rx_ba_window: aggregation window size
+ * @scd_queue_bank: queue bank in used. Each bank contains 32 queues. 0 means
+ * that the queues used by this station are in the first 32.
*
* The device contains an internal table of per-station information, with info
* on security keys, aggregation parameters, and Tx rates for initial Tx
@@ -382,7 +384,8 @@ struct iwl_mvm_add_sta_cmd {
__le16 beamform_flags;
__le32 tfd_queue_msk;
__le16 rx_ba_window;
- __le16 reserved;
+ u8 scd_queue_bank;
+ u8 uapsd_trigger_acs;
} __packed; /* ADD_STA_CMD_API_S_VER_8 */

/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index 9763369..ae12bad 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -332,6 +332,7 @@ enum iwl_data_path_subcmd_ids {
DQA_ENABLE_CMD = 0x0,
UPDATE_MU_GROUPS_CMD = 0x1,
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
+ STA_PM_NOTIF = 0xFD,
MU_GROUP_MGMT_NOTIF = 0xFE,
RX_QUEUES_NOTIFICATION = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 318efd8..9eeb2c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -445,6 +445,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
if (iwl_mvm_has_new_rx_api(mvm))
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF))
+ ieee80211_hw_set(hw, AP_LINK_PS);

if (mvm->trans->num_rx_queues > 1)
ieee80211_hw_set(hw, USES_RSS);
@@ -2318,10 +2320,9 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
tids, more_data, true);
}

-static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd,
- struct ieee80211_sta *sta)
+static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -2374,6 +2375,67 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
spin_unlock_bh(&mvmsta->lock);
}

+static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
+{
+ __iwl_mvm_mac_sta_notify(hw, cmd, sta);
+}
+
+void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_mvm_pm_state_notification *notif = (void *)pkt->data;
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+ bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE);
+
+ if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
+ return;
+
+ rcu_read_lock();
+ sta = mvm->fw_id_to_mac_id[notif->sta_id];
+ if (WARN_ON(IS_ERR_OR_NULL(sta))) {
+ rcu_read_unlock();
+ return;
+ }
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (!mvmsta->vif ||
+ mvmsta->vif->type != NL80211_IFTYPE_AP) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (mvmsta->sleeping != sleeping) {
+ mvmsta->sleeping = sleeping;
+ __iwl_mvm_mac_sta_notify(mvm->hw,
+ sleeping ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE,
+ sta);
+ ieee80211_sta_ps_transition(sta, sleeping);
+ }
+
+ if (sleeping) {
+ switch (notif->type) {
+ case IWL_MVM_PM_EVENT_AWAKE:
+ case IWL_MVM_PM_EVENT_ASLEEP:
+ break;
+ case IWL_MVM_PM_EVENT_UAPSD:
+ ieee80211_sta_uapsd_trigger(sta, IEEE80211_NUM_TIDS);
+ break;
+ case IWL_MVM_PM_EVENT_PS_POLL:
+ ieee80211_sta_pspoll(sta);
+ break;
+ default:
+ break;
+ }
+ }
+
+ rcu_read_unlock();
+}
+
static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index d17cbf6..726ba48 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1418,6 +1418,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_window_status_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 05fe6dd..e86986f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -306,6 +306,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC),
RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF,
iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC),
+ RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF,
+ iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC),
};
#undef RX_HANDLER
#undef RX_HANDLER_GRP
@@ -452,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
+ HCMD_NAME(STA_PM_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
HCMD_NAME(RX_QUEUES_NOTIFICATION),
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 5ec1b96..82ee786 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -203,6 +203,19 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
add_sta_cmd.station_flags |=
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);

+ if (sta->wme) {
+ add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
+
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BK);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO);
+ }
+
status = ADD_STA_SUCCESS;
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
iwl_mvm_add_sta_cmd_size(mvm),
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index e068d53..b45c7b9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -436,6 +436,7 @@ struct iwl_mvm_sta {

bool disable_tx;
bool tlc_amsdu;
+ bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
u8 avg_energy;
--
2.9.3

2016-10-19 15:18:17

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 02/10] iwlwifi: mvm: fix reserved txq freeing

From: Liad Kaufman <[email protected]>

If a TXQ's marking as a reserved queue is removed,
when removing the STA the driver might try to access
out of bounds memory. Make sure the reserved queue
is freed only if it is still reserved.

Signed-off-by: Liad Kaufman <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index a65030f..c9dcb70 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1494,12 +1494,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);

/* If DQA is supported - the queues can be disabled now */
- if (iwl_mvm_is_dqa_supported(mvm)) {
+ if (iwl_mvm_is_dqa_supported(mvm))
+ iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
+
+ /* If there is a TXQ still marked as reserved - free it */
+ if (iwl_mvm_is_dqa_supported(mvm) &&
+ mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
u8 reserved_txq = mvm_sta->reserved_queue;
enum iwl_mvm_queue_status *status;

- iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
-
/*
* If no traffic has gone through the reserved TXQ - it
* is still marked as IWL_MVM_QUEUE_RESERVED, and
--
2.9.3

2016-10-19 15:18:32

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 06/10] iwlwifi: pcie: give a meaningful name to interrupt request

From: Sharon Dvir <[email protected]>

Instead of passing DRV_NAME pass a string that
represents the reason for the interrupt.

Signed-off-by: Sharon Dvir <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 29 ++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index ae95533..b10e363 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1598,6 +1598,29 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
}
}

+static const char *queue_name(struct device *dev,
+ struct iwl_trans_pcie *trans_p, int i)
+{
+ if (trans_p->shared_vec_mask) {
+ int vec = trans_p->shared_vec_mask &
+ IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
+
+ if (i == 0)
+ return DRV_NAME ": shared IRQ";
+
+ return devm_kasprintf(dev, GFP_KERNEL,
+ DRV_NAME ": queue %d", i + vec);
+ }
+ if (i == 0)
+ return DRV_NAME ": default queue";
+
+ if (i == trans_p->alloc_vecs - 1)
+ return DRV_NAME ": exception";
+
+ return devm_kasprintf(dev, GFP_KERNEL,
+ DRV_NAME ": queue %d", i);
+}
+
static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
struct iwl_trans_pcie *trans_pcie)
{
@@ -1606,6 +1629,10 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
for (i = 0; i < trans_pcie->alloc_vecs; i++) {
int ret;
struct msix_entry *msix_entry;
+ const char *qname = queue_name(&pdev->dev, trans_pcie, i);
+
+ if (!qname)
+ return -ENOMEM;

msix_entry = &trans_pcie->msix_entries[i];
ret = devm_request_threaded_irq(&pdev->dev,
@@ -1615,7 +1642,7 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
iwl_pcie_irq_msix_handler :
iwl_pcie_irq_rx_msix_handler,
IRQF_SHARED,
- DRV_NAME,
+ qname,
msix_entry);
if (ret) {
IWL_ERR(trans_pcie->trans,
--
2.9.3

2016-10-20 13:32:04

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 10/10] iwlwifi: mvm: use dev_coredumpsg()


> - dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump,
> 0,
> -       GFP_KERNEL, iwl_mvm_read_coredump,
> iwl_mvm_free_coredump);
> + sg_dump_data = alloc_sgtable(file_len);
> + if (sg_dump_data) {
> + sg_pcopy_from_buffer(sg_dump_data,
> +      sg_nents(sg_dump_data),
> +      fw_error_dump->op_mode_ptr,
> +      fw_error_dump->op_mode_len, 0);
> + sg_pcopy_from_buffer(sg_dump_data,
> +      sg_nents(sg_dump_data),
> +      fw_error_dump->trans_ptr->data,
> +      fw_error_dump->trans_ptr->len,
> +      fw_error_dump->op_mode_len);
>
smatch pointed out that we check fw_error_dump->trans_ptr for NULL
earlier, and that is indeed correct afaict; I've sent you a fix
internally :)

johannes

2016-10-19 15:18:11

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 09/10] iwlwifi: mvm: operate in dqa mode

From: Liad Kaufman <[email protected]>

Run DQA flows by default, as long as the FW supports it.

Signed-off-by: Liad Kaufman <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 726ba48..cde8c6c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1111,9 +1111,8 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)

static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
{
- /* Make sure DQA isn't allowed in driver until feature is complete */
- return false && fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
+ return fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
}

static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
--
2.9.3

2016-10-26 06:32:58

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 09/10] iwlwifi: mvm: operate in dqa mode

Luca Coelho <[email protected]> writes:

> From: Liad Kaufman <[email protected]>
>
> Run DQA flows by default, as long as the FW supports it.
>
> Signed-off-by: Liad Kaufman <[email protected]>
> Signed-off-by: Luca Coelho <[email protected]>

What's this DQA mode? A short summary would have been nice why it's
useful.

--
Kalle Valo

2016-10-19 15:18:15

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 08/10] iwlwifi: mvm: assign cab queue to the correct station

From: Sara Sharon <[email protected]>

Currently when configuring the cab queue the scheduler is configured
without station id - which results in station id 0.
In DQA mode this causes firmware to assert later on when the actual
station 0 is added with an empty tfd_queue_mask.
Fix that by configuring the queue to the broadcast station.
This is a bit trickier since the queue should not be included in the
tfd_queue_mask of the ADD_STA since it is a multicast queue, and the
tfd_queue_mask is only unicast queue. As a result the queue should be
enabled only after the broadcast station is added.

Signed-off-by: Sara Sharon <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 16 +++++++---------
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 16 ++++++++++++++++
2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 9a91203..4a0874e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -499,23 +499,21 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (ret)
return ret;

+ /* If DQA is supported - queues will be enabled when needed */
+ if (iwl_mvm_is_dqa_supported(mvm))
+ return 0;
+
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
- if (!iwl_mvm_is_dqa_supported(mvm))
- iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_TX_FIFO_VO, 0,
- wdg_timeout);
+ iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
+ IWL_MVM_OFFCHANNEL_QUEUE,
+ IWL_MVM_TX_FIFO_VO, 0, wdg_timeout);
break;
case NL80211_IFTYPE_AP:
iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue,
IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
/* fall through */
default:
- /* If DQA is supported - queues will be enabled when needed */
- if (iwl_mvm_is_dqa_supported(mvm))
- break;
-
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac],
vif->hw_queue[ac],
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 9eeb2c3..4f8c134 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2099,6 +2099,22 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unbind;

+ /* enable the multicast queue, now that we have a station for it */
+ if (iwl_mvm_is_dqa_supported(mvm)) {
+ unsigned int wdg_timeout =
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ struct iwl_trans_txq_scd_cfg cfg = {
+ .fifo = IWL_MVM_TX_FIFO_MCAST,
+ .sta_id = mvmvif->bcast_sta.sta_id,
+ .tid = IWL_MAX_TID_COUNT,
+ .aggregate = false,
+ .frame_limit = IWL_FRAME_LIMIT,
+ };
+
+ iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
+ &cfg, wdg_timeout);
+ }
+
/* must be set before quota calculations */
mvmvif->ap_ibss_active = true;

--
2.9.3