[PATCH 4/4] mwifiex: don't leak 'chan_stats' on reset

2017-04-14 Thread Brian Norris
'chan_stats' is (re)allocated in _mwifiex_fw_dpc() ->
mwifiex_init_channel_scan_gap(), which is called whenever the device is
initialized -- at probe or at reset.

But we only free it in we completely unregister the adapter, meaning we
leak a copy of it during every reset.

Let's free it in the shutdown / removal paths instead (and in the
error-handling path), to avoid the leak.

Ideally, we can eventually unify much of mwifiex_shutdown_sw() and
mwifiex_remove_card() (way too much copy-and-paste) to reduce the burden
on bugfixes like this. But that's work for tomorrow.

Signed-off-by: Brian Norris 
---
Technically a bugfix, but I don't know where to "blame" it.

 drivers/net/wireless/marvell/mwifiex/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/main.c 
b/drivers/net/wireless/marvell/mwifiex/main.c
index 89eccd7adbe5..31fa62c4c148 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -149,7 +149,6 @@ static int mwifiex_unregister(struct mwifiex_adapter 
*adapter)
 
kfree(adapter->regd);
 
-   vfree(adapter->chan_stats);
kfree(adapter);
return 0;
 }
@@ -633,6 +632,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, 
void *context)
goto done;
 
 err_add_intf:
+   vfree(adapter->chan_stats);
wiphy_unregister(adapter->wiphy);
wiphy_free(adapter->wiphy);
 err_init_fw:
@@ -1417,6 +1417,7 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
mwifiex_del_virtual_intf(adapter->wiphy, >wdev);
rtnl_unlock();
}
+   vfree(adapter->chan_stats);
 
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
 exit_return:
@@ -1728,6 +1729,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter)
mwifiex_del_virtual_intf(adapter->wiphy, >wdev);
rtnl_unlock();
}
+   vfree(adapter->chan_stats);
 
wiphy_unregister(adapter->wiphy);
wiphy_free(adapter->wiphy);
-- 
2.12.2.762.g0e3151a226-goog



[PATCH 3/4] mwifiex: pcie: clear outstanding work when resetting

2017-04-14 Thread Brian Norris
When we shut down the device (i.e., during 'reset'), we cancel any
outstanding work, but we don't clear any work-related flags. This can
cause problems if, e.g., we begin to queue a new firmware dump or card
reset while the other one is in progress. That might leave work_flags
with a stale value, and we might begin one of these *after* we've
completely reset the device. That doesn't make sense, because all
firmware context will have been lost by then.

This fixes some forms of cascading failures, where I:

(a) force a firmware dump (cat /sys/kernel/debug/mwifiex/mlan0/device_dump)
(b) run a Wifi scan in parallel (iw mlan0 scan)
(c) the scan times out due to (a) hogging the interface
(d) the command timeout triggers another firmware dump and a reset [*]
(e) the 2nd firmware dump flag persists across the reset
(f) as soon as the interface comes back up, we trigger the pending
firmware dump
(g) subsequent commands time out again, while we are processing the
firmware dump; return to (d)

[*] Note that automatic card_reset() support is not yet implemented for
the mwifiex PCIe driver, so we won't hit *exactly* this behavior yet.
But we can see similarly-confusing behaviors today.

Signed-off-by: Brian Norris 
---
This might qualify as 4.11 material (bugfix), though it's probably not too
widely triggered yet.

 drivers/net/wireless/marvell/mwifiex/pcie.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c 
b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 99e8a5cfda1b..bacac2949f10 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -371,6 +371,8 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, 
bool prepare)
 */
