Adding DSA support to TP-Link Archer C7 v4/ whole ath79 tree

Hey Everyone!

I'd like to get some help from you guys, I'm trying to add support for DSA on my router Archer C7, I've been modifying the device DTS file and I'm getting nowhere since the changes I make so far get me these errors in the kernel log:

[    0.499018] libphy: Fixed MDIO Bus: probed
[    1.190109] libphy: ag71xx_mdio: probed
[    1.197041] switch0: Atheros AR8337 rev. 2 switch registered on mdio-bus.0
[    1.204213] Atheros AR8216/AR8236/AR8316: probe of mdio-bus.0:00 failed with error -22
[    1.215299] ar8327: qca,phy-rgmii-en is not specified
[    1.222046] ar8327: qca,phy-rgmii-en is not specified
[    1.227744] ag71xx 19000000.eth: Could not find valid phy node

I know some stuff, but this is garbage to me since it's device tree coding and I've never done that before.
Can someone help me?
I've been using a branch in my github to make those changes, this is the link to the file:


If I can make it and maybe Openwrt believes it's usefull it can be merged in trunk as DSA is super usefull, simpler to deploy and simpler to understand.

Thanks for the help!

4 Likes

Well, I got no reply but I have been experimenting in the meanwhile. This is my configured dts:

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>

#include "qca956x.dtsi"

/ {
	compatible = "tplink,archer-c7-v4", "qca,qca9563";
	model = "TP-Link Archer C7 v4";

	chosen {
		bootargs = "console=ttyS0,115200n8";
	};

	aliases {
		led-boot = &system;
		led-failsafe = &system;
		led-running = &system;
		led-upgrade = &system;
		label-mac-device = &eth0;
	};

	led_spi {
		compatible = "spi-gpio";
		#address-cells = <1>;
		#size-cells = <0>;

		sck-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;	// 74HC595 SRCLK (Serial Clock)
		mosi-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;	// 74HC595 SER (Serial)
		cs-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;		// 74HC595 RCLK (Register Clock)
		num-chipselects = <1>;

		led_gpio: led_gpio@0 {
			compatible = "fairchild,74hc595";
			reg = <0>;
			gpio-controller;
			#gpio-cells = <2>;
			registers-number = <1>;
			spi-max-frequency = <10000000>;
		};
	};

	gpio-export {
		compatible = "gpio-export";

		gpio_shift_register_oe {
			gpio-export,name = "tp-link:oe:sr";
			gpio-export,output = <0>;
			gpios = <&gpio 1 GPIO_ACTIVE_LOW>;	// 74HC595 /OE (Output Enable)
		};

		gpio_shift_register_reset {
			gpio-export,name = "tp-link:reset:sr";
			gpio-export,output = <1>;
			gpios = <&gpio 21 GPIO_ACTIVE_LOW>;	// 74HC595 /SRCLR (Serial Clear)
		};
	};

	leds {
		compatible = "gpio-leds";

		system: system {
			label = "tp-link:green:system";
			gpios = <&gpio 6 GPIO_ACTIVE_LOW>;
			default-state = "on";
		};

		usb1 {
			label = "tp-link:green:usb1";
			gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
			trigger-sources = <&hub_port1>;
			linux,default-trigger = "usbport";
		};

		usb2 {
			label = "tp-link:green:usb2";
			gpios = <&gpio 7 GPIO_ACTIVE_LOW>;
			trigger-sources = <&hub_port0>;
			linux,default-trigger = "usbport";
		};

		wlan5g {
			label = "tp-link:green:wlan5g";
			gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy0tpt";
		};

		wlan2g {
			label = "tp-link:green:wlan2g";
			gpios = <&led_gpio 7 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "phy1tpt";
		};

		wan {
			label = "tp-link:green:wan";
			gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>;
		};

		wan_fail {
			label = "tp-link:orange:wan";
			gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>;
		};

		lan1 {
			label = "tp-link:green:lan1";
			gpios = <&led_gpio 4 GPIO_ACTIVE_LOW>;
		};

		lan2 {
			label = "tp-link:green:lan2";
			gpios = <&led_gpio 3 GPIO_ACTIVE_LOW>;
		};

		lan3 {
			label = "tp-link:green:lan3";
			gpios = <&led_gpio 2 GPIO_ACTIVE_LOW>;
		};

		lan4 {
			label = "tp-link:green:lan4";
			gpios = <&led_gpio 1 GPIO_ACTIVE_LOW>;
		};

		wps {
			label = "tp-link:green:wps";
			gpios = <&led_gpio 0 GPIO_ACTIVE_LOW>;
		};
	};

	keys {
		compatible = "gpio-keys";

		reset {
			label = "Reset button";
			linux,code = <KEY_RESTART>;
			gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
			debounce-interval = <60>;
		};

		wps {
			label = "WPS button";
			linux,code = <KEY_WPS_BUTTON>;
			gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
			debounce-interval = <60>;
		};
	};
};

&pcie {
	status = "okay";
};

&uart {
	status = "okay";
};

&gpio {
	status = "okay";
};

&usb_phy0 {
	status = "okay";
};

