Broadcom switch config with Freescale LS1012A

Hello,

I have a custom board based on Freescale (NXP) LS1012ARDB reference design, but mine has a Broadcom BCM53128 connected to the CPU via the RGMII bus.

First question: Should I be using the driver in ../drivers/net/phy/b53
or the DSA driver in ../drivers/net/dsa/b53?

I'm currently using the DSA driver, and that leads to my second question: Is my device tree correct (partly shown below)? I'm very confused on how I should set this up. I'm currently only using one mac port, and I commented out the two SGMII and RGMII sections that are used by the reference design board.

I can see that the switch is found. "b53_common: found switch: BCM53128, rev 4" is displayed during boot up. But right now I'm also seeing "bcm53xx ls1012a-0:1e: failed to register switch: -517".
That error is EPROBE_DEFER. I won't get into the specifics of my attempts to debug the code generating that error. I just want to start by getting my device tree correct.

Any help would be extremely appreciated. Thanks,
Joel

#include "fsl-ls1012a.dtsi"

/ {
	model = "LS1012A RDB Board";
	compatible = "fsl,ls1012a-rdb", "fsl,ls1012a";

	aliases {
//		ethernet0 = &pfe_mac0;
		ethernet1 = &pfe_mac1;
	};
-----
&pfe {
	status = "okay";
	#address-cells = <1>;
	#size-cells = <0>;

	pfe_mac1: ethernet@1 {
		compatible = "fsl,pfe-gemac-port";
		#address-cells = <1>;
		#size-cells = <0>;
		reg = <0x1>;	/* GEM_ID */
		fsl,mdio-mux-val = <0x0>;
		phy-mode = "rgmii-txid";
		fixed-link {
		    speed = <1000>;
         	    full-duplex;
     	 	};
	};
	mdio@0 {
		#address-cells = <1>;
		#size-cells = <0>;

//		sgmii_phy: ethernet-phy@1 {   // JAC - was 2
//			reg = <0x1>;          // JAC - was 2
//		};

//		rgmii_phy: ethernet-phy@1 {   // JAC -was 1
//			reg = <0x1E>;         //  JAC -was 1
//		};
		
		switch0: ethernet-switch@1e {
			compatible = "brcm,bcm53128";
			reg = <30>;
			dsa,member = <0 0>;
			
			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				
				port0@0 {
					reg = <0>;
					label = "lan1";
				};
				port1@1 {
					reg = <1>;
					label = "lan2";
				};
				port2@2 {
					reg = <2>;
					label = "lan3";
				};
				port3@3 {
					reg = <3>;
					label = "lan4";
				};
				port4@4 {
					reg = <4>;
					label = "lan5";
				};
				port5@5 {
					reg = <5>;
					label = "lan6";
				};
				port6@6 {
					reg = <6>;
					label = "lan7";
				};
				port7@7 {
					reg = <7>;
					label = "lan8";
				};
				port8@8 {
					reg = <8>;
					label = "cpu";
					ethernet = <&pfe_mac1>;
					fixed-link {
						speed = <1000>;
						duplex-full;
					};
				};
			};
		};
	};
};
1 Like

I only quickly glanced at it and whatever you assign to reg properties needs to equal the part after it's node's @ sign which is not the case, at least not everywhere.
Anyway, you may find good examples of a DSA switch configurations in @Ansuel 's DSA pull request for the IPQ806x here.
Good luck!

the switch configuration is for dsa driver (AFAIK)
Anyway probe defer is not really an error... (it should not be reported with a good driver)
With probe defer, the kernel just retry to probe the driver after some time...

Anyway to transition from a swconfig to a dsa config you should first check how it's init in the swconfig driver and check if the dsa driver does the same thing.