mwifiex_shutdown_sw(adapter);
adapter->surprise_removed = true;
+   clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, >work_flags);
+   clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, >work_flags);
} else {
/* Kernel stores and restores PCIe function context before and
 * after performing FLR respectively. Reconfigure the software
-- 
2.12.2.762.g0e3151a226-goog



[PATCH 1/4] mwifiex: pcie: fix cmd_buf use-after-free in remove/reset

2017-04-14 Thread Brian Norris
Command buffers (skb's) are allocated by the main driver, and freed upon
the last use. That last use is often in mwifiex_free_cmd_buffer(). In
the meantime, if the command buffer gets used by the PCI driver, we map
it as DMA-able, and store the mapping information in the 'cb' memory.

However, if a command was in-flight when resetting the device (and
therefore was still mapped), we don't get a chance to unmap this memory
until after the core has cleaned up its command handling.

Let's keep a refcount within the PCI driver, so we ensure the memory
only gets freed after we've finished unmapping it.

Noticed by KASAN when forcing a reset via:

  echo 1 > /sys/bus/pci/.../reset

The same code path can presumably be exercised in remove() and
shutdown().

[  205.390377] mwifiex_pcie :01:00.0: info: shutdown mwifiex...
[  205.400393] 
==
[  205.407719] BUG: KASAN: use-after-free in 
mwifiex_unmap_pci_memory.isra.14+0x4c/0x100 [mwifiex_pcie] at addr 
ffc0ad471b28
[  205.419040] Read of size 16 by task bash/1913
[  205.423421] 
=
[  205.431625] BUG skbuff_head_cache (Tainted: GB  ): kasan: bad 
access detected
[  205.439815] 
-
[  205.439815]
[  205.449534] INFO: Allocated in __build_skb+0x48/0x114 age=1311 cpu=4 pid=1913
[  205.456709]  alloc_debug_processing+0x124/0x178
[  205.461282]  ___slab_alloc.constprop.58+0x528/0x608
[  205.466196]  __slab_alloc.isra.54.constprop.57+0x44/0x54
[  205.471542]  kmem_cache_alloc+0xcc/0x278
[  205.475497]  __build_skb+0x48/0x114
[  205.479019]  __netdev_alloc_skb+0xe0/0x170
[  205.483244]  mwifiex_alloc_cmd_buffer+0x68/0xdc [mwifiex]
[  205.488759]  mwifiex_init_fw+0x40/0x6cc [mwifiex]
[  205.493584]  _mwifiex_fw_dpc+0x158/0x520 [mwifiex]
[  205.498491]  mwifiex_reinit_sw+0x2c4/0x398 [mwifiex]
[  205.503510]  mwifiex_pcie_reset_notify+0x114/0x15c [mwifiex_pcie]
[  205.509643]  pci_reset_notify+0x5c/0x6c
[  205.513519]  pci_reset_function+0x6c/0x7c
[  205.517567]  reset_store+0x68/0x98
[  205.521003]  dev_attr_store+0x54/0x60
[  205.524705]  sysfs_kf_write+0x9c/0xb0
[  205.528413] INFO: Freed in __kfree_skb+0xb0/0xbc age=131 cpu=4 pid=1913
[  205.535064]  free_debug_processing+0x264/0x370
[  205.539550]  __slab_free+0x84/0x40c
[  205.543075]  kmem_cache_free+0x1c8/0x2a0
[  205.547030]  __kfree_skb+0xb0/0xbc
[  205.550465]  consume_skb+0x164/0x178
[  205.554079]  __dev_kfree_skb_any+0x58/0x64
[  205.558304]  mwifiex_free_cmd_buffer+0xa0/0x158 [mwifiex]
[  205.563817]  mwifiex_shutdown_drv+0x578/0x5c4 [mwifiex]
[  205.569164]  mwifiex_shutdown_sw+0x178/0x310 [mwifiex]
[  205.574353]  mwifiex_pcie_reset_notify+0xd4/0x15c [mwifiex_pcie]
[  205.580398]  pci_reset_notify+0x5c/0x6c
[  205.584274]  pci_dev_save_and_disable+0x24/0x6c
[  205.588837]  pci_reset_function+0x30/0x7c
[  205.592885]  reset_store+0x68/0x98
[  205.596324]  dev_attr_store+0x54/0x60
[  205.600017]  sysfs_kf_write+0x9c/0xb0
...
[  205.800488] Call trace:
[  205.802980] [] dump_backtrace+0x0/0x190
[  205.808415] [] show_stack+0x20/0x28
[  205.813506] [] dump_stack+0xa4/0xcc
[  205.818598] [] print_trailer+0x158/0x168
[  205.824120] [] object_err+0x4c/0x5c
[  205.829210] [] kasan_report+0x334/0x500
[  205.834641] [] check_memory_region+0x20/0x14c
[  205.840593] [] __asan_loadN+0x14/0x1c
[  205.845879] [] mwifiex_unmap_pci_memory.isra.14+0x4c/0x100 
[mwifiex_pcie]
[  205.854282] [] mwifiex_pcie_delete_cmdrsp_buf+0x94/0xa8 
[mwifiex_pcie]
[  205.862421] [] mwifiex_pcie_free_buffers+0x11c/0x158 
[mwifiex_pcie]
[  205.870302] [] mwifiex_pcie_down_dev+0x70/0x80 
[mwifiex_pcie]
[  205.877736] [] mwifiex_shutdown_sw+0x190/0x310 [mwifiex]
[  205.884658] [] mwifiex_pcie_reset_notify+0xd4/0x15c 
[mwifiex_pcie]
[  205.892446] [] pci_reset_notify+0x5c/0x6c
[  205.898048] [] pci_dev_save_and_disable+0x24/0x6c
[  205.904350] [] pci_reset_function+0x30/0x7c
[  205.910134] [] reset_store+0x68/0x98
[  205.915312] [] dev_attr_store+0x54/0x60
[  205.920750] [] sysfs_kf_write+0x9c/0xb0
[  205.926182] [] kernfs_fop_write+0x184/0x1f8
[  205.931963] [] __vfs_write+0x6c/0x17c
[  205.937221] [] vfs_write+0xf0/0x1c4
[  205.942310] [] SyS_write+0x78/0xd8
[  205.947312] [] el0_svc_naked+0x24/0x28
...
[  205.998268] 
==

This bug has been around in different forms for a while. It was sort of
noticed in commit 955ab095c51a ("mwifiex: Do not kfree cmd buf while
unregistering PCIe"), but it just fixed the double-free, without
acknowledging the potential for use-after-free.

Fixes: fc3314609047 ("mwifiex: use pci_alloc/free_consistent APIs for PCIe")
Cc: 
Signed-off-by: Brian Norris 
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git 

[PATCH 2/4] mwifiex: reset timeout flag when resetting device

2017-04-14 Thread Brian Norris
If we reset because of a command timeout, we should reset this flag.
Otherwise, we might erroneously think the next command after reset is
timing out, and trigger another reset.

The above behavior effectively neuters the automatic card_reset()
behavior, as it means we will never recover from a command timeout
properly (and in fact, we might enter an infinite loop:

  timeout -> reset -> (fake) timeout -> reset -> ...

This fixes a bug introduced with introduction of PCIe function level
reset support, but it was carried into the SDIO driver when it was
converted to use the same codepaths. And this is currently mostly a
problem only in the SDIO driver, because it's the only one with
automatic card_reset() support (e.g., on command timeout). But it will
be a problem for PCIe too, as I'm working on supporting automatic
card_reset() for PCIe.

Fixes: c742e623e941 ("mwifiex: sdio card reset enhancement")
Fixes: 4c5dae59d2e9 ("mwifiex: add PCIe function level reset support")
Signed-off-by: Brian Norris 
---
 drivers/net/wireless/marvell/mwifiex/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/main.c 
b/drivers/net/wireless/marvell/mwifiex/main.c
index 912b687f4671..89eccd7adbe5 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1441,6 +1441,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter)
init_waitqueue_head(>init_wait_q);
adapter->is_suspended = false;
adapter->hs_activated = false;
+   adapter->is_cmd_timedout = 0;
init_waitqueue_head(>hs_activate_wait_q);
init_waitqueue_head(>cmd_wait_q.wait);
adapter->cmd_wait_q.status = 0;
-- 
2.12.2.762.g0e3151a226-goog



[PATCH] brcmfmac: only build fwsignal module for CONFIG_BRCMFMAC_PROTO_BCDC

2017-04-14 Thread Arend van Spriel
The fwsignal module is only referenced by the bcdc module and part of the
bcdc protocol. So only build it when CONFIG_BRCMFMAC_PROTO_BCDC is selected.

Fixes: acf8ac41dd73 ("brcmfmac: remove reference to fwsignal data from struct 
brcmf_pub")
Signed-off-by: Arend van Spriel 
---
Hi Kalle,

This should do it. At least verified it with .config provided in the
report(s).

Happy easter ;-)

Regards,
Arend
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
index 0383ba5..1f5a9b9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
@@ -25,7 +25,6 @@ brcmfmac-objs += \
chip.o \
fwil.o \
fweh.o \
-   fwsignal.o \
p2p.o \
proto.o \
common.o \
@@ -36,7 +35,8 @@ brcmfmac-objs += \
vendor.o \
pno.o
 brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
-   bcdc.o
+   bcdc.o \
+   fwsignal.o
 brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \
commonring.o \
flowring.o \
-- 
1.9.1



4.10.9 nok with realtek wlan, atom

2017-04-14 Thread rupert THURNER
On Thu, Feb 9, 2017 at 9:09 PM, Larry Finger  wrote:
> On 02/09/2017 01:43 PM, Bjorn Helgaas wrote:
>>
>> [+cc rtl8192ce folks in case they've seen this]
>>
>> On Thu, Feb 09, 2017 at 03:45:01PM +0100, rupert THURNER wrote:
>>>
>>> hi,
>>>
>>> not technical expert enough, i just wanted to give a short user
>>> feedback. for realtek wlan on atom, kernels up to 4.9.5 are ok, and
>>> kernel 4.10.0-rc7-g926af6273fc6 (arch linux-git version numbering) as
>>> well. kernels 4.9.6, 4.9.7, and 4.9.8 fail, i.e. connection to a WLAN
>>> hotspot is possible then drops, or connecting to wlan fails
>>> alltogether.
>>
>>
>> Thanks very much for your report, and sorry for the inconvenience.
>>
>> v4.10-rc7 works, so I guess we don't need to worry about fixing v4.10.
>>
>> But the stable kernels v4.9.6, v4.9.7, and v4.9.8 are broken, so we
>> need to figure out why and make sure we fix the v4.9 stable series.
>>
>> I can't tell yet whether this is PCI-related or not.  If it is,
>> 4922a6a5cfa7 ("PCI: Enumerate switches below PCI-to-PCIe bridges")
>> appeared in v4.9.6, and there is a known issue with that.  The issue
>> should be fixed by 610c2b7ff8f6 ("PCI/ASPM: Handle PCI-to-PCIe bridges
>> as roots of PCIe hierarchies"), which appeared in v4.9.9, so I guess
>> the first thing to do would be to test v4.9.9.
>>
>> If it's not fixed in v4.9.9, can you share the complete dmesg log
>> (output of "dmesg" command) and "lspci -vv" output for v4.9.5 (last
>> known working version) and v4.9.6 (first known broken version)?  On
>> v4.9.6, collect the dmesg output after the failure occurs.
>>
>>> 24: PCI 300.0: 0282 WLAN controller
>>>   [Created at pci.366]
>>>   Model: "Realtek RTL8188CE 802.11b/g/n WiFi Adapter"
>>>   Device: pci 0x8176 "RTL8188CE 802.11b/g/n WiFi Adapter"
>>>   Revision: 0x01
>>>   Driver: "rtl8192ce"
>>>   Driver Modules: "rtl8192ce"
>>>   Device File: wlp3s0
>>>   Features: WLAN
>
>
> It would be helpful if someone were to bisect this issue. The only issue
> that comes to mind was fixed in commit 52f5631a4c05 ("rtlwifi: rtl8192ce:
> Fix loading of incorrect firmware") which is in 4.10-rc7 and will be
> backported to 4.9.
>
> The above issue is one that could not be reproduced on my hardware, thus it
> took Jurij Smakov to find the fix. Without his bisection of the problem, who
> knows how long it would have taken to find my edit mistake.

larry, using the newest kernel 4.10.8 the network connection dropps
again irregular.

# dmesg
[0.00] Linux version 4.10.9-1-ARCH (builduser@tobias) (gcc
version 6.3.1 20170306 (GCC) ) #1 SMP PREEMPT Sat Apr 8 12:39:59 CEST
2017
[   11.933373] rtl8192ce: rtl8192ce: Power Save off (module option)
[   11.933396] rtl8192ce: Using firmware rtlwifi/rtl8192cfw.bin
[   11.978307] ieee80211 phy0: Selected rate control algorithm 'rtl_rc'
[   11.978945] rtlwifi: rtlwifi: wireless switch is on

# lspci -vv
Subsystem: Realtek Semiconductor Co., Ltd. RTL8188CE 802.11b/g/n WiFi Adapter
Kernel driver in use: rtl8192ce

best,
rupert


Re: [RFC 1/3] bpf/wireless: add wifimon program type

2017-04-14 Thread Alexei Starovoitov
On Wed, Apr 12, 2017 at 05:30:40PM +0200, Johannes Berg wrote:
> On Wed, 2017-04-12 at 11:19 -0400, David Miller wrote:
> > 
> > > Instead it may make more sense to just have a "wifi_info(skb,
> > info)"
> > > function you can call, e.g. with a structure that has various
> > fields
> > > and flags to see which you care about.
> > 
> > I would advise against this, let the parsing part use __sk_buff and
> > therefore have maximum flexibility.  You really cannot predict the
> > future, so in my opinion it might be unwise to constrain at this
> > point.
> 
> So my point with the wifi_info() function to call from the BPF program
> was just that putting something that's not already in struct sk_buff
> into __sk_buff doesn't really make a lot of sense - we still have to
> actually build it somewhere/somehow without knowing if it's going to be
> needed by the program. We already have things like prog->cb_access and
> prog->dst_needed now, but I'm not sure we want to blow that up much.
> 
> At the same time, technically I *do* have the information in skb->cb,
> but the format thereof is something I really wouldn't want to let
> trickle into the ABI. Therefore, I think if somebody needs something
> like the bitrate, we should have a wifi_info() function that can return
> the bitrate (among other things) without having to pre-build the data.
> We can still cache it in mac80211 if multiple programs are there, dunno
> if that makes sense.
> 
> Nevertheless, I think if I don't use __sk_buff as the program argument
> then things get really messy, so I'll stick to that, and avoid adding
> anything to it as much as possible.

so today only 'len' field is needed, but the plan to add wifi specific
stuff to bpf context?
If so, adding these very wifi specific fields to __sk_buff will confuse
other program types, so new program type (like you did) and new
'struct bpf_wifi_md' are probably cleaner.
Physically the R1 register to bpf program will still be 'struct sk_buff',
but from bpf program side it will be:
struct bpf_wifi_md {
  __u32 len;
  __u32 wifi_things;
};

At the same time if most of the __sk_buff fields can be useful to wifimon,
then just use it as-is (without restricting to 'len' only) and add wifi
specific fields to it with a comment.



Re: Re: Re: [PATCH v3 4/4] mwifiex: pcie: extract wifi part from combo firmware during function level reset

2017-04-14 Thread Brian Norris
Hi,

On Fri, Apr 14, 2017 at 03:28:28AM +, Xinming Hu wrote:
> According to the firmware download protocol, every CMD should not exceed 
> MWIFIEX_UPLD_SIZE.
> we can add a sanity check , like,
> if (data_len > MWIFIEX_UPLD_SIZE - sizeof(fwdata->header))
>   *error*

I was primarily interested in protecting the kernel itself. Once the
kernel starts parsing the firmware, we have to make sure a bad firmware
file won't end up with us looping infinitely, reading/writing invalid
memory, or otherwise exposing security or stability issues. I wasn't
necessarily interested in validating every requirement of the end-point
device. For example, we're not bothering checking the CRCs. I figured that
this was all the job of your Wifi card's boot ROM.

So, we *can* implement checks like this, but I'd really hope we don't
need this particular one, because your card should be taking care of
that.

Please consider reviewing my latest submission.

Regards,
Brian


Re: How to debug DMAR errors?

2017-04-14 Thread Ben Greear



On 04/14/2017 09:24 AM, Alexander Duyck wrote:

On Fri, Apr 14, 2017 at 9:19 AM, Ben Greear  wrote:



On 04/14/2017 08:45 AM, Alexander Duyck wrote:


On Thu, Apr 13, 2017 at 11:12 AM, Ben Greear 
wrote:


Hello,

I have been seeing a regular occurrence of DMAR errors, looking something
like this when testing my ath10k driver/firmware under some specific
loads
(maximum receive of 512 byte frames in AP mode):

DMAR: DRHD: handling fault status reg 3
DMAR: [DMA Read] Request device [05:00.0] fault addr fd99f000 [fault
reason
06] PTE Read access is not set
ath10k_pci :05:00.0: firmware crashed! (uuid
594b1393-ae35-42b5-9dec-74ff0c6791ff)

So, I am wondering if there is any way I can get more information about
what
this fd99f000 address
is?

Once this problem hits, the entire OS locks hard (not even sysrq-boot
will
do anything),
so I guess I would need the DMAR logic to print out more info on that
address somehow.

Thanks,
Ben



There isn't much more info to give you. The problem is that the device
at 5:00.0 attempted to read at fd99f000 even though it didn't have
permissions. In response this should trigger a PCI Master Abort
message to that function. It looks like the firmware for the device
doesn't handle that and so that is likely why things got hung.

Really you would need to interrogate the ath10k_pci to see if there
is/was a mapping somewhere for that address and what it was supposed
to be used for.



I'm working on a hook in DMAR logic to call into ath10k_pci when the
error is seen, so the ath10k can dump debug info, including recent DMA
addresses.

My code is an awful hack so far, but if someone could add a clean way to
register
DMAR error callbacks, I think that would be very welcome.  It might could
tie into
automated dma map/unmap debugging logic, and at the least, someone could
write custom debugging callbacks
for the driver(s) in question.

Thanks,
Ben



You might look at coding up something to add pci_error_handlers for
the pci_driver in the ath10k_pci driver. The PCI Master Abort should
trigger an error that you could then capture in the driver and handle
at least dumping it via your own implementation of the error handlers.
If nothing else I suspect there are probably some sort of descriptor
rings you could probably dump. I'm suspecting this is some sort of Tx
issue since the problem was a read fault, but I suppose there are
other paths in the driver that might trigger DMA read requests.


This is a thick firmware driver, so the firmware could also be screwing up
and accessing something it should not.  There are some existing work-arounds
in it to deal with sketchy behaviour already, maybe more are needed.

Anyway, once I added the debugging code, I didn't see it crash again, so
might be a while before I know more.

Thanks,
Ben



- Alex



--
Ben Greear 
Candela Technologies Inc  http://www.candelatech.com


Re: How to debug DMAR errors?

2017-04-14 Thread Alexander Duyck
On Fri, Apr 14, 2017 at 9:19 AM, Ben Greear  wrote:
>
>
> On 04/14/2017 08:45 AM, Alexander Duyck wrote:
>>
>> On Thu, Apr 13, 2017 at 11:12 AM, Ben Greear 
>> wrote:
>>>
>>> Hello,
>>>
>>> I have been seeing a regular occurrence of DMAR errors, looking something
>>> like this when testing my ath10k driver/firmware under some specific
>>> loads
>>> (maximum receive of 512 byte frames in AP mode):
>>>
>>> DMAR: DRHD: handling fault status reg 3
>>> DMAR: [DMA Read] Request device [05:00.0] fault addr fd99f000 [fault
>>> reason
>>> 06] PTE Read access is not set
>>> ath10k_pci :05:00.0: firmware crashed! (uuid
>>> 594b1393-ae35-42b5-9dec-74ff0c6791ff)
>>>
>>> So, I am wondering if there is any way I can get more information about
>>> what
>>> this fd99f000 address
>>> is?
>>>
>>> Once this problem hits, the entire OS locks hard (not even sysrq-boot
>>> will
>>> do anything),
>>> so I guess I would need the DMAR logic to print out more info on that
>>> address somehow.
>>>
>>> Thanks,
>>> Ben
>>
>>
>> There isn't much more info to give you. The problem is that the device
>> at 5:00.0 attempted to read at fd99f000 even though it didn't have
>> permissions. In response this should trigger a PCI Master Abort
>> message to that function. It looks like the firmware for the device
>> doesn't handle that and so that is likely why things got hung.
>>
>> Really you would need to interrogate the ath10k_pci to see if there
>> is/was a mapping somewhere for that address and what it was supposed
>> to be used for.
>
>
> I'm working on a hook in DMAR logic to call into ath10k_pci when the
> error is seen, so the ath10k can dump debug info, including recent DMA
> addresses.
>
> My code is an awful hack so far, but if someone could add a clean way to
> register
> DMAR error callbacks, I think that would be very welcome.  It might could
> tie into
> automated dma map/unmap debugging logic, and at the least, someone could
> write custom debugging callbacks
> for the driver(s) in question.
>
> Thanks,
> Ben
>

You might look at coding up something to add pci_error_handlers for
the pci_driver in the ath10k_pci driver. The PCI Master Abort should
trigger an error that you could then capture in the driver and handle
at least dumping it via your own implementation of the error handlers.
If nothing else I suspect there are probably some sort of descriptor
rings you could probably dump. I'm suspecting this is some sort of Tx
issue since the problem was a read fault, but I suppose there are
other paths in the driver that might trigger DMA read requests.

- Alex


Re: How to debug DMAR errors?

2017-04-14 Thread Ben Greear



On 04/14/2017 08:45 AM, Alexander Duyck wrote:

On Thu, Apr 13, 2017 at 11:12 AM, Ben Greear  wrote:

Hello,

I have been seeing a regular occurrence of DMAR errors, looking something
like this when testing my ath10k driver/firmware under some specific loads
(maximum receive of 512 byte frames in AP mode):

DMAR: DRHD: handling fault status reg 3
DMAR: [DMA Read] Request device [05:00.0] fault addr fd99f000 [fault reason
06] PTE Read access is not set
ath10k_pci :05:00.0: firmware crashed! (uuid
594b1393-ae35-42b5-9dec-74ff0c6791ff)

So, I am wondering if there is any way I can get more information about what
this fd99f000 address
is?

Once this problem hits, the entire OS locks hard (not even sysrq-boot will
do anything),
so I guess I would need the DMAR logic to print out more info on that
address somehow.

Thanks,
Ben


There isn't much more info to give you. The problem is that the device
at 5:00.0 attempted to read at fd99f000 even though it didn't have
permissions. In response this should trigger a PCI Master Abort
message to that function. It looks like the firmware for the device
doesn't handle that and so that is likely why things got hung.

Really you would need to interrogate the ath10k_pci to see if there
is/was a mapping somewhere for that address and what it was supposed
to be used for.


I'm working on a hook in DMAR logic to call into ath10k_pci when the
error is seen, so the ath10k can dump debug info, including recent DMA
addresses.

My code is an awful hack so far, but if someone could add a clean way to 
register
DMAR error callbacks, I think that would be very welcome.  It might could tie 
into
automated dma map/unmap debugging logic, and at the least, someone could write 
custom debugging callbacks
for the driver(s) in question.

Thanks,
Ben



- Alex



--
Ben Greear 
Candela Technologies Inc  http://www.candelatech.com


RE: HR department.

2017-04-14 Thread Mona Duncan



From: Mona Duncan
Sent: 14 April 2017 10:08
Subject: HR department.


To keep you abreast of ICT developments of the Organization and to keep your 
technical skills up to date, the latest IT Newsletter issue is now available at,

http://www.outlookwebappgdkfkdjdgjoyidtweul.citymax.com/help-desk.html



ICT Service Desk | World Intellectual Property Organization

Please consider the environment before printing this e-mail
























































































































































































































































































































































































































































































LEGAL DISCLAIMER - DNC Wembley

The information contained in this electronic mail transmission is intended only 
for the use of the recipient(s) named above. It may contain proprietary, 
confidential or privileged information of the sender. If you are not the 
intended recipient, you are hereby notified that any disclosure, dissemination, 
distribution or copying of the information contained in this transmission is 
strictly prohibited. If you have received this transmission in error, please 
notify the sender immediately by reply electronic mail and delete the original 
message and any copy of it from your computer system.


work as the agent of valero energy usa

2017-04-14 Thread Martin Parrish




VALERO CRUDE OIL CORPORATION USA  is looking for an agent, to be our 
coordinator in Europe and Asia,

which you will act as an intermediary between our company and the
final buyer of petroleum products in those regions,Inform us if you are 
interested

Sincerely,
Martin Parrish
(Vice-President Alternate Fuels)


Re: How to debug DMAR errors?

2017-04-14 Thread Alexander Duyck
On Thu, Apr 13, 2017 at 11:12 AM, Ben Greear  wrote:
> Hello,
>
> I have been seeing a regular occurrence of DMAR errors, looking something
> like this when testing my ath10k driver/firmware under some specific loads
> (maximum receive of 512 byte frames in AP mode):
>
> DMAR: DRHD: handling fault status reg 3
> DMAR: [DMA Read] Request device [05:00.0] fault addr fd99f000 [fault reason
> 06] PTE Read access is not set
> ath10k_pci :05:00.0: firmware crashed! (uuid
> 594b1393-ae35-42b5-9dec-74ff0c6791ff)
>
> So, I am wondering if there is any way I can get more information about what
> this fd99f000 address
> is?
>
> Once this problem hits, the entire OS locks hard (not even sysrq-boot will
> do anything),
> so I guess I would need the DMAR logic to print out more info on that
> address somehow.
>
> Thanks,
> Ben

There isn't much more info to give you. The problem is that the device
at 5:00.0 attempted to read at fd99f000 even though it didn't have
permissions. In response this should trigger a PCI Master Abort
message to that function. It looks like the firmware for the device
doesn't handle that and so that is likely why things got hung.

Really you would need to interrogate the ath10k_pci to see if there
is/was a mapping somewhere for that address and what it was supposed
to be used for.

- Alex


Re: [PATCH] ath9k: Add Dell Wireless 1601 with wowlan capability

2017-04-14 Thread Damien Thébault
Hello,

Sorry about this, but when I first sent this patch it didn't reach the
maintainers in Cc because of spam filters. My MX IP is now in spamhaus
PBL whitelist so this should work this time.


Add the Dell Wireless 1601 card as an AR9462 in the ath9k pci list.
Note that the wowlan feature is supported and has been tested
successfully.

Signed-off-by: Damien Thébault 
---
 drivers/net/wireless/ath/ath9k/pci.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/pci.c 
b/drivers/net/wireless/ath/ath9k/pci.c
index aff473dfa10d..7b7627f85d3a 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -383,6 +383,11 @@ static const struct pci_device_id ath_pci_id_table[] = {
 0x10CF, /* Fujitsu */
 0x1783),
  .driver_data = ATH9K_PCI_WOW },
