Mini PCIe Module QCA9880 WPEA-352ACN 802.11AC Dual Band Wireless WiFi network card support Linux (WHL #39)

While I’m in the “X doesn’t do Y, so let’s hotchpotch DIY something to get Z running” mindset, let’s release something else that I’m slightly bitter about. WiFi network cards. [scroll down to the first image to skip my rambly introduction]

I’m not a big fan of Intel for their business practices, but when it comes to Consumer/Prosumer network cards, Intel is basically the brand to get. I’m running a CT Gigabit (82574L) addon card in my AMD ZFS server, and my old Thinkpad has something similar (82567LM) built in. I’ve also been using WiFi cards ever since the 2200BG series, and while there were shitty driver packages along the way, there never was a “you’re fucked, the manufacturer doesn’t support your card/system combo” moment. If an Intel network card needed to work, there was a way. I know several examples with other manufacturers that do not work at all to this day. And there were cases where I removed working WiFi cards from family equipment to replace it with an Intel part to avoid future failures due to upgrades. So Intel was the brand I pretty much trust in LAN/WLAN applications. 2100A, 2200BG, 3945ABG, 4965AGN, WiFi link 1000, 5100, 5300, Ultimate 6300, you name it.

But: Intel, for whatever reason, does not release a friggen 3×3 ac card. They just don’t. If you want 3×3, you’re stuck at WiFi-n (e.g. my 6300 card – so 450 Mb/s unless you run into Linux driver issues that disable the third antenna). If you want ac speeds, you’re stuck at 2×2 (e.g. 7260 – so 867 Mb/s in the 5 GHz bands or 300 Mb/s in 2.4 GHz). My T400 does have three antennas, why would I go back to 2 antennas when 3x3n is still so abundant and I only take advantage of ac when at home?

Well, as discussed previously, I accidentally upgraded my internet connection to VDSL100 speeds, meaning 100 Mb/s download and 30-something Mb/s upload. 3x3n supports that – barely. If you’re not in the optimal spot, the WiFi limits your internet connection speed (and the air isn’t really crowded in here, I’m not living in a big city with dozens of active WiFi networks that interfere with your own). It doesn’t really matter if the WiFi limits your 4k UHD streams to the bathroom to three instead of four supported by your internet connection, but as a nerd, I cannot let that happen. I needed to upgrade, so I bought a Mikrotik wAP ac access point (RBwAPG-5HacT2HnD – no review planned, but feel free to ask) and replaced the single 2.4G WiFi of my FritzBox router with that.

And I wouldn’t have done that if I were stuck with 3x3n or 2x2ac WiFi. I finally found a suitable card – based on the Qualcomm Atheros QCA9880 chipset, called the WPEA-352ACN.

Yeah, what does that unshapely plastic container say? Oh, right, Intel… :roll: Looks like original packaging straight from the factory…

Ah well, that aside, it’s like in the seller’s description. One full-sized mPCIe card for 19.97€ (including tracked shipping) from AliExpress, bought in early March, arrived in late March. It is an WPEA-352ACN card, which seems no different to the WPEQ-353ACNI model that is specced with a broader operating temperature for industrial use. It’s pretty much a NoName/generic model in reference design; other companies like SparkLAN or Compex put a nice sticker on it and sell it as their own. It is important to note that this is v2 hardware, as v1 is deprecated in the driver package (see below). Don’t get v1 hardware! Also, don’t get hardware that doesn’t comply with the mPCIe form factor. There are plenty of QCA cards out there that have huge heat sinks for use in dedicated router hardware, but these will not fit your laptop. And with their huge power amps, they probably shouldn’t…

Back side of the board is equally boring, just a few passives. Plotech seems to be a PCB manufacturer for prototypes and also mass production, which might be a good choice given the relatively low production numbers of these WiFi cards.

So I swapped my old Intel 6300 (half-size) for that puppy, and here’s the T400 from the inside…

(I would have tried dual operation, but apparently the QCA chipset dies when there’s an antenna missing. I could have used some others from older machines, but hey, why bother setting up a dual-WiFi setup in the first place…)

Soo…the card is identified correctly using Kubuntu 16.04 LTS:

sudo lspci -vvv | grep Qual -A60
03:00.0 Network controller: Qualcomm Atheros QCA986x/988x 802.11ac Wireless Network Adapter
Physical Slot: 1-1
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 35
Region 0: Memory at f4200000 (64-bit, non-prefetchable) [size=2M]
[virtual] Expansion ROM at c0400000 [disabled] [size=64K]
Capabilities: [40] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=375mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/8 Maskable+ 64bit-
Address: fee0100c Data: 4183
Masking: 00fe00fe Pending: 00000000
Capabilities: [70] Express (v2) Endpoint, MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s unlimited, L1 <64us
ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <4us, L1 <64us
ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk+
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR-, OBFF Not Supported
DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-
Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
Compliance De-emphasis: -6dB
LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
Capabilities: [100 v1] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
Capabilities: [140 v1] Virtual Channel
Caps: LPEVC=0 RefClk=100ns PATEntryBits=1
Arb: Fixed- WRR32- WRR64- WRR128-
Ctrl: ArbSelect=Fixed
Status: InProgress-
VC0: Caps: PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
Arb: Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256-
Ctrl: Enable+ ID=0 ArbSelect=Fixed TC/VC=01
Status: NegoPending- InProgress-
Capabilities: [160 v1] Device Serial Number 00-00-00-00-00-00-00-00
Kernel driver in use: ath10k_pci
Kernel modules: ath10k_pci

Serial number 0 looks quite professional. Hardware ID is 168c:003c.

Driver is ath10k, which can be found here: https://wireless.wiki.kernel.org/en/users/drivers/ath10k

However, first startup was not successful. I had an older ath10k driver package installed, which isn’t that unusual for a LTS version that is maintained for quite some time. In this case, the WiFi card wouldn’t even turn on:


ath10k_pci 0000:03:00.0: device has crashed during init
ath10k_pci 0000:03:00.0: device has crashed during init
ath10k_pci 0000:03:00.0: failed to wait for target init: -70
ath10k_pci 0000:03:00.0: failed to warm reset attempt 1 of 3: -70
ath10k_pci 0000:03:00.0: device has crashed during init
ath10k_pci 0000:03:00.0: device has crashed during init
ath10k_pci 0000:03:00.0: failed to wait for target init: -70
ath10k_pci 0000:03:00.0: failed to warm reset attempt 2 of 3: -70
ath10k_pci 0000:03:00.0: device has crashed during init
ath10k_pci 0000:03:00.0: device has crashed during init
ath10k_pci 0000:03:00.0: firmware crashed! (uuid 3532ccf7-411f-45b4-b3a7-c4049f3b43c0)
ath10k_pci 0000:03:00.0: qca988x hw2.0 target 0x4100016c chip_id 0x043202ff sub 0000:0000
ath10k_pci 0000:03:00.0: kconfig debug 0 debugfs 1 tracing 1 dfs 0 testmode 0
ath10k_pci 0000:03:00.0: firmware ver 10.2.4.70.9-2 api 5 features no-p2p,raw-mode crc32 b8d50af5
ath10k_pci 0000:03:00.0: board_file api 1 bmi_id N/A crc32 bebc7c08
ath10k_pci 0000:03:00.0: htt-ver 2.1 wmi-op 5 htt-op 2 cal otp max-sta 128 raw 0 hwcrypto 1
ath10k_pci 0000:03:00.0: failed to read firmware dump area: -16
ath10k_pci 0000:03:00.0: Copy Engine register dump:
ath10k_pci 0000:03:00.0: [00]: 0x00057400 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [01]: 0x00057800 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [02]: 0x00057c00 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [03]: 0x00058000 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [04]: 0x00058400 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [05]: 0x00058800 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [06]: 0x00058c00 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: [07]: 0x00059000 3735928559 3735928559 3735928559 3735928559
ath10k_pci 0000:03:00.0: failed to reset chip: -70
ath10k_pci 0000:03:00.0: Could not init hif: -70

This scared me a little, but it’s actually a firmware problem. Visit the wiki above and download a newer version, and the card comes to life.

IPv6: ADDRCONF(NETDEV_UP): wlp3s0: link is not ready
wlp3s0: authenticate with 08:[...]
wlp3s0: send auth to 08:[...] (try 1/3)
wlp3s0: authenticated
wlp3s0: associate with 08:[...](try 1/3)
wlp3s0: RX AssocResp from 08:[...] (capab=0x431 status=0 aid=1)
wlp3s0: associated
IPv6: ADDRCONF(NETDEV_CHANGE): wlp3s0: link becomes ready
ath: EEPROM regdomain: 0x8114
ath: EEPROM indicates we should expect a country code
ath: doing EEPROM country->regdmn map search
ath: country maps to regdmn code: 0x37
ath: Country alpha2 being used: DE
ath: Regpair used: 0x37
ath: regdomain 0x8114 dynamically updated by country IE
wlp3s0: AP 08:[...] changed bandwidth, new config is 2472 MHz, width 1 (2472/0 MHz)
wlp3s0: AP 08:[...] changed bandwidth, new config is 2472 MHz, width 2 (2462/0 MHz)

(stupid wlp3s0 re-naming – moved that to wlan0 as soon as I could!)

Now, as said in the intro, I prefer Intel NICs to everything else, and this proves to be true once more. This card isn’t without flaws, and I cannot tell if that is a firmware or hardware issue. I use standby a lot instead of rebooting my machine every day, so I perform a sleep cycle basically every day. Quite often, the WiFi card doesn’t wake up properly:

DHCPDISCOVER on wlp3s0 to 255.255.255.255 port 67 interval 3 (xid=0xad6ede75)
send_packet: Network is down
dhclient.c:2098: Failed to send 300 byte long packet over wlp3s0 interface.

The connection seems still active, but it’s completely dead. I now have a reset script in place that can be run whenever that happens – I’m thinking about moving that into the wakeup procedures.

#!/bin/bash
sudo ifdown wlan0
sudo modprobe -r ath10k_pci
sudo modprobe -r ath10k_core
sudo modprobe ath10k_pci
sudo modprobe ath10k_core
sleep 5
sudo ethtool -i wlan0
sudo ifup wlan0

On the down side, this went wrong one time. I ran the script and everything froze. And by everything, I mean everything. I’m running thinkfan instead of the native fan control, and that froze, too. But the CPU was still active. Not much, but as the fan was stopped, the notebook eventually did an emergency shut-off while I was in the shower, waiting for the laptop to recover. Turns out it didn’t recover – and when I picked it up from the couch, it was TOASTY. After blowing in the fan holes and starting back up (which takes some time due to the encrypted system partition the the now defunct key-derivation), the CPU still reported 80°C. Wow, huge bullet dodged…

(the card has a temperature sensor itself, athk10_hwmon, which is picked up by xsensors – nice!)

The wakeup problems seem to correlate with firmware version. I used the newest one (10.2.4.70.66) first, and that one didn’t always stop on sleep/wakeup. 10.2.4.70.61-2 does have this issue basically on every cycle. I’m now testing 10.2.4.70.59-2 as seen below, and I just realized that this week 10.2.4.70.67 was published, so I will have a go with that as well.

sudo ethtool -i wlan0
driver: ath10k_pci
version: 4.13.0-38-generic
firmware-version: 10.2.4.70.59-2
expansion-rom-version:
bus-info: 0000:03:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

10.2.4.70.61-2 is not compatible with more than one IP, so once wlan0:1 is ifup’d, the card will play dead as well. It does seem to work, but the existing wlan0 connection is dead as a dodo, and upon ifdown/ifup, it doesn’t connect anymore:

wlan0: authenticate with cc:[...]
[458227.297538] wlan0: send auth to cc:[...] (try 1/3)
[458227.298003] wlan0: authenticated
[458227.300089] wlan0: associate with cc:[...] (try 1/3)
[458227.301777] wlan0: RX AssocResp from cc:[...] (capab=0x431 status=0 aid=1)
[458227.303081] wlan0: associated
[458227.305076] wlan0: deauthenticating from cc:[...] by local choice (Reason: 3=DEAUTH_LEAVING)

Running the reset as shown above will stop the deauths instantly. Not sure if other firmware does the same, but it was for performance testing only, virtually nobody needs to bind more than one address to one physical network interface.

Now, for the performance data…running netio 1.32 (although displayed otherwise) is probably the easiest one if you have two machines. So this was done with the WiFi card -(5GHz)-> Mikrotik wAP -(Gigabit)-> FritzBox -(Gigabit)-> second Linux machine.

WiFi machine acting as server:

TCP connection established ...
Receiving from client, packet size 1k ... 28.07 MByte/s
Sending to client, packet size 1k ... 3794.36 KByte/s
Receiving from client, packet size 2k ... 26.36 MByte/s
Sending to client, packet size 2k ... 5205.82 KByte/s
Receiving from client, packet size 4k ... 26.39 MByte/s
Sending to client, packet size 4k ... 6623.69 KByte/s
Receiving from client, packet size 8k ... 26.71 MByte/s
Sending to client, packet size 8k ... 6195.32 KByte/s
Receiving from client, packet size 16k ... 26.59 MByte/s
Sending to client, packet size 16k ... 6904.42 KByte/s
Receiving from client, packet size 32k ... 26.05 MByte/s
Sending to client, packet size 32k ... 7839.76 KByte/s
Done.

UDP connection established ...
Receiving from client, packet size 1k ... 32.32 MByte/s
Sending to client, packet size 1k ... 42.78 MByte/s
Receiving from client, packet size 2k ... 23.86 MByte/s
Sending to client, packet size 2k ... 22.48 MByte/s
Receiving from client, packet size 4k ... 36.01 MByte/s
Sending to client, packet size 4k ... 31.70 MByte/s
Receiving from client, packet size 8k ... 30.09 MByte/s
Sending to client, packet size 8k ... 38.18 MByte/s
Receiving from client, packet size 16k ... 27.61 MByte/s
Sending to client, packet size 16k ... 43.29 MByte/s
Receiving from client, packet size 32k ... 28.49 MByte/s
Sending to client, packet size 32k ... 47.42 MByte/s
Done.

And as client:
TCP connection established.
Packet size 1k bytes: 3699.58 KByte/s Tx, 25.48 MByte/s Rx.
Packet size 2k bytes: 4197.67 KByte/s Tx, 25.90 MByte/s Rx.
Packet size 4k bytes: 5298.00 KByte/s Tx, 26.62 MByte/s Rx.
Packet size 8k bytes: 4261.33 KByte/s Tx, 23.07 MByte/s Rx.
Packet size 16k bytes: 5618.67 KByte/s Tx, 24.84 MByte/s Rx.
Packet size 32k bytes: 9111.42 KByte/s Tx, 24.74 MByte/s Rx.
Done.

UDP connection established.
Packet size 1k bytes: 24.58 MByte/s (0%) Tx, 37.16 MByte/s (65%) Rx.
Packet size 2k bytes: 20.28 MByte/s (0%) Tx, 16.76 MByte/s (80%) Rx.
Packet size 4k bytes: 29.00 MByte/s (0%) Tx, 35.46 MByte/s (68%) Rx.
Packet size 8k bytes: 35.87 MByte/s (0%) Tx, 32.96 MByte/s (68%) Rx.
Packet size 16k bytes: 41.63 MByte/s (0%) Tx, 27.35 MByte/s (72%) Rx.
Packet size 32k bytes: 46.36 MByte/s (0%) Tx, 32.07 MByte/s (71%) Rx.
Done.

So doing 25 MB/s (200Mb/s) of ACK’d TCP traffic or 45 MB/s (360Mb/s) of “in your face” UDP traffic doesn’t look too shabby, but it could be better. A lot better. However, I cannot say where to optimize first, this might be a settings problem on the computers involved, or some AP or router settings that are not optimal. I actually encountered a routing problem between the two computers (192.168.0 and .2 subnets in a /24 configuration) and fixed that by telling the FritzBox how to route to the .2 subnet that is managed by the wAP. I still have an open issue with the wAP, but that is not affecting performance at the moment, I think.

So, with 200 Mb/s of throughput, I’m well above my DSL line speed again. Upgrade cost me about 110-120 bucks in total (20 for the card, 75 for the AP, and I’ll run both Fritz and AP on a single power supply, so that’ll be a separate blog) and a lot of hours to make everything work again and do some performance tests. The WiFi card caused the most trouble with the firmware stuff, so all in all I wouldn’t recommend this to the ordinary user – mainly because there might not be a Windows driver available, and also because of the firmware stuff explained earlier, which might or might not resolve over time. After all, it’s Qualcomm, and Qualcomm is not Intel. Did I mention that Intel needs to release a 3×3 ac ASAP? ;-)


Leave a Reply

Your email address will not be published. Required fields are marked *

:mrgreen: 
:neutral: 
:twisted: 
:arrow: 
:shock: 
:smile: 
:???: 
:cool: 
:evil: 
:grin: 
:idea: 
:oops: 
:razz: 
:roll: 
;-) 
:cry: 
:eek: 
:lol: 
:mad: 
:sad: 
:suspect: 
:!: 
:?: 
:bye: 
:good: 
:negative: 
:scratch: 
:wacko: 
:yahoo: 
:heart: 
B-) 
:rose: 
:whistle: 
:yes: 
:cry2: 
:mail: 
:-(( 
:unsure: 
:wink: