lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211218214954.109755-1-colin.foster@in-advantage.com>
Date:   Sat, 18 Dec 2021 13:49:41 -0800
From:   Colin Foster <colin.foster@...advantage.com>
To:     linux-gpio@...r.kernel.org, netdev@...r.kernel.org,
        linux-kernel@...r.kernel.org
Cc:     Linus Walleij <linus.walleij@...aro.org>,
        Russell King <linux@...linux.org.uk>,
        Heiner Kallweit <hkallweit1@...il.com>,
        Jakub Kicinski <kuba@...nel.org>,
        "David S. Miller" <davem@...emloft.net>,
        Florian Fainelli <f.fainelli@...il.com>,
        Vivien Didelot <vivien.didelot@...il.com>,
        Andrew Lunn <andrew@...n.ch>, UNGLinuxDriver@...rochip.com,
        Alexandre Belloni <alexandre.belloni@...tlin.com>,
        Claudiu Manoil <claudiu.manoil@....com>,
        Vladimir Oltean <vladimir.oltean@....com>,
        Lee Jones <lee.jones@...aro.org>
Subject: [RFC v5 net-next 00/13] add support for VSC75XX control over SPI

The patch set in general is to add support for the VSC7511, VSC7512,
VSC7513 and VSC7514 devices controlled over SPI. The driver is
believed to be fully functional for the internal phy ports (0-3) 
on the VSC7512. As I'll discuss, it is not yet functional for other
ports yet.


V5 is an overhaul of the framework. Instead of struct spi_device being
called directly into drivers/net/dsa/ocelot/ocelot_spi.c, it is now done
through drivers/net/mfd/ocelot-spi.c. The MFD layer is handled in
drivers/net/mfd/ocelot-core.c. At the end of this patch set, three
optional devices are supported: ocelot-pinctrl to control pins, 
mdio-mscc-miim to communicate on the external MDIO bus, and
ocelot-ext to manage the switch.

This structure seems to really clean things up. "ocelot_ext" comes in
around 650 lines now, down from 950 in v4. Much of that has moved to
ocelot-spi.c. All references to SPI have been removed from ocelot_ext. I
know lines of a file isn't a great metric of software design quality,
but I think they are related in this case.

My hope at the end of this RFC is to be able to split this into several
smaller patch sets. One set would add MFD + pinctrl, and possibly MDIO.
To the best of my current knowledge those drivers are functionally
complete and possibly ready for full "PATCH" status instead of RFC. 

Of note: the MFD uses hard-coded resources, while the MMIO version uses
DTS resources. If nothing else, I'll update the relevant documentation
accordingly.

A separate patch set would be to add switch capabilities. Since the
external phys are now functional, I can turn my focus to those
additional ports. 

That leads to a direct question: Is it acceptable to do switch
capabilities in two patch sets? Set 1 would add internal phy
functionality that currently works, set 2 would add PCS / SGMII support
to ports 4-7? For full transparency: I don't have Fib{re,er} 
hardware so I don't plan to develop that support. I simply won't be able
to test it.

As I mentioned in the last RFC:
The hardware setup I'm using for development is a beaglebone black, with
jumpers from SPI0 to the microchip VSC7512 dev board. The microchip dev 
board has been modified to not boot from flash, but wait for SPI. An
ethernet cable is connected from the beaglebone ethernet to port 0 of
the dev board.