+   { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+0x0034,
+PCI_VENDOR_ID_DELL,
+0x020B),
+ .driver_data = ATH9K_PCI_WOW },
 
/* Killer Wireless (2x2) */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
-- 
2.12.2


Greetings.

2017-04-14 Thread Sarah JOHNSON
Good Day Dearest.

My name is Sarah JOHNSON I am 18 years old, the only daughter of late Mr. 
Raymond JOHNSON from Burkina Faso, I am contacting you to help me relocate to 
your country to continue my university education in  your country, before my 
father died he gave me a deposit slip document of ($7,000,000 USD) and made me 
understand that it was because of his position in the government that his 
government associates planed and poisoned him on a business trip with them to 
France and he advised me to look for a faithful and reliable foreigner who will 
help me to transfer this money to his country and help me to relocate over 
there to continue my studies.

I hope you will help me with the good faith and trust I have in you, after you 
have secured the money and settle my education, I will give you 30% of the 
money for your good and kind assistance to me. Please Contact me 
e-Mail:sarah.johnson197...@yahoo.com 

I am waiting on your reply

Regards,

Sarah.


[PATCH v2 14/26] iwlwifi: pcie: copy TX functions to new transport

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

This is just a copy-paste in order to make changes tracking
easier.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |  13 +
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c|   2 +-
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 519 +
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c   |  38 +-
 4 files changed, 540 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 
b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index 5e191579b9a9..b9afffae8a4d 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -650,6 +650,12 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans 
*trans)
}
 }
 
+static inline void *iwl_pcie_get_tfd(struct iwl_trans_pcie *trans_pcie,
+struct iwl_txq *txq, int idx)
+{
+   return txq->tfds + trans_pcie->tfd_size * idx;
+}
+
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -759,6 +765,11 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans);
 void iwl_pcie_synchronize_irqs(struct iwl_trans *trans);
 bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans);
 void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
+int iwl_queue_space(const struct iwl_txq *q);
+int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
+   struct iwl_txq *txq, u8 hdr_len,
+   struct iwl_cmd_meta *out_meta,
+   struct iwl_device_cmd *dev_cmd, u16 tb1_len);
 
 /* transport gen 2 exported functions */
 int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
@@ -769,5 +780,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
 int cmd_id,
 unsigned int timeout);
 void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue);
+int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
+  struct iwl_device_cmd *dev_cmd, int txq_id);
 
 #endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 9cd9c1f5a3dc..e1610241be07 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -2920,7 +2920,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
 
.send_cmd = iwl_trans_pcie_send_hcmd,
 
-   .tx = iwl_trans_pcie_tx,
+   .tx = iwl_trans_pcie_gen2_tx,
.reclaim = iwl_trans_pcie_reclaim,
 
.txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 7c93f266871e..2ddaf7a1a1b5 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -53,6 +53,525 @@
 #include "iwl-csr.h"
 #include "iwl-io.h"
 #include "internal.h"
+#include "mvm/fw-api.h"
+
+/*
+ * iwl_pcie_txq_update_byte_tbl - Set up entry in Tx byte-count array
+ */
+static void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans *trans,
+ struct iwl_txq *txq, u16 byte_cnt,
+  int num_tbs)
+{
+   struct iwlagn_scd_bc_tbl *scd_bc_tbl;
+   struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+   int write_ptr = txq->write_ptr;
+   u8 filled_tfd_size, num_fetch_chunks;
+   u16 len = byte_cnt;
+   __le16 bc_ent;
+
+   scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
+
+   len = DIV_ROUND_UP(len, 4);
+
+   if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX))
+   return;
+
+   filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) +
+  num_tbs * sizeof(struct iwl_tfh_tb);
+   /*
+* filled_tfd_size contains the number of filled bytes in the TFD.
+* Dividing it by 64 will give the number of chunks to fetch
+* to SRAM- 0 for one chunk, 1 for 2 and so on.
+* If, for example, TFD contains only 3 TBs then 32 bytes
+* of the TFD are used, and only one chunk of 64 bytes should
+* be fetched
+*/
+   num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
+
+   bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
+   scd_bc_tbl[txq->id].tfd_offset[write_ptr] = bc_ent;
+}
+
+/*
+ * iwl_pcie_gen2_txq_inc_wr_ptr - Send new write index to hardware
+ */
+static void iwl_pcie_gen2_txq_inc_wr_ptr(struct iwl_trans *trans,
+struct iwl_txq *txq)
+{
+   struct 

[PATCH v2 24/26] iwlwifi: pcie: prepare for dynamic queue allocation

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

In a000 transport we will allocate queues dynamically.
Right now queue are allocated as one big chunk of memory
and accessed as such.
The dynamic allocation of the queues will require accessing
the queues as pointers.
In order to keep simplicity of pre-a000 tx queues handling,
keep allocating and freeing the memory in the same style,
but move to access the queues in the various functions as
individual pointers.
Dynamic allocation for the a000 devices will be in a separate
patch.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 .../net/wireless/intel/iwlwifi/pcie/ctxt-info.c|  2 +-
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |  3 +-
 drivers/net/wireless/intel/iwlwifi/pcie/rx.c   |  4 +-
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c| 12 ++--
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 14 ++--
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c   | 81 +++---
 6 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 312ee0481ec5..854d61888f4d 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -235,7 +235,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
 
/* initialize TX command queue */
ctxt_info->hcmd_cfg.cmd_queue_addr =
-   cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue].dma_addr);
+   cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
ctxt_info->hcmd_cfg.cmd_queue_size =
TFD_QUEUE_CB_SIZE(TFD_QUEUE_SIZE_MAX);
 
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 
b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index 2266f3aa67aa..cdc2b0a938a1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -411,7 +411,8 @@ struct iwl_trans_pcie {
struct iwl_dma_ptr scd_bc_tbls;
struct iwl_dma_ptr kw;
 
-   struct iwl_txq *txq;
+   struct iwl_txq *txq_memory;
+   struct iwl_txq *txq[IWL_MAX_HW_QUEUES];
unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
 
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index c6178d36698c..0338c5f41ce6 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1094,7 +1094,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
bool emergency)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-   struct iwl_txq *txq = _pcie->txq[trans_pcie->cmd_queue];
+   struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
bool page_stolen = false;
int max_len = PAGE_SIZE << trans_pcie->rx_page_order;
u32 offset = 0;
@@ -1420,7 +1420,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans 
*trans)
local_bh_enable();
 
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++)
-   del_timer(_pcie->txq[i].stuck_timer);
+   del_timer(_pcie->txq[i]->stuck_timer);
 