&usb0 {
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";

	hub_port0: port@1 {
		reg = <1>;
		#trigger-source-cells = <0>;
	};
};

&usb_phy1 {
	status = "okay";
};

&usb1 {
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";

	hub_port1: port@1 {
		reg = <1>;
		#trigger-source-cells = <0>;
	};
};

&spi {
	status = "okay";
	num-cs = <1>;

	flash@0 {
		compatible = "jedec,spi-nor";
		reg = <0>;
		spi-max-frequency = <25000000>;

		partitions {
			compatible = "fixed-partitions";
			#address-cells = <1>;
			#size-cells = <1>;

			partition@0 {
				label = "factory-uboot";
				reg = <0x000000 0x020000>;
				read-only;
			};

			partition@20000 {
				label = "u-boot";
				reg = <0x020000 0x020000>;
				read-only;
			};

			partition@40000 {
				label = "firmware";
				reg = <0x040000 0xec0000>;
				compatible = "denx,uimage";
			};

			info: partition@f00000 {
				label = "info";
				reg = <0xf00000 0x0f0000>;
				read-only;
			};

			art: partition@ff0000 {
				label = "art";
				reg = <0xff0000 0x010000>;
				read-only;
			};
		};
	};
};

&mdio0 {
	status = "okay";

  phy_port1: phy@1 {
  	reg = <0>;
  };

  phy_port2: phy@2 {
  	reg = <1>;
  };

  phy_port3: phy@3 {
  	reg = <2>;
  };

  phy_port4: phy@4 {
  	reg = <3>;
  };

  phy_port5: phy@5 {
  	reg = <4>;
  };

	switch0@0 {
		compatible = "qca,qca8337";
		#address-cells = <1>;
		#size-cells = <0>;

		reg = <0>;

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				label = "cpu";
				ethernet = <&eth0>;
				phy-mode = "sgmii";
				qca,mib-poll-interval = <500>;
				fixed-link {
					speed = <1000>;
					full-duplex;
				};
			};

			port@1 {
				reg = <1>;
				label = "wan";
				phy-handle = <&phy_port1>;
			};

			port@2 {
				reg = <2>;
				label = "lan1";
				phy-handle = <&phy_port2>;
			};

			port@3 {
				reg = <3>;
				label = "lan2";
				phy-handle = <&phy_port3>;
			};

			port@4 {
				reg = <4>;
				label = "lan3";
				phy-handle = <&phy_port4>;
			};

			port@5 {
				reg = <5>;
				label = "lan4";
				phy-handle = <&phy_port5>;
			};
		};
	};
};

	&eth0 {
		status = "okay";

		phy-mask = <0>;

		pll-data = <0x03000101 0x00000101 0x00001919>;

		phy-mode = "sgmii";
		mtd-mac-address = <&info 0x8>;
		fixed-link {
			speed = <1000>;
			full-duplex;
		};
};

&wmac {
	status = "okay";
	mtd-cal-data = <&art 0x1000>;
	mtd-mac-address = <&info 0x8>;
};

But there are some issues, when linux detects eth0 it doesn't detect the switch and vice versa, any help from developers? @blogic I've read that you made transition for IPQ8xxx devices, could you help me?

1 Like

Hi everyone,

Since I have seen some people like my main post I decided to write something.

I managed to get DSA working on Archer C7 v4, although I read somewhere that vlans weren't working it is indeed working.

If anyone wants to checkout my work you can do it here:

I hope somebody can use it!

PS: I currently don't have my archer c7 working so I can't test these changes but I usually rebase the branch against master

5 Likes

Wow, that's quite a feat! Based on your work I decided to try with my WDR4300 and Archer C7v2. The latter has two CPU ports - I think I might need to backport some patches to support multiple CPU ports through DSA, but even without that, the setup should work at single CPU port.

I really, really wonder, why there was so little interest for conversion of existing ath79 devices to DSA so far.

2 Likes

I believe that that's an issue that's easy to solve... the patches going around allow the user to select which ports are bound to a port, but that doesn't seem like a proper solution because the bandwidth might be wasted, instead the ports should be bound together in a low level link aggregation in a round-robin fashion, and then that link aggregation interface should be used as the CPU port. Unfortunately, I do not have the knowledge in coding to perform this...

It will work perfectly, from my experience it works great, the only thing that would make it better would be qca8k routing offloading like there is in some mediatek targets. I have seen that blogic has made some work with this https://git.openwrt.org/?p=openwrt/staging/blogic.git;a=commit;h=dd3bdac6d1dcd98d4d494052f7df31ca21558d6f but since then the linux kernel has added a proper api to offload stuff with the iptables-offload/nftables-offload modules and his work has unfortunately become obsolete.

I have no idea either, these devices would very much benefit from DSA

1 Like

I reviewed the upstream driver and got the explanation - the work is going on, but there is still a lot to be done, only beginning to be ready to move ath79 target.

Regarding CPU link aggregation, this makes sense - this way combination of any two ports could sustain full-duplex gigabit traffic through CPU port, at least in theory, not just WAN<->LAN. I haven't had a chance to dig in this deep, though, and I don't know if QCA8337 et al, support this.