The device tree I'm using for the VSC7512 is below, and has changed in
architecture significantly since V4:

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

	ocelot-chip@0 {
		compatible = "mscc,vsc7512_mfd_spi";
		spi-max-frequency = <250000>;
		reg = <0>;

		ethernet-switch@0 {
			compatible = "mscc,vsc7512-ext-switch";
			ports {
				#address-cells = <1>;
				#size-cells = <0>;

				port@0 {
					reg = <0>;
					label = "cpu";
					status = "okay";
					ethernet = <&mac_sw>;
					phy-handle = <&sw_phy0>;
					phy-mode = "internal";
				};

				port@1 {
					reg = <1>;
					label = "swp1";
					status = "okay";
					phy-handle = <&sw_phy1>;
					phy-mode = "internal";
				};

				port@2 {
					reg = <2>;
					label = "swp2";
					status = "okay";
					phy-handle = <&sw_phy2>;
					phy-mode = "internal";
				};

				port@3 {
					reg = <3>;
					label = "swp3";
					status = "okay";
					phy-handle = <&sw_phy3>;
					phy-mode = "internal";
				};

				port@4 {
					reg = <4>;
					label = "swp4";
					status = "okay";
					phy-handle = <&sw_phy4>;
					phy-mode = "sgmii";
				};

				port@5 {
					reg = <5>;
					label = "swp5";
					status = "okay";
					phy-handle = <&sw_phy5>;
					phy-mode = "sgmii";
				};

				port@6 {
					reg = <6>;
					label = "swp6";
					status = "okay";
					phy-handle = <&sw_phy6>;
					phy-mode = "sgmii";
				};

				port@7 {
					reg = <7>;
					label = "swp7";
					status = "okay";
					phy-handle = <&sw_phy7>;
					phy-mode = "sgmii";
				};
			};


			mdio {
				#address-cells = <1>;
				#size-cells = <0>;

				sw_phy0: ethernet-phy@0 {
					reg = <0x0>;
				};

				sw_phy1: ethernet-phy@1 {
					reg = <0x1>;
				};

				sw_phy2: ethernet-phy@2 {
					reg = <0x2>;
				};

				sw_phy3: ethernet-phy@3 {
					reg = <0x3>;
				};
			};
		};

		mdio1: mdio1 {
			compatible = "mscc,ocelot-miim";
			pinctrl-names = "default";
			pinctrl-0 = <&miim1>;
			#address-cells = <1>;
			#size-cells = <0>;

			sw_phy4: ethernet-phy@4 {
				reg = <0x4>;
			};

			sw_phy5: ethernet-phy@5 {
				reg = <0x5>;
			};

			sw_phy6: ethernet-phy@6 {
				reg = <0x6>;
			};

			sw_phy7: ethernet-phy@7 {
				reg = <0x7>;
			};
		};

		gpio: pinctrl@0 {
			compatible = "mscc,ocelot-pinctrl";
			gpio-controller;
			#gpio_cells = <2>;
			gpio-ranges = <&gpio 0 0 22>;

			led_shift_reg_pins: led-shift-reg-pins {
				pins = "GPIO_0", "GPIO_1", "GPIO_2", "GPIO_3";
				function = "sg0";
			};

			miim1: miim1 {
				pins = "GPIO_14", "GPIO_15";
				function = "miim";
			};
		};

        /* Non-functional at the moment */
		sgpio: sgpio {
			compatible = "mscc,ocelot-sgpio";
			bus-frequency=<12500000>;
			clocks = <&ocelot_clock>;
			microchip,sgpio-port-ranges = <0 31>;

			sgpio_in0: sgpio@0 {
				compatible = "microchip,sparx5-sgpio-bank";
				reg = <0>;
				gpio-controller;
				#gpio-cells = <3>;
				ngpios = <32>;
			};

			sgpio_out1: sgpio@1 {
				compatible = "microchip,sparx5-sgpio-bank";
				reg = <1>;
				gpio-controller;
				gpio-cells = <3>;
				ngpios = <32>;
			};
		};
	};
};



The relevant boot log for the switch / MDIO bus is here. Of note: ports
4-7 are now properly probed before the switch comes up.