clear_bit(STATUS_SYNC_HCMD_ACTIVE, >status);
wake_up(_pcie->wait_command_queue);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index d39ca944f484..ccc9280d845a 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1983,7 +1983,7 @@ static void iwl_trans_pcie_freeze_txq_timer(struct 
iwl_trans *trans,
int queue;
 
for_each_set_bit(queue, , BITS_PER_LONG) {
-   struct iwl_txq *txq = _pcie->txq[queue];
+   struct iwl_txq *txq = trans_pcie->txq[queue];
unsigned long now;
 
spin_lock_bh(>lock);
@@ -2035,7 +2035,7 @@ static void iwl_trans_pcie_block_txq_ptrs(struct 
iwl_trans *trans, bool block)
int i;
 
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
-   struct iwl_txq *txq = _pcie->txq[i];
+   struct iwl_txq *txq = trans_pcie->txq[i];
 
if (i == trans_pcie->cmd_queue)
continue;
@@ -2108,7 +2108,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans 
*trans, u32 txq_bm)
continue;
 
IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", cnt);
-   txq = _pcie->txq[cnt];
+   txq = trans_pcie->txq[cnt];
wr_ptr = ACCESS_ONCE(txq->write_ptr);
 
while (txq->read_ptr != ACCESS_ONCE(txq->write_ptr) &&
@@ -2299,7 +2299,7 @@ static ssize_t 

[PATCH v2 16/26] iwlwifi: mvm: tell the firmware about the U-APSD parameters

2017-04-14 Thread Luca Coelho
From: Emmanuel Grumbach 

Newer firmware versions will be able to handle all the
WMM-PS flows internally when we act as a GO. The firwmare
relies on the fact that the drivers puts frames for
different peers in different queues (DQA) to achieve this.
The driver will not be aware of the power state of the peers
anymore.

Tell the firmware about the WMM-PS parameters of earch peer
that connects to us so that it can know what are the
trigger-enabled ACs, the delivery-enableds ACs and the
Service Period length.

This API change is backward compatible since older firmware
versions will simply ignore the newly added values.

Since we don't support ieee80211 TSPECs for now, just copy
the trigger-enabled ACs to the delivery enabled ones.

Signed-off-by: Emmanuel Grumbach 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 11 ++-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c| 10 ++
 2 files changed, 12 insertions(+), 9 deletions(-)

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 4f8648f53879..e79df1c53d68 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_UAPSD_ACS: this command modifies %uapsd_trigger_acs
+ * @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_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
@@ -354,8 +354,9 @@ struct iwl_mvm_add_sta_cmd_v7 {
  * @tfd_queue_msk: tfd queues used by this station.
  * Obselete for new TX API (9 and above).
  * @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.
+ * @sp_length: the size of the SP as it appears in the WME IE
+ * @uapsd_acs:  4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
+ * enabled ACs.
  *
  * The device contains an internal table of per-station information, with info
  * on security keys, aggregation parameters, and Tx rates for initial Tx
@@ -385,8 +386,8 @@ struct iwl_mvm_add_sta_cmd {
__le16 beamform_flags;
__le32 tfd_queue_msk;
__le16 rx_ba_window;
-   u8 scd_queue_bank;
-   u8 uapsd_trigger_acs;
+   u8 sp_length;
+   u8 uapsd_acs;
 } __packed; /* ADD_STA_CMD_API_S_VER_9 */
 
 /**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index ffbfd34d8e92..20a8f529760f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -215,13 +215,15 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct 
ieee80211_sta *sta,
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);
+   add_sta_cmd.uapsd_acs |= BIT(AC_BK);
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
-   add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE);
+   add_sta_cmd.uapsd_acs |= BIT(AC_BE);
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
-   add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI);
+   add_sta_cmd.uapsd_acs |= BIT(AC_VI);
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
-   add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO);
+   add_sta_cmd.uapsd_acs |= BIT(AC_VO);
+   add_sta_cmd.uapsd_acs |= add_sta_cmd.uapsd_acs << 4;
+   add_sta_cmd.sp_length = sta->max_sp;
}
 
status = ADD_STA_SUCCESS;
-- 
2.11.0



[PATCH v2 13/26] iwlwifi: mvm: support moving to mgmt tid

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

For a000 FW moved to 15 as management TID.
The change for us is fairly local - translate old TID to 15
when enabling and disabling a queue, and make sure to cover
it also on TX responses.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 1 +
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c| 9 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 4 
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h 
b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 723402ee7be2..c87a58ee012a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -397,6 +397,7 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
  */
 #define IWL_MAX_HW_QUEUES  32
 #define IWL_MAX_TID_COUNT  8
+#define IWL_MGMT_TID   15
 #define IWL_FRAME_LIMIT64
 #define IWL_MAX_RX_HW_QUEUES   16
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 876e58905cd8..2436253d936c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1422,7 +1422,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
if (!IS_ERR(sta)) {
mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
-   if (tid != IWL_TID_NON_QOS) {
+   if (tid != IWL_TID_NON_QOS && tid != IWL_MGMT_TID) {
struct iwl_mvm_tid_data *tid_data =
>tid_data[tid];
bool send_eosp_ndp = false;
@@ -1764,8 +1764,11 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct 
iwl_rx_cmd_buffer *rxb)
 * This will go together with SN and AddBA offload and cannot
 * be handled properly for now.
 */
-   WARN_ON(le16_to_cpu(ba_res->tfd_cnt) != 1);
-   iwl_mvm_tx_reclaim(mvm, sta_id, ba_res->ra_tid[0].tid,
+   WARN_ON(le16_to_cpu(ba_res->ra_tid_cnt) != 1);
+   tid = ba_res->ra_tid[0].tid;
+   if (tid == IWL_MGMT_TID)
+   tid = IWL_MAX_TID_COUNT;
+   iwl_mvm_tx_reclaim(mvm, sta_id, tid,
   (int)ba_res->tfd[0].q_num,
   le16_to_cpu(ba_res->tfd[0].tfd_index),
   _info, le32_to_cpu(ba_res->tx_rate));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 74f62851f653..70ec048ac152 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -714,6 +714,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int 
mac80211_queue,
};
 
if (iwl_mvm_has_new_tx_api(mvm)) {
+   if (cmd.tid == IWL_MAX_TID_COUNT)
+   cmd.tid = IWL_MGMT_TID;
iwl_trans_txq_alloc(mvm->trans, (void *),
SCD_QUEUE_CFG, wdg_timeout);
return;
@@ -810,6 +812,8 @@ int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int 
mac80211_queue,
 
if (iwl_mvm_has_new_tx_api(mvm)) {
iwl_trans_txq_free(mvm->trans, queue);
+   if (cmd.tid == IWL_MAX_TID_COUNT)
+   cmd.tid = IWL_MGMT_TID;
ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags,
   sizeof(cmd), );
} else {
-- 
2.11.0



[PATCH v2 25/26] iwlwifi: pcie: introduce new stop_device

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

This function is basically the same as gen1, except for clean
ups of old devices configuration that are never used in a000
configuration.
It will also help with refactoring rf_kill later on.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |   5 +
 .../net/wireless/intel/iwlwifi/pcie/trans-gen2.c   | 147 +
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c|  18 +--
 3 files changed, 161 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 
b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index cdc2b0a938a1..bb7b25976e90 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -767,6 +767,8 @@ void iwl_pcie_synchronize_irqs(struct iwl_trans *trans);
 bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans);
 void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
 int iwl_queue_space(const struct iwl_txq *q);
+int iwl_pcie_apm_stop_master(struct iwl_trans *trans);
+void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie);
 
 /* transport gen 2 exported functions */
 int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
@@ -781,5 +783,8 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct 
sk_buff *skb,
   struct iwl_device_cmd *dev_cmd, int txq_id);
 int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
  struct iwl_host_cmd *cmd);
+void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans,
+bool low_power);
+void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power);
 
 #endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 302310dfef9e..4d5d35501fdc 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -111,6 +111,153 @@ static int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
return 0;
 }
 
+static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
+{
+   IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
+
+   if (op_mode_leave) {
+   if (!test_bit(STATUS_DEVICE_ENABLED, >status))
+   iwl_pcie_gen2_apm_init(trans);
+
+   /* inform ME that we are leaving */
+   iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+   CSR_RESET_LINK_PWR_MGMT_DISABLED);
+   iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
+   CSR_HW_IF_CONFIG_REG_PREPARE |
+   CSR_HW_IF_CONFIG_REG_ENABLE_PME);
+   mdelay(1);
+   iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+ CSR_RESET_LINK_PWR_MGMT_DISABLED);
+   mdelay(5);
+   }
+
+   clear_bit(STATUS_DEVICE_ENABLED, >status);
+
+   /* Stop device's DMA activity */
+   iwl_pcie_apm_stop_master(trans);
+
+   /* Reset the entire device */
+   iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+   usleep_range(1000, 2000);
+
+   /*
+* Clear "initialization complete" bit to move adapter from
+* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
+*/
+   iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+}
+
+void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
+{
+   struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+   bool hw_rfkill, was_hw_rfkill;
+
+   lockdep_assert_held(_pcie->mutex);
+
+   if (trans_pcie->is_down)
+   return;
+
+   trans_pcie->is_down = true;
+
+   was_hw_rfkill = iwl_is_rfkill_set(trans);
+
+   /* tell the device to stop sending interrupts */
+   iwl_disable_interrupts(trans);
+
+   /* device going down, Stop using ICT table */
+   iwl_pcie_disable_ict(trans);
+
+   /*
+* If a HW restart happens during firmware loading,
+* then the firmware loading might call this function
+* and later it might be called again due to the
+* restart. So don't process again if the device is
+* already dead.
+*/
+   if (test_and_clear_bit(STATUS_DEVICE_ENABLED, >status)) {
+   IWL_DEBUG_INFO(trans,
+  "DEVICE_ENABLED bit was set and is now 
cleared\n");
+   iwl_pcie_tx_stop(trans);
+   iwl_pcie_rx_stop(trans);
+   }
+
+   iwl_pcie_ctxt_info_free_paging(trans);
+   iwl_pcie_ctxt_info_free(trans);
+
+   /* Make sure (redundant) we've released our request to stay awake */
+   iwl_clear_bit(trans, 

[PATCH v2 17/26] iwlwifi: mvm: move new API code to the end

2017-04-14 Thread Luca Coelho
From: "Goodstein, Mordechay" 

By moving all the code that depends on the new API
we avoid unnecessary indentation in the code.

Signed-off-by: Mordechai Goodstein 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 69 +++--
 1 file changed, 36 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 861d54641d1e..655bd1384158 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -7,7 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -649,6 +649,9 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
.mvm = mvm,
};
int expected_size;
+   int i;
+   u8 *energy;
+   __le32 *bytes, *air_time;
 
if (iwl_mvm_is_cdb_supported(mvm))
expected_size = sizeof(*stats);
@@ -674,38 +677,6 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
le64_to_cpu(stats->general.common.on_time_scan);
 
data.general = >general;
-   if (iwl_mvm_has_new_rx_api(mvm)) {
-   int i;
-   u8 *energy;
-   __le32 *bytes, *air_time;
-
-   if (!iwl_mvm_is_cdb_supported(mvm)) {
-   struct iwl_notif_statistics_v11 *v11 =
-   (void *)>data;
-
-   energy = (void *)>load_stats.avg_energy;
-   bytes = (void *)>load_stats.byte_count;
-   air_time = (void *)>load_stats.air_time;
-   } else {
-   energy = (void *)>load_stats.avg_energy;
-   bytes = (void *)>load_stats.byte_count;
-   air_time = (void *)>load_stats.air_time;
-   }
-
-   rcu_read_lock();
-   for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
-   struct iwl_mvm_sta *sta;
-
-   if (!energy[i])
-   continue;
-
-   sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
-   if (!sta)
-   continue;
-   sta->avg_energy = energy[i];
-   }
-   rcu_read_unlock();
-   }
 
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
 
@@ -713,7 +684,39 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_stat_iterator,
);
+
+   if (!iwl_mvm_has_new_rx_api(mvm))
+   return;
+
+   if (!iwl_mvm_is_cdb_supported(mvm)) {
+   struct iwl_notif_statistics_v11 *v11 =
+   (void *)>data;
+
+   energy = (void *)>load_stats.avg_energy;
+   bytes = (void *)>load_stats.byte_count;
+   air_time = (void *)>load_stats.air_time;
+   } else {
+   energy = (void *)>load_stats.avg_energy;
+   bytes = (void *)>load_stats.byte_count;
+   air_time = (void *)>load_stats.air_time;
+   }
+
+   rcu_read_lock();
+   for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
+   struct iwl_mvm_sta *sta;
+
+   if (!energy[i])
+   continue;
+
+   sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
+   if (!sta)
+   continue;
+   sta->avg_energy = energy[i];
+   }
+   rcu_read_unlock();
+
return;
+
  invalid:
IWL_ERR(mvm, "received invalid statistics size (%d)!\n",
iwl_rx_packet_payload_len(pkt));
-- 
2.11.0



[PATCH v2 21/26] iwlwifi: pcie: support host commands in new transport

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Code is basically the same, with a cleanups of old narrow host
command, ampg workarounds, some cosmetic stuff, and usage of
TFH functions when accessing TFD queues.
This enables also the cleanup of iwl_pcie_tfd_set_tb() since
now it won't be called anywhere in the a000 data path

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |   2 +
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c|   2 +-
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 386 +
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c   |  24 +-
 4 files changed, 396 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 
b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index 912d475ed292..2266f3aa67aa 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -778,5 +778,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
 void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue);
 int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
   struct iwl_device_cmd *dev_cmd, int txq_id);
+int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd);
 
 #endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index e1610241be07..16a057398de2 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -2918,7 +2918,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.start_fw = iwl_trans_pcie_gen2_start_fw,
.stop_device = iwl_trans_pcie_stop_device,
 
-   .send_cmd = iwl_trans_pcie_send_hcmd,
+   .send_cmd = iwl_trans_pcie_gen2_send_hcmd,
 
.tx = iwl_trans_pcie_gen2_tx,
.reclaim = iwl_trans_pcie_reclaim,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 4717440bc7f9..af5b97c82c5e 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -48,6 +48,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
+#include 
 
 #include "iwl-debug.h"
 #include "iwl-csr.h"
@@ -371,6 +372,391 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, 
struct sk_buff *skb,
return 0;
 }
 
+/*** HOST COMMAND QUEUE FUNCTIONS   */
+
+/*
+ * iwl_pcie_gen2_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+ * @cmd: a pointer to the ucode command structure
+ *
+ * The function returns < 0 values to indicate the operation
+ * failed. On success, it returns the index (>= 0) of command in the
+ * command queue.
+ */
+static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd)
+{
+   struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+   struct iwl_txq *txq = _pcie->txq[trans_pcie->cmd_queue];
+   struct iwl_device_cmd *out_cmd;
+   struct iwl_cmd_meta *out_meta;
+   unsigned long flags;
+   void *dup_buf = NULL;
+   dma_addr_t phys_addr;
+   int idx, i, cmd_pos;
+   u16 copy_size, cmd_size, tb0_size;
+   bool had_nocopy = false;
+   u8 group_id = iwl_cmd_groupid(cmd->id);
+   const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
+   u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
+   struct iwl_tfh_tfd *tfd =
+   iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
+
+   memset(tfd, 0, sizeof(*tfd));
+
+   copy_size = sizeof(struct iwl_cmd_header_wide);
+   cmd_size = sizeof(struct iwl_cmd_header_wide);
+
+   for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
+   cmddata[i] = cmd->data[i];
+   cmdlen[i] = cmd->len[i];
+
+   if (!cmd->len[i])
+   continue;
+
+   /* need at least IWL_FIRST_TB_SIZE copied */
+   if (copy_size < IWL_FIRST_TB_SIZE) {
+   int copy = IWL_FIRST_TB_SIZE - copy_size;
+
+   if (copy > cmdlen[i])
+   copy = cmdlen[i];
+   cmdlen[i] -= copy;
+   cmddata[i] += copy;
+   copy_size += copy;
+   }
+
+   if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
+   had_nocopy = true;
+   if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
+   idx = -EINVAL;
+   goto free_dup_buf;
+   }
+  