Anyway, I tried building an image for WDR4300 as a test, and it crashed - I haven't had time to debug this, yet. I have one question as well: how did you derive MDIO address for the switch? Is it always 16? This doesn't correspond to previous entries in device tree. It'd be nice if you could take a quick look at my patches here: https://github.com/Leo-PL/openwrt/commits/ath79-dsa - I imported your patch and split the kernel configuration part and device-specific part as well.

A friend of mine, with quite substantial background on DSA and WDR4300 on hand, told me he's willing to do some work on this, first to get DSA running, and then on the offloading part.

3 Likes

I took another attempt on building an image for my WDR4300 and C7v2, but still wonder form where did the MDIO address 16 came from, other than copying stuff from @blogic's tree.

Could you please post a boot log from your unit running DSA? Would definitely help me map the connections for my devices.

1 Like

Fairly WIP. Only tested on C7v2. Probably works with v1 as well. v4 and v5 use a different switch AFAIK.

edit: some of the commits prior to that one are also needed...

edit2: https://github.com/neheb/openwrt/commits/mangix everything after mt76 update.

I must say that you've done amazing work, I hope to see it merged soon!
I now have my archer c7 v4 working again and am available for any testing! :smiley:

that unit has qca8337n IIRC. @Ansuel is looking for someone with that unit to test hardware offload.

1 Like

I'm here to test! Where can I get a build/source to build, and what are the tests?

@neheb @Ansuel I have a spare Archer C7 v4 doing nothing, let me know where to get the source/patches.

I will give the GitHub.com/Leo-Pl ath79-dsa branch a go for the time being.

https://github.com/openwrt/openwrt/pull/4622 is the most up to date branch.

1 Like

So I am now using your ath79-dsa branch. Boots just find on my Archer C7 v4. Lan-Lan normal speed 940-ish mbps. Lan-Wan not great: around 330-ish. Clearly HW-Nat is not enabled and I couldn't find any patches that suggest that it was added. Software and Hardware offload both ticked.

Another observation (not related to DSA): I can't use wlan0 (5ghz) in client-mode any more. This was working before and is still working on my Zyxel NB6817 which seems to use the same driver.

[   62.388256] wlan0: authenticate with d4:5f:25:eb:ce:5a
[   62.398528] wlan0: send auth to d4:5f:25:eb:ce:5a (try 1/3)
[   62.405381] wlan0: authenticated
[   62.411423] wlan0: associate with d4:5f:25:eb:ce:5a (try 1/3)
[   62.418551] wlan0: RX AssocResp from d4:5f:25:eb:ce:5a (capab=0x831 status=0 aid=2)
[   62.427724] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
[   62.435029] ath10k_pci 0000:00:00.0: failed to enable peer stats info: -122
[   62.442267] wlan0: associated
[   68.618606] wlan0: deauthenticated from d4:5f:25:eb:ce:5a (Reason: 15=4WAY_HANDSHAKE_TIMEOUT)
[   68.641529] ath10k_pci 0000:00:00.0: mac flush null vif, drop 0 queues 0xffff
[   91.465445] wlan0: authenticate with d4:5f:25:eb:ce:5a
[   91.475772] wlan0: send auth to d4:5f:25:eb:ce:5a (try 1/3)
[   91.482285] wlan0: authenticated
[   91.491460] wlan0: associate with d4:5f:25:eb:ce:5a (try 1/3)
[   91.498526] wlan0: RX AssocResp from d4:5f:25:eb:ce:5a (capab=0x831 status=0 aid=2)
[   91.507643] ath10k_pci 0000:00:00.0: pdev param 0 not supported by firmware
[   91.514948] ath10k_pci 0000:00:00.0: failed to enable peer stats info: -122
[   91.522418] wlan0: associated
[   97.698239] wlan0: deauthenticated from d4:5f:25:eb:ce:5a (Reason: 15=4WAY_HANDSHAKE_TIMEOUT)

Speaking of the NB6817: is the wiki correct that is has the AR8337 switch without "N" for hardware NAT, but is using the same DSA driver? LAN-WAN speeds on that device is higher (better CPU). (using Ansuel git ipq806x-dsa branch)

multiple people have reported speed problems with routing. iperf performance is higher than with the swconfig driver. I have no idea if that's only for qca8337. I only have qca8327 units.

HWNAT is not implemented yet.

I believe the ipq stuff doesn't have the N variant. The ipq stuff uses a separate networking processor that doesn't have an upstream driver.

c7 v4 and v5 should come with ar8337n/ qca8337n, according to the FCC images.

I thought @Ansuel was looking for test devices for experimental HWNAT. I will wait for him to tell us where to get those patches.

AR8229 will have DSA?

https://git.openwrt.org/?p=openwrt/staging/blocktrron.git;a=shortlog;h=refs/heads/dsa-ar9344

Needs testing. Probably will happen in release after next.

Is there any plan to get hwnat working and getting better speeds lan--> wan?

Also If you need testing I have a c7 v5 that I can use for testing!