[    1.357533] SPI driver ocelot_mfd_spi has no spi_device_id for mscc,vsc7514_mfd_spi
[    1.357561] SPI driver ocelot_mfd_spi has no spi_device_id for mscc,vsc7513_mfd_spi
[    1.357571] SPI driver ocelot_mfd_spi has no spi_device_id for mscc,vsc7512_mfd_spi
[    1.357581] SPI driver ocelot_mfd_spi has no spi_device_id for mscc,vsc7511_mfd_spi
[    3.159000] ocelot_mfd_spi spi0.0: configured SPI bus for speed 250000, rx padding bytes 0
[    3.167549] ocelot_mfd_spi spi0.0: initializing SPI interface for chip
[    3.175088] ocelot_mfd_spi spi0.0: resetting ocelot chip
[    3.301006] ocelot_mfd_spi spi0.0: initializing SPI interface for chip
[    3.309537] pinctrl-ocelot pinctrl-ocelot: DMA mask not set
[    3.315694] gpiochip_find_base: found new base at 2026
[    3.315737] gpio gpiochip4: (ocelot-gpio): created GPIO range 0->21 ==> pinctrl-ocelot PIN 0->21
[    3.321957] gpio gpiochip4: (ocelot-gpio): added GPIO chardev (254:4)
[    3.322059] gpio gpiochip4: registered GPIOs 2026 to 2047 on ocelot-gpio
[    3.322076] pinctrl-ocelot pinctrl-ocelot: driver registered
[    3.331370] mscc-miim ocelot-miim1: DMA mask not set
[    3.337044] mdio_bus ocelot-miim1-mii: GPIO lookup for consumer reset
[    3.337065] mdio_bus ocelot-miim1-mii: using device tree for GPIO lookup
[    3.337088] of_get_named_gpiod_flags: can't parse 'reset-gpios' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...dio1[0]'
[    3.337141] of_get_named_gpiod_flags: can't parse 'reset-gpio' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...dio1[0]'
[    3.337190] mdio_bus ocelot-miim1-mii: using lookup tables for GPIO lookup
[    3.337202] mdio_bus ocelot-miim1-mii: No GPIO consumer reset found
[    3.337215] libphy: mscc_miim: probed
[    3.343764] mdio_bus ocelot-miim1-mii:04: GPIO lookup for consumer reset
[    3.343788] mdio_bus ocelot-miim1-mii:04: using device tree for GPIO lookup
[    3.343809] of_get_named_gpiod_flags: can't parse 'reset-gpios' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...dio1/ethernet-phy@4[0]'
[    3.343873] of_get_named_gpiod_flags: can't parse 'reset-gpio' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...dio1/ethernet-phy@4[0]'
[    3.343928] mdio_bus ocelot-miim1-mii:04: using lookup tables for GPIO lookup
[    3.343939] mdio_bus ocelot-miim1-mii:04: No GPIO consumer reset found
# Repeated for 5, 6 and 7
[    3.355921] ocelot-ext-switch ocelot-ext-switch: DMA mask not set
[    3.864119] mdio_bus ocelot-ext-switch-mii: GPIO lookup for consumer reset
[    3.864151] mdio_bus ocelot-ext-switch-mii: using device tree for GPIO lookup
[    3.864176] of_get_named_gpiod_flags: can't parse 'reset-gpios' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...thernet-switch@...dio[0]'
[    3.864236] of_get_named_gpiod_flags: can't parse 'reset-gpio' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...thernet-switch@...dio[0]'
[    3.864291] mdio_bus ocelot-ext-switch-mii: using lookup tables for GPIO lookup
[    3.864303] mdio_bus ocelot-ext-switch-mii: No GPIO consumer reset found
[    4.363826] libphy: ocelot_ext MDIO bus: probed
[    4.371316] mdio_bus ocelot-ext-switch-mii:00: GPIO lookup for consumer reset
[    4.371340] mdio_bus ocelot-ext-switch-mii:00: using device tree for GPIO lookup
[    4.371360] of_get_named_gpiod_flags: can't parse 'reset-gpios' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...thernet-switch@...dio/ethernet-phy@0[0]'
[    4.371433] of_get_named_gpiod_flags: can't parse 'reset-gpio' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...thernet-switch@...dio/ethernet-phy@0[0]'
[    4.371495] mdio_bus ocelot-ext-switch-mii:00: using lookup tables for GPIO lookup
[    4.371507] mdio_bus ocelot-ext-switch-mii:00: No GPIO consumer reset found
[    4.374476] mdio_bus ocelot-ext-switch-mii:01: GPIO lookup for consumer reset
[    4.374504] mdio_bus ocelot-ext-switch-mii:01: using device tree for GPIO lookup
[    4.374524] of_get_named_gpiod_flags: can't parse 'reset-gpios' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...thernet-switch@...dio/ethernet-phy@1[0]'
[    4.374597] of_get_named_gpiod_flags: can't parse 'reset-gpio' property of node '/ocp/interconnect@...00000/segment@...arget-module@...00/spi@...celot-chip@...thernet-switch@...dio/ethernet-phy@1[0]'
[    4.374657] mdio_bus ocelot-ext-switch-mii:01: using lookup tables for GPIO lookup
[    4.374669] mdio_bus ocelot-ext-switch-mii:01: No GPIO consumer reset found
# Repeated for 2 and 3
[    8.105647] ocelot-ext-switch ocelot-ext-switch: PHY [ocelot-ext-switch-mii:00] driver [Generic PHY] (irq=POLL)
[    8.119027] ocelot-ext-switch ocelot-ext-switch: configuring for phy/internal link mode
[    8.145065] ocelot-ext-switch ocelot-ext-switch swp1 (uninitialized): PHY [ocelot-ext-switch-mii:01] driver [Generic PHY] (irq=POLL)
[    8.163599] ocelot-ext-switch ocelot-ext-switch swp2 (uninitialized): PHY [ocelot-ext-switch-mii:02] driver [Generic PHY] (irq=POLL)
[    8.182016] ocelot-ext-switch ocelot-ext-switch swp3 (uninitialized): PHY [ocelot-ext-switch-mii:03] driver [Generic PHY] (irq=POLL)
[    8.200313] ocelot-ext-switch ocelot-ext-switch swp4 (uninitialized): PHY [ocelot-miim1-mii:04] driver [Generic PHY] (irq=POLL)
[    8.218238] ocelot-ext-switch ocelot-ext-switch swp5 (uninitialized): PHY [ocelot-miim1-mii:05] driver [Generic PHY] (irq=POLL)
[    8.236204] ocelot-ext-switch ocelot-ext-switch swp6 (uninitialized): PHY [ocelot-miim1-mii:06] driver [Generic PHY] (irq=POLL)
[    8.254153] ocelot-ext-switch ocelot-ext-switch swp7 (uninitialized): PHY [ocelot-miim1-mii:07] driver [Generic PHY] (irq=POLL)
[    8.277362] device eth0 entered promiscuous mode
[    8.282119] DSA: tree 0 setup
[    8.285250] ocelot_mfd_spi spi0.0: ocelot mfd core setup complete
[    8.297532] ocelot_mfd_spi spi0.0: ocelot spi mfd probed
[   10.259154] ocelot-ext-switch ocelot-ext-switch: Link is Up - 100Mbps/Full - flow control off