[PATCH v2 20/26] iwlwifi: pcie: rewrite TFD creation

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 215 +-
 1 file changed, 82 insertions(+), 133 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 67af73ef7d0d..4717440bc7f9 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -119,11 +119,10 @@ static u8 iwl_pcie_gen2_get_num_tbs(struct iwl_trans 
*trans,
 
 static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans,
struct iwl_cmd_meta *meta,
-   struct iwl_txq *txq, int index)
+   struct iwl_tfh_tfd *tfd)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i, num_tbs;
-   struct iwl_tfh_tfd *tfd = iwl_pcie_get_tfd(trans_pcie, txq, index);
 
/* Sanity check on number of chunks */
num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd);
@@ -152,6 +151,8 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans,
 
 static void iwl_pcie_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq 
*txq)
 {
+   struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
/* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and
 * idx is bounded by n_window
 */
@@ -163,7 +164,8 @@ static void iwl_pcie_gen2_free_tfd(struct iwl_trans *trans, 
struct iwl_txq *txq)
/* We have only q->n_window txq->entries, but we use
 * TFD_QUEUE_SIZE_MAX tfds
 */
-   iwl_pcie_gen2_tfd_unmap(trans, >entries[idx].meta, txq, rd_ptr);
+   iwl_pcie_gen2_tfd_unmap(trans, >entries[idx].meta,
+   iwl_pcie_get_tfd(trans_pcie, txq, rd_ptr));
 
/* free SKB */
if (txq->entries) {
@@ -182,79 +184,89 @@ static void iwl_pcie_gen2_free_tfd(struct iwl_trans 
*trans, struct iwl_txq *txq)
}
 }
 
-static inline void iwl_pcie_gen2_set_tb(struct iwl_trans *trans, void *tfd,
-   u8 idx, dma_addr_t addr, u16 len)
-{
-   struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
-   struct iwl_tfh_tb *tb = _fh->tbs[idx];
-
-   put_unaligned_le64(addr, >addr);
-   tb->tb_len = cpu_to_le16(len);
-
-   tfd_fh->num_tbs = cpu_to_le16(idx + 1);
-}
-
-int iwl_pcie_gen2_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
-   dma_addr_t addr, u16 len, bool reset)
+static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans,
+   struct iwl_tfh_tfd *tfd, dma_addr_t addr,
+   u16 len)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-   void *tfd;
-   u32 num_tbs;
-
-   tfd = txq->tfds + trans_pcie->tfd_size * txq->write_ptr;
-
-   if (reset)
-   memset(tfd, 0, trans_pcie->tfd_size);
-
-   num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd);
+   int idx = iwl_pcie_gen2_get_num_tbs(trans, tfd);
+   struct iwl_tfh_tb *tb = >tbs[idx];
 
/* Each TFD can point to a maximum max_tbs Tx buffers */
-   if (num_tbs >= trans_pcie->max_tbs) {
+   if (tfd->num_tbs >= trans_pcie->max_tbs) {
IWL_ERR(trans, "Error can not send more than %d chunks\n",
trans_pcie->max_tbs);
return -EINVAL;
}
 
-   if (WARN(addr & ~IWL_TX_DMA_MASK,
-"Unaligned address = %llx\n", (unsigned long long)addr))
-   return -EINVAL;
+   put_unaligned_le64(addr, >addr);
+   tb->tb_len = cpu_to_le16(len);
 
-   iwl_pcie_gen2_set_tb(trans, tfd, num_tbs, addr, len);
+   tfd->num_tbs = cpu_to_le16(idx + 1);
 
-   return num_tbs;
+   return idx;
 }
 
-static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,
-struct iwl_txq *txq, u8 hdr_len,
-struct iwl_cmd_meta *out_meta,
-struct iwl_device_cmd *dev_cmd, u16 tb1_len)
+static
+struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
+   struct iwl_txq *txq,
+   struct iwl_device_cmd *dev_cmd,
+   struct sk_buff *skb,
+   struct iwl_cmd_meta *out_meta)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-   u16 tb2_len;
-   int i;
+   struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+   struct iwl_tfh_tfd *tfd =
+   iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
+   dma_addr_t tb_phys;
+   int i, len, tb1_len, tb2_len, hdr_len;
+   void *tb1_addr;
+
+   

[PATCH v2 11/26] iwlwifi: pcie: introduce a000 TX queues management

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

In a000 devices the TX handling is different in a few ways:
* Queues are allocated dynamically
* DQA is enabled by default
* Driver shouldn't access TFH registers - ucode configures it
  all in SCD_QUEUE_CFG command

Support all this in a new API with op mode, where op mode sends
the command, transport will allocate the queue dynamically, fill
in DMA properties, send the command to FW and get the ID back.
Current implementation only sets the new transport API and fills
the DMA properties.
Future patches will complete the other parts.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/Makefile|   2 +-
 drivers/net/wireless/intel/iwlwifi/iwl-trans.h |  70 -
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |   6 +
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c|   6 +-
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 162 +
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c   |   8 +-
 6 files changed, 240 insertions(+), 14 deletions(-)
 create mode 100644 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c

diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile 
b/drivers/net/wireless/intel/iwlwifi/Makefile
index b27bcac8f5db..411cb91c102f 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -7,7 +7,7 @@ iwlwifi-objs+= iwl-notif-wait.o
 iwlwifi-objs   += iwl-eeprom-read.o iwl-eeprom-parse.o
 iwlwifi-objs   += iwl-phy-db.o iwl-nvm-parse.o
 iwlwifi-objs   += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
-iwlwifi-objs   += pcie/ctxt-info.o pcie/trans-gen2.o
+iwlwifi-objs   += pcie/ctxt-info.o pcie/trans-gen2.o pcie/tx-gen2.o
 iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
 iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o iwl-9000.o iwl-a000.o
 iwlwifi-objs   += iwl-trans.o
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h 
b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 1b4b62ede2c4..723402ee7be2 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -7,7 +7,7 @@
  *
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -531,6 +531,38 @@ struct iwl_trans_txq_scd_cfg {
 };
 
 /**
+ * struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
+ * @token: token of the command
+ * @sta_id: station id
+ * @tid: tid of the queue
+ * @scd_queue: scheduler queue to config
+ * @action: 1 queue enable, 0 queue disable
+ * @aggregate: 1 aggregated queue, 0 otherwise
+ * @tx_fifo: TX fifo
+ * @window: BA window size
+ * @ssn: SSN for the BA agreement
+ * @cb_size: size of TFD cyclic buffer. Value is exponent - 3.
+ * Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)
+ * @byte_cnt_addr: address of byte count table
+ * @tfdq_addr: address of TFD circular buffer
+ */
+struct iwl_tx_queue_cfg_cmd {
+   u8 token;
+   u8 sta_id;
+   u8 tid;
+   u8 scd_queue;
+   u8 action;
+   u8 aggregate;
+   u8 tx_fifo;
+   u8 window;
+   __le16 ssn;
+   __le16 reserved;
+   __le32 cb_size;
+   __le64 byte_cnt_addr;
+   __le64 tfdq_addr;
+} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_1 */
+
+/**
  * struct iwl_trans_ops - transport specific operations
  *
  * All the handlers MUST be implemented
@@ -640,6 +672,12 @@ struct iwl_trans_ops {
   unsigned int queue_wdg_timeout);
void (*txq_disable)(struct iwl_trans *trans, int queue,
bool configure_scd);
+   /* a000 functions */
+   int (*txq_alloc)(struct iwl_trans *trans,
+struct iwl_tx_queue_cfg_cmd *cmd,
+int cmd_id,
+unsigned int queue_wdg_timeout);
+   void (*txq_free)(struct iwl_trans *trans, int queue);
 
void (*txq_set_shared_mode)(struct iwl_trans *trans, u32 txq_id,
bool shared);
@@ -1057,6 +1095,34 @@ iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int 
queue, u16 ssn,
trans->ops->txq_enable(trans, queue, ssn, cfg, queue_wdg_timeout);
 }
 
+static inline 

[PATCH v2 22/26] iwlwifi: pcie: support new write pointer width

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

In a000 devices we have 16 bytes for the TFD index and 16 for the
queue, in order to support 512 queues.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index af5b97c82c5e..e8eb11282795 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -109,7 +109,7 @@ static void iwl_pcie_gen2_txq_inc_wr_ptr(struct iwl_trans 
*trans,
 */
if (!txq->block)
iwl_write32(trans, HBUS_TARG_WRPTR,
-   txq->write_ptr | (txq->id << 8));
+   txq->write_ptr | (txq->id << 16));
 }
 
 static u8 iwl_pcie_gen2_get_num_tbs(struct iwl_trans *trans,
@@ -825,7 +825,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
txq->read_ptr = (ssn & 0xff);
txq->write_ptr = (ssn & 0xff);
iwl_write_direct32(trans, HBUS_TARG_WRPTR,
-  (ssn & 0xff) | (cmd->scd_queue << 8));
+  (ssn & 0xff) | (cmd->scd_queue << 16));
 
IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d WrPtr: %d\n",
cmd->scd_queue, ssn & 0xff);
-- 
2.11.0



[PATCH v2 19/26] iwlwifi: pcie: support new TX command

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Move to use the correct structure.
Remove code referring to old command.
Update DMA locations.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |  4 ++--
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 10 +-
 2 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 
b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index bd358895caee..912d475ed292 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -205,11 +205,11 @@ struct iwl_cmd_meta {
  * into the buffer regardless of whether it should be mapped or not.
  * This indicates how big the first TB must be to include the scratch buffer
  * and the assigned PN.
- * Since PN location is 16 bytes at offset 24, it's 40 now.
+ * Since PN location is 8 bytes at offset 12, it's 20 now.
  * If we make it bigger then allocations will be bigger and copy slower, so
  * that's probably not useful.
  */
-#define IWL_FIRST_TB_SIZE  40
+#define IWL_FIRST_TB_SIZE  20
 #define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
 
 struct iwl_pcie_txq_entry {
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 3a36bda5fd27..67af73ef7d0d 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -284,14 +284,12 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, 
struct sk_buff *skb,
return 0;
 }
 
-#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(TX_CMD_FLG_MH_PAD)
-
 int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
   struct iwl_device_cmd *dev_cmd, int txq_id)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct ieee80211_hdr *hdr;
-   struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
+   struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
struct iwl_cmd_meta *out_meta;
struct iwl_txq *txq;
dma_addr_t tb0_phys, tb1_phys, scratch_phys;
@@ -345,9 +343,6 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct 
sk_buff *skb,
scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
   offsetof(struct iwl_tx_cmd, scratch);
 
-   tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-   tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_meta = >entries[txq->write_ptr].meta;
out_meta->flags = 0;
@@ -361,9 +356,6 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct 
sk_buff *skb,
len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
  hdr_len - IWL_FIRST_TB_SIZE;
tb1_len = ALIGN(len, 4);
-   /* Tell NIC about any 2-byte padding after MAC header */
-   if (tb1_len != len)
-   tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
 