(I would also advice to check if there are some example in the kernel documentation about this dsa driver... And i would also advice to try (if not impossible) to make the dsa driver work since this is the future (1?!?!?) and dsa driver are present upstream and are better maintainable than swconfg driver that can't be proposed upstream)

Thank you for replying.

I think the problem is that the EPROBE_DEFER is happening more than once and it eventually gives up.

I have traced back to the code that is failing.

Step 1:
Function dsa_port_parse_of calls of_find_net_device_by_node(ethernet), where "ethernet" is a device_node* returned from of_parse_phandle.

Step 2:
Then of_find_net_device_by_node calls class_find_device to locate the device associated with "ethernet" (I think).

Step 3:
class_find_device iterates a couple of times and finds a device, then it calls the callback function of_dev_node_match.

Finally:
of_dev_node_match takes the device found in step 3 (dev) and compares dev->parent->of_node to "data", where data is the "ethernet" device_node pointer from step 1 cast as a "const void *". These two things do not match.

My question is, what are the two things that are being compared? I think it parses the device tree and finds the "ethernet" phandle, correct? In my device tree I have ethernet=<&pfe_eth1>.
I printed out dev->parent->of_node->name and it is "pfe".

I don't understand what these two things are, and why don't they match? The fact that they do not match is what causes EPROBE_DEFER.

I hope that made sense. I didn't want to copy and paste many pages of code. Any help would be very much appreciated.

Thank you,
Joel

Thank you for pointing that out. I now have:

switch0: ethernet-switch@30 {
			compatible = "brcm,bcm53128";
			reg = <30>;

But I still have the problem described in my reply to Ansuel.

Please let me know if you have any other suggestions.
Thanks again,
Joel

you need to find the cause of the probe defer... honestly the function you notice doesn't look a direct cause of the probe defer.

It's from step 1 of my description above.
dsa_port_parse_of is shown below. It is returning EPROBE_DEFER. So my long description lists all the functions that get called before two things are compared and determined not to match. That causes
of_find_net_device_by_node to return NULL. Thus the EPROBE_DEFER.
But I don't understand what is being compared and why.

Thanks,
Joel

static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
{
	struct device_node *ethernet = of_parse_phandle(dn, "ethernet", 0);
	const char *name = of_get_property(dn, "label", NULL);
	bool link = of_property_read_bool(dn, "link");

	dp->dn = dn;

	if (ethernet) {
		struct net_device *master;
		master = of_find_net_device_by_node(ethernet);
		if (!master) {
			pr_info("returning EPROBE_DEFER \n"); // JAC
			return -EPROBE_DEFER;
		}

		return dsa_port_parse_cpu(dp, master);
	}

Actually, I think it was supposed to be this:

switch0: ethernet-switch@1e {
			compatible = "brcm,bcm53128";
			reg = <0x1e>;

I suggest for you to have a look at e.g. the following examples:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts#n137

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/bcm47094-linksys-panamera.dts#n134

I got past the probe defer error. It now appears to be loading the driver and there are no error messages. ifconfig -a now shows all the lan ports that were not listed before. I see "bcm53xx ls1012a-0:1e lan1: Link is Up" when I plug in a cable. But I still can't ping. There is no response. The other end of the cable is connected to a laptop running Wireshark and I see nothing there. I'm pretty sure this is just a configuration problem, but I have no experience in this area, so I'm looking for any clues

root@OpenWrt:/etc/config# ping 192.168.1.20
PING 192.168.1.20 (192.168.1.20): 56 data bytes
^C
--- 192.168.1.20 ping statistics ---
10 packets transmitted, 0 packets received, 100% packet loss
root@OpenWrt:/etc/config# ifconfig
br-lan    Link encap:Ethernet  HWaddr 00:04:9F:06:75:9E
          inet6 addr: fe80::204:9fff:fe06:759e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:746 (746.0 B)

eth0      Link encap:Ethernet  HWaddr 00:04:9F:06:75:9E
          inet6 addr: fe80::204:9fff:fe06:759e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:54 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:4500 (4.3 KiB)

eth0.1    Link encap:Ethernet  HWaddr 00:04:9F:06:75:9E
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:746 (746.0 B)

lan1      Link encap:Ethernet  HWaddr 00:00:00:00:00:00
          inet addr:192.168.1.2  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::200:ff:fe00:0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:29 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:1818 (1.7 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:1529 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1529 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:105072 (102.6 KiB)  TX bytes:105072 (102.6 KiB)

Here's my etc/config/network:

root@OpenWrt:/etc/config# cat network

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config interface 'lan'
        option type 'bridge'
        option ifname 'eth0.1'
        option proto 'static'
        option ipaddr '192.168.1.1;
        option netmask '255.255.255.0'

config globals 'globals'
        option ula_prefix 'fdb7:4e06:d363::/48'

config  switch
        option name 'switch0'
        option 'enable_vlan' '1'

config  switch_vlan
        option device 'switch0'
        option vlan '1'
        option ports '0 1 2 3 4 5 6 7 8t'

Any help at all would be greatly appreciated. I'm stuck.

Thanks,
Joel

Whats the control protocol of switch

I struggle with the same problem but with different switch. PFE driver is so crappy...

In my case help change line ethernet = <&pfe_mac1>; to ethernet = <&pfe>; . After that change, there's no "-517". But it binds DSA to eth0 instead eth1.

Then you need to change what you reference as ethernet node.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/bcm47094-linksys-panamera.dts#n182

And that is the problem with this driver. Interfaces have nodes pfe_mac0 and pfe_mac1. But when I use it, driver return -517. When I put &pfe node which is whole controller, driver start, but with wrong interface. It's impossible to bind do eth1.

That is just a probe deferral and should not really be an issue. You are saying it really does not work then? Maybe some probe deferral bug. I used to fix countless such a few years back but would expect this to work quite nicely nowadays.

Hello, I also encountered the same problem, may I ask how you finally solved it