Then I enable ports 1-3 on a bridge with STP with an intentional loop of
port 2 plugged directly into port 3:

[   21.040578] cpsw-switch 4a100000.switch: starting ndev. mode: dual_mac
[   21.133226] SMSC LAN8710/LAN8720 4a101000.mdio:00: attached PHY driver (mii_bus:phy_addr=4a101000.mdio:00, irq=POLL)
[   21.150341] 8021q: adding VLAN 0 to HW filter on device eth0
[   21.175435] ocelot-ext-switch ocelot-ext-switch swp1: configuring for phy/internal link mode
[   21.210804] ocelot-ext-switch ocelot-ext-switch swp2: configuring for phy/internal link mode
[   21.245110] ocelot-ext-switch ocelot-ext-switch swp3: configuring for phy/internal link mode
[   21.310462] br0: port 1(swp1) entered blocking state
[   21.315670] br0: port 1(swp1) entered disabled state
[   21.334172] device swp1 entered promiscuous mode
[   21.365554] br0: port 2(swp2) entered blocking state
[   21.370594] br0: port 2(swp2) entered disabled state
[   21.388041] device swp2 entered promiscuous mode
[   21.410549] br0: port 3(swp3) entered blocking state
[   21.415726] br0: port 3(swp3) entered disabled state
[   21.432923] device swp3 entered promiscuous mode
[   21.713724] ocelot-ext-switch ocelot-ext-switch: Link is Down
[   22.741120] ocelot-ext-switch ocelot-ext-switch: Link is Up - 100Mbps/Full - flow control off
[   23.382081] cpsw-switch 4a100000.switch eth0: Link is Up - 100Mbps/Full - flow control off
[   23.392704] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   24.339517] ocelot-ext-switch ocelot-ext-switch swp2: Link is Up - 1Gbps/Full - flow control rx/tx
[   24.348688] IPv6: ADDRCONF(NETDEV_CHANGE): swp2: link becomes ready
[   24.355215] br0: port 2(swp2) entered blocking state
[   24.360220] br0: port 2(swp2) entered listening state
[   24.427317] ocelot-ext-switch ocelot-ext-switch swp3: Link is Up - 1Gbps/Full - flow control rx/tx
[   24.436649] IPv6: ADDRCONF(NETDEV_CHANGE): swp3: link becomes ready
[   24.443458] br0: port 3(swp3) entered blocking state
[   24.448507] br0: port 3(swp3) entered listening state
[   25.463130] ocelot-ext-switch ocelot-ext-switch swp1: Link is Up - 1Gbps/Full - flow control rx/tx
[   25.472385] IPv6: ADDRCONF(NETDEV_CHANGE): swp1: link becomes ready
[   25.479062] br0: port 1(swp1) entered blocking state
[   25.484241] br0: port 1(swp1) entered listening state
[   26.091585] br0: port 3(swp3) entered blocking state
[   39.531066] br0: port 2(swp2) entered learning state
[   40.811057] br0: port 1(swp1) entered learning state
[   54.891054] br0: port 2(swp2) entered forwarding state
[   54.896328] br0: topology change detected, propagating
[   54.906787] IPv6: ADDRCONF(NETDEV_CHANGE): br0: link becomes ready
[   55.531415] br0: received packet on swp2 with own address as source address (addr:*, vlan:0)
[   56.171057] br0: port 1(swp1) entered forwarding state
[   56.176312] br0: topology change detected, propagating
[   90.091617] br0: received packet on swp2 with own address as source address (addr:*, vlan:0)