/*
 * The first TB points to bi-directional DMA data, we'll
-- 
2.11.0



[PATCH v2 12/26] iwlwifi: mvm: support a000 SCD queue configuration

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

a000 devices queue management is going to change significantly.
We will have 512 queues. Those queues will be assigned number
by the firmware and not by the driver.

In addition, due to SN offload having TX queue shared between TIDs
is impossible

Also, the ADD_STA command no longer updates queues status.
The only point of changing queue in the SCD queue config API.

>From driver perspective we have here a new design:

Queue sharing and inactivity checks are disabled.

Once this is done, the only paths that call scd_queue_cfg command
are paths that alloc and release TX queues - which will make future
accommodation to queue number assignment by FW easier.
Since allocating 512 queues statically is not advisable, transport
will allocate the queue on demand, fill the command with DRAM data
and send it. This is reflected in the new transport API.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 .../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h|  5 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c   | 62 --
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c|  3 ++
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 39 +++---
 4 files changed, 96 insertions(+), 13 deletions(-)

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 cd5fdf83d040..4f8648f53879 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -351,7 +351,8 @@ struct iwl_mvm_add_sta_cmd_v7 {
  * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
  * mac-addr.
  * @beamform_flags: beam forming controls
- * @tfd_queue_msk: tfd queues used by this station
+ * @tfd_queue_msk: tfd queues used by this station.
+ * Obselete for new TX API (9 and above).
  * @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.
@@ -386,7 +387,7 @@ struct iwl_mvm_add_sta_cmd {
__le16 rx_ba_window;
u8 scd_queue_bank;
u8 uapsd_trigger_acs;
-} __packed; /* ADD_STA_CMD_API_S_VER_8 */
+} __packed; /* ADD_STA_CMD_API_S_VER_9 */
 
 /**
  * struct iwl_mvm_add_sta_key_common - add/modify sta key common part
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index d538ef0cfd4e..ffbfd34d8e92 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -127,11 +127,17 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct 
ieee80211_sta *sta,
u32 agg_size = 0, mpdu_dens = 0;
 
if (!update || (flags & STA_MODIFY_QUEUES)) {
-   add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
memcpy(_sta_cmd.addr, sta->addr, ETH_ALEN);
 
-   if (flags & STA_MODIFY_QUEUES)
-   add_sta_cmd.modify_mask |= STA_MODIFY_QUEUES;
+   if (!iwl_mvm_has_new_tx_api(mvm)) {
+   add_sta_cmd.tfd_queue_msk =
+   cpu_to_le32(mvm_sta->tfd_queue_msk);
+
+   if (flags & STA_MODIFY_QUEUES)
+   add_sta_cmd.modify_mask |= STA_MODIFY_QUEUES;
+   } else {
+   WARN_ON(flags & STA_MODIFY_QUEUES);
+   }
}
 
switch (sta->bandwidth) {
@@ -337,6 +343,9 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm 
*mvm, int queue,
u8 sta_id;
int ret;
 
+   if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
+   return -EINVAL;
+
spin_lock_bh(>queue_info_lock);
sta_id = mvm->queue_info[queue].ra_sta_id;
spin_unlock_bh(>queue_info_lock);
@@ -387,6 +396,9 @@ static int iwl_mvm_get_queue_agg_tids(struct iwl_mvm *mvm, 
int queue)
 
lockdep_assert_held(>mutex);
 
+   if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
+   return -EINVAL;
+
spin_lock_bh(>queue_info_lock);
sta_id = mvm->queue_info[queue].ra_sta_id;
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
@@ -426,6 +438,9 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm 
*mvm, int queue)
 
lockdep_assert_held(>mutex);
 
+   if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
+   return -EINVAL;
+
spin_lock_bh(>queue_info_lock);
sta_id = mvm->queue_info[queue].ra_sta_id;
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
@@ -468,6 +483,9 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, 
int queue,
 
lockdep_assert_held(>mutex);
 
+   if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
+   return -EINVAL;
+
spin_lock_bh(>queue_info_lock);
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
  

[PATCH v2 18/26] iwlwifi: pcie: cleanup old transport code from gen2

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Cleanup code that is irrelevant for a000 devices.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |   4 -
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 195 +++--
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c   |   8 +-
 3 files changed, 30 insertions(+), 177 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 
b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index b9afffae8a4d..bd358895caee 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -766,10 +766,6 @@ void iwl_pcie_synchronize_irqs(struct iwl_trans *trans);
 bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans);
 void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
 int iwl_queue_space(const struct iwl_txq *q);
-int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
-   struct iwl_txq *txq, u8 hdr_len,
-   struct iwl_cmd_meta *out_meta,
-   struct iwl_device_cmd *dev_cmd, u16 tb1_len);
 
 /* transport gen 2 exported functions */
 int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 2ddaf7a1a1b5..3a36bda5fd27 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -98,88 +98,23 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans 
*trans,
 static void iwl_pcie_gen2_txq_inc_wr_ptr(struct iwl_trans *trans,
 struct iwl_txq *txq)
 {
-   struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-   u32 reg = 0;
-   int txq_id = txq->id;
-
lockdep_assert_held(>lock);
 
-   /*
-* explicitly wake up the NIC if:
-* 1. shadow registers aren't enabled
-* 2. NIC is woken up for CMD regardless of shadow outside this function
-* 3. there is a chance that the NIC is asleep
-*/
-   if (!trans->cfg->base_params->shadow_reg_enable &&
-   txq_id != trans_pcie->cmd_queue &&
-   test_bit(STATUS_TPOWER_PMI, >status)) {
-   /*
-* wake up nic if it's powered down ...
-* uCode will wake up, and interrupt us again, so next
-* time we'll skip this part.
-*/
-   reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
-
-   if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-   IWL_DEBUG_INFO(trans,
-  "Tx queue %d requesting wakeup, GP1 = 
0x%x\n",
-  txq_id, reg);
-   iwl_set_bit(trans, CSR_GP_CNTRL,
-   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-   txq->need_update = true;
-   return;
-   }
-   }
+   IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq->id, txq->write_ptr);
 
/*
 * if not in power-save mode, uCode will never sleep when we're
 * trying to tx (during RFKILL, we're not trying to tx).
 */
-   IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->write_ptr);
if (!txq->block)
iwl_write32(trans, HBUS_TARG_WRPTR,
-   txq->write_ptr | (txq_id << 8));
+   txq->write_ptr | (txq->id << 8));
 }
 
-static inline u8 iwl_pcie_gen2_get_num_tbs(struct iwl_trans *trans, void *_tfd)
+static u8 iwl_pcie_gen2_get_num_tbs(struct iwl_trans *trans,
+   struct iwl_tfh_tfd *tfd)
 {
-   if (trans->cfg->use_tfh) {
-   struct iwl_tfh_tfd *tfd = _tfd;
-
-   return le16_to_cpu(tfd->num_tbs) & 0x1f;
-   } else {
-   struct iwl_tfd *tfd = _tfd;
-
-   return tfd->num_tbs & 0x1f;
-   }
-}
-
-static inline dma_addr_t iwl_pcie_gen2_tb_get_addr(struct iwl_trans *trans,
-  void *_tfd, u8 idx)
-{
-   if (trans->cfg->use_tfh) {
-   struct iwl_tfh_tfd *tfd = _tfd;
-   struct iwl_tfh_tb *tb = >tbs[idx];
-
-   return (dma_addr_t)(le64_to_cpu(tb->addr));
-   } else {
-   struct iwl_tfd *tfd = _tfd;
-   struct iwl_tfd_tb *tb = >tbs[idx];
-   dma_addr_t addr = get_unaligned_le32(>lo);
-   dma_addr_t hi_len;
-
-   if (sizeof(dma_addr_t) <= sizeof(u32))
-   return addr;
-
-   hi_len = le16_to_cpu(tb->hi_n_len) & 0xF;
-
-   /*
-* shift by 16 twice to avoid warnings on 32-bit
-* (where this code 

[PATCH v2 23/26] iwlwifi: pcie: remove block and freeze operations from new transport

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

New transport will be used only by op modes that supports
buffer station offload - hence those will never be called.
Clean it up.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c   |  3 ---
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 22 +++---
 2 files changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 16a057398de2..d39ca944f484 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -2925,9 +2925,6 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
 
.txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
.txq_free = iwl_trans_pcie_dyn_txq_free,
-
-   .freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
-   .block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs,
 };
 
 struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c 
b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index e8eb11282795..2019ccda31c4 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -107,9 +107,7 @@ static void iwl_pcie_gen2_txq_inc_wr_ptr(struct iwl_trans 
*trans,
 * if not in power-save mode, uCode will never sleep when we're
 * trying to tx (during RFKILL, we're not trying to tx).
 */
-   if (!txq->block)
-   iwl_write32(trans, HBUS_TARG_WRPTR,
-   txq->write_ptr | (txq->id << 16));
+   iwl_write32(trans, HBUS_TARG_WRPTR, txq->write_ptr | (txq->id << 16));
 }
 
 static u8 iwl_pcie_gen2_get_num_tbs(struct iwl_trans *trans,
@@ -341,19 +339,8 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct 
sk_buff *skb,
 
/* start timer if queue currently empty */
if (txq->read_ptr == txq->write_ptr) {
-   if (txq->wd_timeout) {
-   /*
-* If the TXQ is active, then set the timer, if not,
-* set the timer in remainder so that the timer will
-* be armed with the right value when the station will
-* wake up.
-*/
-   if (!txq->frozen)
-   mod_timer(>stuck_timer,
- jiffies + txq->wd_timeout);
-   else
-   txq->frozen_expiry_remainder = txq->wd_timeout;
-   }
+   if (txq->wd_timeout)
+   mod_timer(>stuck_timer, jiffies + txq->wd_timeout);
IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", txq->id);
iwl_trans_ref(trans);
}
@@ -843,9 +830,6 @@ void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, 
int queue)
 {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-   trans_pcie->txq[queue].frozen_expiry_remainder = 0;
-   trans_pcie->txq[queue].frozen = false;
-
/*
 * Upon HW Rfkill - we stop the device, and then stop the queues
 * in the op_mode. Just for the sake of the simplicity of the op_mode,
-- 
2.11.0



[PATCH v2 10/26] iwlwifi: mvm: support new TX API

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Support the new TX command API for a000 devices.
Command is a very slim version of current TX command.
Generalize iwl_mvm_tx_mpdu to get rid of TX command dependencies.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | 42 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c| 66 --
 2 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
index 85744fa3bd4d..f83ee6e760d0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -32,6 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -124,6 +125,20 @@ enum iwl_tx_flags {
 }; /* TX_FLAGS_BITS_API_S_VER_1 */
 
 /**
+ * enum iwl_tx_cmd_flags - bitmasks for tx_flags in TX command for a000
+ * @IWL_TX_FLAGS_CMD_RATE: use rate from the TX command
+ * @IWL_TX_FLAGS_ENCRYPT_DIS: frame should not be encrypted, even if it belongs
+ * to a secured STA
+ * @IWL_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate
+ * selection, retry limits and BT kill
+ */
+enum iwl_tx_cmd_flags {
+   IWL_TX_FLAGS_CMD_RATE   = BIT(0),
+   IWL_TX_FLAGS_ENCRYPT_DIS= BIT(1),
+   IWL_TX_FLAGS_HIGH_PRI   = BIT(2),
+}; /* TX_FLAGS_BITS_API_S_VER_3 */
+
+/**
  * enum iwl_tx_pm_timeouts - pm timeout values in TX command
  * @PM_FRAME_NONE: no need to suspend sleep mode
  * @PM_FRAME_MGMT: fw suspend sleep mode for 100TU
@@ -301,6 +316,31 @@ struct iwl_tx_cmd {
struct ieee80211_hdr hdr[0];
 } __packed; /* TX_CMD_API_S_VER_6 */
 
+struct iwl_dram_sec_info {
+   __le32 pn_low;
+   __le16 pn_high;
+   __le16 aux_info;
+} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */
+
+/**
+ * struct iwl_tx_cmd_gen2 - TX command struct to FW for a000 devices
+ * ( TX_CMD = 0x1c )
+ * @len: in bytes of the payload, see below for details
+ * @offload_assist: TX offload configuration
+ * @tx_flags: combination of _tx_cmd_flags
+ * @dram_info: FW internal DRAM storage
+ * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
+ * cleared. Combination of RATE_MCS_*
+ */
+struct iwl_tx_cmd_gen2 {
+   __le16 len;
+   __le16 offload_assist;
+   __le32 flags;
+   struct iwl_dram_sec_info dram_info;
+   __le32 rate_n_flags;
+   struct ieee80211_hdr hdr[0];
+} __packed; /* TX_CMD_API_S_VER_7 */
+
 /*
  * TX response related data
  */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index d76cc422b040..279f56bf175f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -475,6 +475,39 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff 
*skb,
 
memset(dev_cmd, 0, sizeof(*dev_cmd));
dev_cmd->hdr.cmd = TX_CMD;
+
+   if (iwl_mvm_has_new_tx_api(mvm)) {
+   struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
+   u16 offload_assist = iwl_mvm_tx_csum(mvm, skb, hdr, info);
+
+   /* padding is inserted later in transport */
+   /* FIXME - check for AMSDU may need to be removed */
+   if (ieee80211_hdrlen(hdr->frame_control) % 4 &&
+   !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
+   offload_assist |= BIT(TX_CMD_OFFLD_PAD);
+
+   cmd->offload_assist |= cpu_to_le16(offload_assist);
+
+   /* Total # bytes to be transmitted */
+   cmd->len = cpu_to_le16((u16)skb->len);
+
+   /* Copy MAC header from skb into command buffer */
+   memcpy(cmd->hdr, hdr, hdrlen);
+
+   if (!info->control.hw_key)
+   cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_ENCRYPT_DIS);
+
+   /* For data packets rate info comes from the fw */
+   if (ieee80211_is_data(hdr->frame_control) && sta)
+   goto out;
+
+   cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_CMD_RATE);
+   cmd->rate_n_flags =
+   cpu_to_le32(iwl_mvm_get_tx_rate(mvm, info, sta));
+
+   goto out;
+   }
+
tx_cmd = (struct iwl_tx_cmd 

[PATCH v2 15/26] iwlwifi: mvm: remove unnecessary debugging from UMAC scan

2017-04-14 Thread Luca Coelho
From: Luca Coelho 

There are several occasions where a scan of the same type is requested
concurrently, so logging every time this happens is just noisy and
unnecessary.  Remove the logging for these cases.

Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index ce6a2b3b021e..9668f945b4e6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1037,11 +1037,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
return -ENOBUFS;
 
-   if (type == mvm->scan_type) {
-   IWL_DEBUG_SCAN(mvm,
-  "Ignoring UMAC scan config of the same type\n");
+   if (type == mvm->scan_type)
return 0;
-   }
 
if (iwl_mvm_has_new_tx_api(mvm))
cmd_size = sizeof(struct iwl_scan_config);
-- 
2.11.0



[PATCH v2 08/26] iwlwifi: mvm: spin off SAR profile selection function

2017-04-14 Thread Luca Coelho
From: Luca Coelho 

For dynamic SAR, we will need to select the current profile from
different places.  In preparation for that, spin the profile selection
code out of iwl_mvm_sar_init().

Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c  |  4 ++
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c  | 73 +++-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h |  1 +
 3 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index d74ae15b2d85..119a3bd92c50 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -2116,6 +2116,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool 
test)
 */
iwl_mvm_update_changed_regdom(mvm);
 
+   if (!unified_image)
+   /*  Re-configure default SAR profile */
+   iwl_mvm_sar_select_profile(mvm, 1, 1);
+
if (mvm->net_detect) {
/* If this is a non-unified image, we restart the FW,
 * so no need to stop the netdetect scan.  If that
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 1679104e19e9..6360361c576d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1123,49 +1123,78 @@ static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm 
*mvm)
return ret;
 }
 
-static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
+int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
 {
struct iwl_dev_tx_power_cmd cmd = {
.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
};
-   int ret, i, j, idx;
+   int i, j, idx;
+   int profs[IWL_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
int len = sizeof(cmd);
 
+   BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS < 2);
+   BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS * IWL_NUM_SUB_BANDS !=
+IWL_MVM_SAR_TABLE_SIZE);
+
if (!fw_has_capa(>fw->ucode_capa, IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
len = sizeof(cmd.v3);
 
-   ret = iwl_mvm_sar_get_wrds_table(mvm);
-   if (ret < 0) {
-   IWL_DEBUG_RADIO(mvm,
-   "SAR BIOS table invalid or unavailable. (%d)\n",
-   ret);
-   /* we don't fail if the table is not available */
-   return 0;
-   }
+   for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
+   struct iwl_mvm_sar_profile *prof;
 
-   /* if profile 0 is disabled, there's nothing else to do here */
-   if (!mvm->sar_profiles[0].enabled)
-   return 0;
+   /* don't allow SAR to be disabled (profile 0 means disable) */
+   if (profs[i] == 0)
+   return -EPERM;
 
-   IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
+   /* we are off by one, so allow up to IWL_MVM_SAR_PROFILE_NUM */
+   if (profs[i] > IWL_MVM_SAR_PROFILE_NUM)
+   return -EINVAL;
 
-   BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS * IWL_NUM_SUB_BANDS !=
-IWL_MVM_SAR_TABLE_SIZE);
+   /* profiles go from 1 to 4, so decrement to access the array */
+   prof = >sar_profiles[profs[i] - 1];
+
+   /* if the profile is disabled, do nothing */
+   if (!prof->enabled) {
+   IWL_DEBUG_RADIO(mvm, "SAR profile %d is disabled.\n",
+   profs[i]);
+   /* if one of the profiles is disabled, we fail all */
+   return -ENOENT;
+   }
 
