Meraki MR24 swap wifi mPCIe card ath9k --> ath10k

Hello community,
I got two Meraki MR24 I've read somewhere over at reddit, that maybe it is possible to swap out the old atheros 5GHz card with a new 802.11ac one.

I've installed a Compex WLE900VX and installed kmod-ath10k, ath10k-firmware-qca988x and ath10k-board-qca988x but lspci only shows the 2.4 GHz card. I think I've missed something, but I'm not sure how to look further.

Or is the only solution to build a custom image with ath10k integrated?

You'll have to make sure that the calibration data handling is correct, prevent the calibration data from the old ath9k card being loaded and make sure that the calibration data of your new card gets applied (depends on the card, if it's on an internal flash or needs to be extracted from the donor device). Other things might involve non-standard mini-PCIe slots (required signals missing, non-standard power requirements, too much heat, etc.). Yes, you can do most of these things at runtime, but in practice you probably do want to patch your device specifications at buildtime already (for convenience reasons).

1 Like

Thanks for the input, sounds scary :sweat_smile:

But maybe you can guide me a bit further. I took a look at the device tree file, there's a hardcoded PCI-ID, I'm not sure if it is really necessary to change it. DTS files aren't something completely new for me, but my knowledge, if one wants to really call it like that, is about adding devices to i2c, and that's it.

&PCIE0 {
	status = "okay";
	/*
	 * relevant lspci topology:
	 *
	 *	-+-[0000:40]---00.0-[41-7f]----00.0-[42-45]--+-02.0-[43]----00.0
	 *	                                             +-03.0-[44]----00.0
	 *
	 */

	bridge@64,0 {
		reg = <0x00400000 0 0 0 0>;
		#address-cells = <3>;
		#size-cells = <2>;
		ranges;

		bridge@65,0 {
			/* IDT PES3T3 PCI Express Switch */
			compatible = "pci111d,8039";
			reg = <0x00410000 0 0 0 0>;
			#address-cells = <3>;
			#size-cells = <2>;
			ranges;

			bridge@66,2 {
				compatible = "pci111d,8039";
				reg = <0x00421000 0 0 0 0>;
				#address-cells = <3>;
				#size-cells = <2>;
				ranges;

				wifi0: wifi@67,0 {
					/* Atheros AR9380 2.4GHz */
					compatible = "pci168c,0030";
					reg = <0x00430000 0 0 0 0>;
					interrupts = <3>; /* INTC 4.1.1 */
				};
			};

			bridge@66,3 {
				compatible = "pci111d,8039";
				reg = <0x00421800 0 0 0 0>;
				#address-cells = <3>;
				#size-cells = <2>;
				ranges;

				wifi1: wifi@68,0 {
					/* Qualcomm QCA9880 5GHz */
					compatible = "pci168c,003c";
					reg = <0x00440000 0 0 0 0>;
					interrupts = <4>; /* INTD 4.1.1 */
				};
			};
		};
	};
};

I've changed the PCI-ID and recompiled it like this (incl. the ath10k stuff), but that would've been to easy. lspci still only shows the 2.4GHz ath9k card. If I'm correct, two additional devices are added besides the wifi card itself. But correct me if I'm wrong:

pci 0000:03:00.0: [168c:003c] type 00 class 0x028000
pci 0000:03:00.0: reg 0x10: [mem 0xc0000000-0xc01fffff 64bit]
pci 0000:03:00.0: reg 0x30: [mem 0xc0200000-0xc020ffff pref]

Source: https://bugzilla.kernel.org/show_bug.cgi?id=84821#c12

And some additional info about the card itself:

02:00.0 0280: 168c:003c
	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 51
	Region 0: Memory at df800000 (64-bit, non-prefetchable) [size=2M]
	Expansion ROM at dfa00000 [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: fee0f00c  Data: 41a2
		Masking: fffefffe  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, Latency L0 <4us, L1 <64us
			ClockPM- Surprise- LLActRep- BwNot-
		LnkCtl:	ASPM Disabled; RCB 64 bytes Disabled- Retrain- 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=ff
			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

Maybe this information could help to bring me one step further. I really appreciate the support. :slight_smile:

I used the commands below and it worked for me. The original information was available here: https://groups.google.com/g/ptp-general/c/1EeHhPiD6fE/m/zheuq1UEDQAJ

SSH into The MR24.
# touch /etc/modules.d/ath10k
# echo  "ath10k_pci irq_mode=1" >> "/etc/modules.d/ath10k"
# opkg update
# opkg install kmod-ath10k-ct
# opkg install ath10k-firmware-qca988x-ct
# reboot

You no longer need irq_mode=1 ("legacy interrupts only") because MSI has been disabled on the apm821xx target, at least on snapshot.

The problem is your card. See this Bugzilla thread. The card thinks it should be off because of the state of pin 20 (floating? up? down? not even sure.). The solution is to scrape off the lead from the contact on pin 20 going out to the motherboard; verify it is cut using a continuity tester.

See this page for the pinout.

From what I remember @riptidewave93 tested this with his MR24 back in the day.

He found out that no, sadly you can't change the minipcie wifi cards. For some reason only the meraki ath9k pcie cards that came with the MR24 worked. :cry:

I had better luck with the Netgear WNDAP620 + 660. They both have minipcie slots.
But unlike the MR24, the QCA9880v2 minipcie I put in there showed up on boot.

I actually use an MR24 with the 5GHz card swapped for a Compex WLE900VX (or I was using it until it started negotiation only 10Mbps on eth0 due to a bad ethernet cable). It's very likely this particular Compex card was also used by @riptidewave93 (it was the most available QCA9880v2 as an individual module for a long time); the card is more distinctive for caring about the state of pin 20 than the device itself is for wiring it differently than mPCIe physical interfaces usually are wired.

Again, it's required to sever the lead for pin 20 in order for the card to work with this board. Once that's done it just works.

1 Like