(I'm curious about those swp2 packets that trickle through...)

In order to make this work, I have modified the cpsw driver, and now the
cpsw_new driver, to allow for frames over 1500 bytes. Otherwise the
tagging protocol will not work between the beaglebone and the VSC7512. I
plan to eventually try to get those changes in mainline, but I don't
want to get distracted from my initial goal. I also had to change
bonecommon.dtsi to avoid using VLAN 0.


Lastly, this patch set relies on changes that have been merged in from
linux-pinctrl/next. kernel-test-robot will complain that the last two
patches won't compile and might not even apply. The path forward might
be to get the MFD / pinctrl into linux-pinctrl before the next merge
window. I doubt the ocelot-ext will be fully functional by then, though
it does feel close!


RFC history:
v1 (accidentally named vN)
	* Initial architecture. Not functional
	* General concepts laid out

v2
	* Near functional. No CPU port communication, but control over all
	external ports
	* Cleaned up regmap implementation from v1

v3
	* Functional
	* Shared MDIO transactions routed through mdio-mscc-miim
	* CPU / NPI port enabled by way of vsc7512_enable_npi_port /
	felix->info->enable_npi_port
	* NPI port tagging functional - Requires a CPU port driver that supports
	frames of 1520 bytes. Verified with a patch to the cpsw driver

v4
    * Functional
    * Device tree fixes
    * Add hooks for pinctrl-ocelot - some functionality by way of sysfs
    * Add hooks for pinctrl-microsemi-sgpio - not yet fully functional
    * Remove lynx_pcs interface for a generic phylink_pcs. The goal here
    is to have an ocelot_pcs that will work for each configuration of
    every port. 

v5
    * Restructured to MFD
    * Several commits were split out, submitted, and accepted
    * pinctrl-ocelot believed to be fully functional (requires commits
    from the linux-pinctrl tree)
    * External MDIO bus believed to be fully functional


Colin Foster (13):
  mfd: ocelot: add support for external mfd control over SPI for the
    VSC7512
  mfd: ocelot: offer an interface for MFD children to get regmaps
  net: mscc: ocelot: expose ocelot wm functions
  net: dsa: felix: add configurable device quirks
  net: mdio: mscc-miim: add ability to externally register phy reset
    control
  net: dsa: ocelot: add external ocelot switch control
  mfd: ocelot: enable the external switch interface
  mfd: add interface to check whether a device is mfd
  net: mdio: mscc-miim: add local dev variable to cleanup probe function
  net: mdio: mscc-miim: add MFD functionality through ocelot-core
  mfd: ocelot-core: add control for the external mdio interface
  pinctrl: ocelot: add MFD functionality through ocelot-core
  mfd: ocelot: add ocelot-pinctrl as a supported child interface

 drivers/mfd/Kconfig                        |  15 +
 drivers/mfd/Makefile                       |   3 +
 drivers/mfd/mfd-core.c                     |   5 +
 drivers/mfd/ocelot-core.c                  | 203 +++++++
 drivers/mfd/ocelot-mfd.h                   |  19 +
 drivers/mfd/ocelot-spi.c                   | 374 ++++++++++++
 drivers/net/dsa/ocelot/Kconfig             |  15 +
 drivers/net/dsa/ocelot/Makefile            |   5 +
 drivers/net/dsa/ocelot/felix.c             |   7 +-
 drivers/net/dsa/ocelot/felix.h             |   1 +
 drivers/net/dsa/ocelot/felix_vsc9959.c     |   1 +
 drivers/net/dsa/ocelot/ocelot_ext.c        | 644 +++++++++++++++++++++
 drivers/net/dsa/ocelot/seville_vsc9953.c   |   4 +-
 drivers/net/ethernet/mscc/ocelot_devlink.c |  31 +
 drivers/net/ethernet/mscc/ocelot_vsc7514.c |  28 -
 drivers/net/mdio/mdio-mscc-miim.c          |  50 +-
 drivers/pinctrl/pinctrl-ocelot.c           |  30 +-
 include/linux/mdio/mdio-mscc-miim.h        |   3 +-
 include/linux/mfd/core.h                   |  10 +
 include/soc/mscc/ocelot.h                  |  19 +
 20 files changed, 1410 insertions(+), 57 deletions(-)
 create mode 100644 drivers/mfd/ocelot-core.c
 create mode 100644 drivers/mfd/ocelot-mfd.h
 create mode 100644 drivers/mfd/ocelot-spi.c
 create mode 100644 drivers/net/dsa/ocelot/ocelot_ext.c

-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