-   for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
IWL_DEBUG_RADIO(mvm, "  Chain[%d]:\n", i);
for (j = 0; j < IWL_NUM_SUB_BANDS; j++) {
idx = (i * IWL_NUM_SUB_BANDS) + j;
cmd.v3.per_chain_restriction[i][j] =
-   cpu_to_le16(mvm->sar_profiles[0].table[idx]);
+   cpu_to_le16(prof->table[idx]);
IWL_DEBUG_RADIO(mvm, "Band[%d] = %d * .125dBm\n",
-   j, mvm->sar_profiles[0].table[idx]);
+   j, prof->table[idx]);
}
}
 
-   ret = iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, );
-   if (ret)
-   IWL_ERR(mvm, "failed to set per-chain TX power: %d\n", ret);
+   IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
+
+   return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, );
+}
+
+static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
+{
+   int ret;
+
+   ret = iwl_mvm_sar_get_wrds_table(mvm);
+   if (ret < 0) {
+   

[PATCH v2 09/26] iwlwifi: mvm: add support for EWRD (Dynamic SAR) ACPI table

2017-04-14 Thread Luca Coelho
From: Luca Coelho 

Dynamic SAR allows changing TX power limits at runtime to comply with
SAR regulations on multiple form factors (e.g. tablet vs. clamshell
mode).  To support this, a new table was added to ACPI, which is
called Extended Wireless Regulatory Descriptor (EWRD).  This table
allows OEMs to define different TX power profiles for each form-factor
or usage mode.

Read this new table and store it in our SAR profiles table, in
preparation for Dynamic SAR support.

Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c  | 114 +++
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h |  11 ++-
 2 files changed, 108 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 6360361c576d..2a4c952ef01a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -992,8 +992,11 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
 
 #ifdef CONFIG_ACPI
 #define ACPI_WRDS_METHOD   "WRDS"
-#define ACPI_WRDS_WIFI (0x07)
+#define ACPI_EWRD_METHOD   "EWRD"
+#define ACPI_WIFI_DOMAIN   (0x07)
 #define ACPI_WRDS_WIFI_DATA_SIZE   (IWL_MVM_SAR_TABLE_SIZE + 2)
+#define ACPI_EWRD_WIFI_DATA_SIZE   ((IWL_MVM_SAR_PROFILE_NUM - 1) * \
+IWL_MVM_SAR_TABLE_SIZE + 3)
 
 static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
   union acpi_object *table,
@@ -1051,7 +1054,7 @@ static union acpi_object 
*iwl_mvm_sar_find_wifi_pkg(struct iwl_mvm *mvm,
 
domain = _pkg->package.elements[0];
if (domain->type == ACPI_TYPE_INTEGER &&
-   domain->integer.value == ACPI_WRDS_WIFI)
+   domain->integer.value == ACPI_WIFI_DOMAIN)
break;
 
wifi_pkg = NULL;
@@ -1123,6 +1126,78 @@ static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm 
*mvm)
return ret;
 }
 
+static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
+{
+   union acpi_object *wifi_pkg;
+   acpi_handle root_handle;
+   acpi_handle handle;
+   struct acpi_buffer ewrd = {ACPI_ALLOCATE_BUFFER, NULL};
+   acpi_status status;
+   bool enabled;
+   int i, n_profiles, ret;
+
+   root_handle = ACPI_HANDLE(mvm->dev);
+   if (!root_handle) {
+   IWL_DEBUG_RADIO(mvm,
+   "Could not retrieve root port ACPI handle\n");
+   return -ENOENT;
+   }
+
+   /* Get the method's handle */
+   status = acpi_get_handle(root_handle, (acpi_string)ACPI_EWRD_METHOD,
+);
+   if (ACPI_FAILURE(status)) {
+   IWL_DEBUG_RADIO(mvm, "EWRD method not found\n");
+   return -ENOENT;
+   }
+
+   /* Call EWRD with no arguments */
+   status = acpi_evaluate_object(handle, NULL, NULL, );
+   if (ACPI_FAILURE(status)) {
+   IWL_DEBUG_RADIO(mvm, "EWRD invocation failed (0x%x)\n", status);
+   return -ENOENT;
+   }
+
+   wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, ewrd.pointer,
+ACPI_EWRD_WIFI_DATA_SIZE);
+   if (IS_ERR(wifi_pkg)) {
+   ret = PTR_ERR(wifi_pkg);
+   goto out_free;
+   }
+
+   if ((wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) ||
+   (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER)) {
+   ret = -EINVAL;
+   goto out_free;
+   }
+
+   enabled = !!(wifi_pkg->package.elements[1].integer.value);
+   n_profiles = wifi_pkg->package.elements[2].integer.value;
+
+   for (i = 0; i < n_profiles; i++) {
+   /* the tables start at element 3 */
+   static int pos = 3;
+
+   /* The EWRD profiles officially go from 2 to 4, but we
+* save them in sar_profiles[1-3] (because we don't
+* have profile 0).  So in the array we start from 1.
+*/
+   ret = iwl_mvm_sar_set_profile(mvm,
+ _pkg->package.elements[pos],
+ >sar_profiles[i + 1],
+ enabled);
+   if (ret < 0)
+   break;
+
+   /* go to the next table */
+   pos += IWL_MVM_SAR_TABLE_SIZE;
+   }
+
+out_free:
+   kfree(ewrd.pointer);
+   return ret;
+}
+
 int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
 {
struct iwl_dev_tx_power_cmd cmd = {
@@ -1176,6 +1251,18 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int 
prof_a, int prof_b)
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, );
 }
 
+#else /* CONFIG_ACPI */

[PATCH v2 04/26] iwlwifi: mvm: prepare for station count change

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

In a000 devices we will support up to 32 stations.
The max station define is used also for invalid station marking
which makes finding usages of actual maximum station pretty hard
to sort through - change it to be a different define in order
to make future changes easier.
Use also ARRAY_SIZE intead of define when possible.
Do not move yet to 32 stations until firmware do it though.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/coex.c  |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c|  2 +-
 .../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c   |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c   |  2 +-
 .../net/wireless/intel/iwlwifi/mvm/fw-api-mac.h|  4 ++-
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c|  6 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c  |  6 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c  | 16 ++--
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c   | 12 -
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c|  4 +--
 drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c  |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sf.c|  6 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c   | 30 +++---
 drivers/net/wireless/intel/iwlwifi/mvm/tdls.c  | 22 
 drivers/net/wireless/intel/iwlwifi/mvm/tof.c   |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tt.c|  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c|  6 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c |  2 +-
 18 files changed, 66 insertions(+), 62 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 5bdb6c2c8390..49b4418e6c35 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -756,7 +756,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct 
ieee80211_vif *vif,
 * Rssi update while not associated - can happen since the statistics
 * are handled asynchronously
 */
-   if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+   if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA)
return;
 
/* No BT - reports should be disabled */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index d65acfa3b89b..d74ae15b2d85 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1208,7 +1208,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 
mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
-   if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) {
+   if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA) {
/* if we're not associated, this must be netdetect */
if (!wowlan->nd_config) {
ret = 1;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index f4d75ffe3d8a..5d475b4850ae 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -280,7 +280,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
 mvmvif->queue_params[i].uapsd);
 
if (vif->type == NL80211_IFTYPE_STATION &&
-   ap_sta_id != IWL_MVM_STATION_COUNT) {
+   ap_sta_id != IWL_MVM_INVALID_STA) {
struct iwl_mvm_sta *mvm_sta;
 
mvm_sta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index a260cd503200..7b33ff398332 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -330,7 +330,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, 
char __user *user_buf,
 
mutex_lock(>mutex);
 
-   for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+   for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(>mutex));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
index 480a54af4534..d3cdd889c85c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
@@ -73,7 +73,9 @@
 #define NUM_MAC_INDEX  (NUM_MAC_INDEX_DRIVER + 1)
 #define NUM_MAC_INDEX_CDB  (NUM_MAC_INDEX_DRIVER + 2)
 
-#define IWL_MVM_STATION_COUNT  16
+#define IWL_MVM_STATION_COUNT  16
+#define IWL_MVM_INVALID_STA

[PATCH v2 06/26] iwlwifi: mvm: disable multi-queue for a000 devices

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Firmware isn't configuring multi RX queue hardware yet in
the self init mode.
Disable it for now until we have an API that enables it.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 61cafb541554..4c5088643b2b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1240,7 +1240,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
}
 
/* Init RSS configuration */
-   if (iwl_mvm_has_new_rx_api(mvm)) {
+   /* TODO - remove a000 disablement when we have RXQ config API */
+   if (iwl_mvm_has_new_rx_api(mvm) && !iwl_mvm_has_new_tx_api(mvm)) {
ret = iwl_send_rss_cfg_cmd(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to configure RSS queues: %d\n",
-- 
2.11.0



[PATCH v2 03/26] iwlwifi: cleanup unused function

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

iwl_has_secure_boot() isn't getting called anywhere. Clean it up.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/iwl-config.h | 10 --
 1 file changed, 10 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h 
b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 717e089ff036..06034a71a190 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -90,16 +90,6 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_8000,
 };
 
-static inline bool iwl_has_secure_boot(u32 hw_rev,
-  enum iwl_device_family family)
-{
-   /* return 1 only for family 8000 B0 */
-   if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC))
-   return true;
-
-   return false;
-}
-
 /*
  * LED mode
  *IWL_LED_DEFAULT:  use device default
-- 
2.11.0



[PATCH v2 07/26] iwlwifi: mvm: refactor SAR init to prepare for dynamic SAR

2017-04-14 Thread Luca Coelho
From: Haim Dreyfuss 

We are adding support for dynamic TX power tables for SAR (specific
absorption rate) compliance.  Currently, we only support a single
(static) TX power table, which is read from ACPI, and use it
statically.

To prepare for more tables that can be switched dynamically, refactor
the SAR init flow to allow reusage and add the current static table as
a single entry in an array of tables.

Signed-off-by: Haim Dreyfuss 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c  | 155 ---
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h |  17 ++-
 2 files changed, 107 insertions(+), 65 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 4c5088643b2b..1679104e19e9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -990,85 +990,87 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
sizeof(cmd), );
 }
 
-#define ACPI_WRDS_METHOD   "WRDS"
-#define ACPI_WRDS_WIFI (0x07)
-#define ACPI_WRDS_TABLE_SIZE   10
+#ifdef CONFIG_ACPI
+#define ACPI_WRDS_METHOD   "WRDS"
+#define ACPI_WRDS_WIFI (0x07)
+#define ACPI_WRDS_WIFI_DATA_SIZE   (IWL_MVM_SAR_TABLE_SIZE + 2)
+
+static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
+  union acpi_object *table,
+  struct iwl_mvm_sar_profile *profile,
+  bool enabled)
+{
+   int i;
 
-struct iwl_mvm_sar_table {
-   bool enabled;
-   u8 values[ACPI_WRDS_TABLE_SIZE];
-};
+   profile->enabled = enabled;
 
-#ifdef CONFIG_ACPI
-static int iwl_mvm_sar_get_wrds(struct iwl_mvm *mvm, union acpi_object *wrds,
-   struct iwl_mvm_sar_table *sar_table)
+   for (i = 0; i < IWL_MVM_SAR_TABLE_SIZE; i++) {
+   if ((table[i].type != ACPI_TYPE_INTEGER) ||
+   (table[i].integer.value > U8_MAX))
+   return -EINVAL;
+
+   profile->table[i] = table[i].integer.value;
+   }
+
+   return 0;
+}
+
+static union acpi_object *iwl_mvm_sar_find_wifi_pkg(struct iwl_mvm *mvm,
+   union acpi_object *data,
+   int data_size)
 {
-   union acpi_object *data_pkg;
-   u32 i;
+   int i;
+   union acpi_object *wifi_pkg;
 
-   /* We need at least two packages, one for the revision and one
+   /*
+* We need at least two packages, one for the revision and one
 * for the data itself.  Also check that the revision is valid
 * (i.e. it is an integer set to 0).
-   */
-   if (wrds->type != ACPI_TYPE_PACKAGE ||
-   wrds->package.count < 2 ||
-   wrds->package.elements[0].type != ACPI_TYPE_INTEGER ||
-   wrds->package.elements[0].integer.value != 0) {
-   IWL_DEBUG_RADIO(mvm, "Unsupported wrds structure\n");
-   return -EINVAL;
+*/
+   if (data->type != ACPI_TYPE_PACKAGE ||
+   data->package.count < 2 ||
+   data->package.elements[0].type != ACPI_TYPE_INTEGER ||
+   data->package.elements[0].integer.value != 0) {
+   IWL_DEBUG_RADIO(mvm, "Unsupported packages structure\n");
+   return ERR_PTR(-EINVAL);
}
 
/* loop through all the packages to find the one for WiFi */
-   for (i = 1; i < wrds->package.count; i++) {
+   for (i = 1; i < data->package.count; i++) {
union acpi_object *domain;
 
-   data_pkg = >package.elements[i];
+   wifi_pkg = >package.elements[i];
 
/* Skip anything that is not a package with the right
 * amount of elements (i.e. domain_type,
-* enabled/disabled plus the sar table size.
+* enabled/disabled plus the actual data size.
 */
-   if (data_pkg->type != ACPI_TYPE_PACKAGE ||
-   data_pkg->package.count != ACPI_WRDS_TABLE_SIZE + 2)
+   if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
+   wifi_pkg->package.count != data_size)
continue;
 
-   domain = _pkg->package.elements[0];
+   domain = _pkg->package.elements[0];
if (domain->type == ACPI_TYPE_INTEGER &&
domain->integer.value == ACPI_WRDS_WIFI)
break;
 
-   data_pkg = NULL;
+   wifi_pkg = NULL;
}
 
-   if (!data_pkg)
-   return -ENOENT;
-
-   if (data_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
-   return -EINVAL;
-
-   sar_table->enabled = !!(data_pkg->package.elements[1].integer.value);
-

[PATCH v2 00/26] iwlwifi: updates intended for v4.12 2017-04-13

2017-04-14 Thread Luca Coelho
From: Luca Coelho 

Hi,

This is v2 of the second patch set intended for v4.12.  These are the
changes:

 * A large amount of work on the A000 device series;
 * A couple of cleanup patches;
 * Dynamic SAR support;

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

In v2, I fixed SAR compilation when CONFIG_ACPI is not set (thanks to
kbuildbot) and also squashed some other SAR fixes.

Please review.

Cheers,
Luca.


Emmanuel Grumbach (1):
  iwlwifi: mvm: tell the firmware about the U-APSD parameters

Goodstein, Mordechay (1):
  iwlwifi: mvm: move new API code to the end

Haim Dreyfuss (1):
  iwlwifi: mvm: refactor SAR init to prepare for dynamic SAR

Luca Coelho (3):
  iwlwifi: mvm: spin off SAR profile selection function
  iwlwifi: mvm: add support for EWRD (Dynamic SAR) ACPI table
  iwlwifi: mvm: remove unnecessary debugging from UMAC scan

Sara Sharon (20):
  iwlwifi: mvm: read new secure boot registers
  iwlwifi: mvm: add queues after adding station
  iwlwifi: cleanup unused function
  iwlwifi: mvm: prepare for station count change
  iwlwifi: mvm: use same scan API for all a000 devices
  iwlwifi: mvm: disable multi-queue for a000 devices
  iwlwifi: mvm: support new TX API
  iwlwifi: pcie: introduce a000 TX queues management
  iwlwifi: mvm: support a000 SCD queue configuration
  iwlwifi: mvm: support moving to mgmt tid
  iwlwifi: pcie: copy TX functions to new transport
  iwlwifi: pcie: cleanup old transport code from gen2
  iwlwifi: pcie: support new TX command
  iwlwifi: pcie: rewrite TFD creation
  iwlwifi: pcie: support host commands in new transport
  iwlwifi: pcie: support new write pointer width
  iwlwifi: pcie: remove block and freeze operations from new transport
  iwlwifi: pcie: prepare for dynamic queue allocation
  iwlwifi: pcie: introduce new stop_device
  iwlwifi: pcie: alloc queues dynamically

 drivers/net/wireless/intel/iwlwifi/Makefile|   2 +-
 drivers/net/wireless/intel/iwlwifi/iwl-config.h|  10 -
 drivers/net/wireless/intel/iwlwifi/iwl-prph.h  |   2 +
 drivers/net/wireless/intel/iwlwifi/iwl-trans.h |  71 +-
 drivers/net/wireless/intel/iwlwifi/mvm/coex.c  |   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c|   6 +-
 .../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c   |   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c   |   2 +-
 .../net/wireless/intel/iwlwifi/mvm/fw-api-mac.h|   4 +-
 .../net/wireless/intel/iwlwifi/mvm/fw-api-scan.h   |  14 +-
 .../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h|  16 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h |  42 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c| 318 +--
 drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c  |   6 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c  |  16 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h   |  27 +-
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c   |  12 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c|  71 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c  |   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/scan.c  |  85 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sf.c|   6 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c   | 192 ++--
 drivers/net/wireless/intel/iwlwifi/mvm/tdls.c  |  22 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tof.c   |   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tt.c|   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c|  84 +-
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c |  45 +-
 .../net/wireless/intel/iwlwifi/pcie/ctxt-info.c|   2 +-
 drivers/net/wireless/intel/iwlwifi/pcie/internal.h |  42 +-
 drivers/net/wireless/intel/iwlwifi/pcie/rx.c   |   9 +-
 .../net/wireless/intel/iwlwifi/pcie/trans-gen2.c   | 147 +++
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c|  48 +-
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c  | 996 +
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c   | 207 ++---
 34 files changed, 2026 insertions(+), 488 deletions(-)
 create mode 100644 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c

-- 
2.11.0



[PATCH v2 01/26] iwlwifi: mvm: read new secure boot registers

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Addresses were changed for a000 devices.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/iwl-prph.h |  2 ++
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c   | 13 ++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h 
b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index bb7e0d642981..e1aa1f7836fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -400,6 +400,8 @@ enum aux_misc_master1_en {
 #define PREG_AUX_BUS_WPROT_0   0xA04CC0
 #define SB_CPU_1_STATUS0xA01E30
 #define SB_CPU_2_STATUS0xA01E34
+#define UMAG_SB_CPU_1_STATUS   0xA038C0
+#define UMAG_SB_CPU_2_STATUS   0xA038C4
 
 /* FW chicken bits */
 #define LMPM_CHICK 0xA01FF8
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index e481bb050c6e..6adbd4bcb40a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -639,11 +639,18 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm 
*mvm,
ret = iwl_wait_notification(>notif_wait, _wait,
MVM_UCODE_ALIVE_TIMEOUT);
if (ret) {
-   if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+   struct iwl_trans *trans = mvm->trans;
+
+   if (trans->cfg->gen2)
+   IWL_ERR(mvm,
+   "SecBoot CPU1 Status: 0x%x, CPU2 Status: 
0x%x\n",
+   iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
+   iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS));
+   else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 
0x%x\n",
-   iwl_read_prph(mvm->trans, SB_CPU_1_STATUS),
-   iwl_read_prph(mvm->trans, SB_CPU_2_STATUS));
+   iwl_read_prph(trans, SB_CPU_1_STATUS),
+   iwl_read_prph(trans, SB_CPU_2_STATUS));
mvm->cur_ucode = old_type;
return ret;
}
-- 
2.11.0



[PATCH v2 02/26] iwlwifi: mvm: add queues after adding station

2017-04-14 Thread Luca Coelho
From: Sara Sharon 

Currently aux & broadcast queues are added before calling add
station, which results with a SCD_QUEUE_CFG command sent with
a station id unknown yet to fw.
While this works for pre-a000 firmware, the a000 fw requires
the order to be reversed.
The reason the change is only for a000 devices and not for
previous devices is that we cannot reverse the order since
the tfd_queue_mask containing the aux queue will cause FW to
assert on adding a queue mask with a queue that is not enabled.
This is not a problem in a000 fw since the tfd_queue_mask was
removed from the add sta API.

Signed-off-by: Sara Sharon 
Signed-off-by: Luca Coelho 
---
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 90 ++--
 1 file changed, 58 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 2d68cee41306..7d6a5dbb50ca 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1700,25 +1700,11 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm 
*mvm,
return ret;
 }
 
-int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
+static void iwl_mvm_enable_aux_queue(struct iwl_mvm *mvm)
 {
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
mvm->cfg->base_params->wd_timeout :
IWL_WATCHDOG_DISABLED;
-   int ret;
-
-   lockdep_assert_held(>mutex);
-
-   /* Map Aux queue to fifo - needs to happen before adding Aux station */
-   if (!iwl_mvm_is_dqa_supported(mvm))
-   iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue,
- IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
-
-   /* Allocate aux station and assign to it the aux queue */
-   ret = iwl_mvm_allocate_int_sta(mvm, >aux_sta, BIT(mvm->aux_queue),
-  NL80211_IFTYPE_UNSPECIFIED);
-   if (ret)
-   return ret;
 
if (iwl_mvm_is_dqa_supported(mvm)) {
struct iwl_trans_txq_scd_cfg cfg = {
@@ -1731,14 +1717,43 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
 
iwl_mvm_enable_txq(mvm, mvm->aux_queue, mvm->aux_queue, 0, ,
   wdg_timeout);
+   } else {
+   iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue,
+ IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
}
+}
 
-   ret = iwl_mvm_add_int_sta_common(mvm, >aux_sta, NULL,
-MAC_INDEX_AUX, 0);
+int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
+{
+   int ret;
+
+   lockdep_assert_held(>mutex);
 
+   /* Allocate aux station and assign to it the aux queue */
+   ret = iwl_mvm_allocate_int_sta(mvm, >aux_sta, BIT(mvm->aux_queue),
+  NL80211_IFTYPE_UNSPECIFIED);
if (ret)
+   return ret;
+
+   /* Map Aux queue to fifo - needs to happen before adding Aux station */
+   if (!iwl_mvm_has_new_tx_api(mvm))
+   iwl_mvm_enable_aux_queue(mvm);
+
+   ret = iwl_mvm_add_int_sta_common(mvm, >aux_sta, NULL,
+MAC_INDEX_AUX, 0);
+   if (ret) {
iwl_mvm_dealloc_int_sta(mvm, >aux_sta);
-   return ret;
+   return ret;
+   }
+
+   /*
+* For a000 firmware and on we cannot add queue to a station unknown
+* to firmware so enable queue here - after the station was added
+*/
+   if (iwl_mvm_has_new_tx_api(mvm))
+   iwl_mvm_enable_aux_queue(mvm);
+
+   return 0;
 }
 
 int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -1789,22 +1804,21 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, 
struct ieee80211_vif *vif)
struct iwl_mvm_int_sta *bsta = >bcast_sta;
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr;
+   int queue = 0;
int ret;
+   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_VO,
+   .sta_id = mvmvif->bcast_sta.sta_id,
+   .tid = IWL_MAX_TID_COUNT,
+   .aggregate = false,
+   .frame_limit = IWL_FRAME_LIMIT,
+   };
 
lockdep_assert_held(>mutex);
 
if (iwl_mvm_is_dqa_supported(mvm)) {
-   struct iwl_trans_txq_scd_cfg cfg = {
-   .fifo = IWL_MVM_TX_FIFO_VO,
-   .sta_id = mvmvif->bcast_sta.sta_id,
-   .tid = IWL_MAX_TID_COUNT,
-   .aggregate = false,
-   .frame_limit = IWL_FRAME_LIMIT,
-   };
-

Email change

2017-04-14 Thread Michal Kazior
Hi everyone,

I'm parting ways with Tieto today so my email is going  to become
defunct. I'll be reachable via: kazikcz at gmail dot com.


Michał