From: Lukasz Majewski <lukma@denx.de>
To: Stefan Wahren <wahrenst@gmx.net>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>,
davem@davemloft.net, Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Shawn Guo <shawnguo@kernel.org>,
Sascha Hauer <s.hauer@pengutronix.de>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Fabio Estevam <festevam@gmail.com>,
Richard Cochran <richardcochran@gmail.com>,
netdev@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org
Subject: Re: [net-next v4 4/5] net: mtip: The L2 switch driver for imx287
Date: Fri, 11 Apr 2025 18:23:15 +0200 [thread overview]
Message-ID: <20250411182315.17b18a7f@wsk> (raw)
In-Reply-To: <90c19e6e-235e-465d-9e1e-1ebef49156a0@gmx.net>
[-- Attachment #1: Type: text/plain, Size: 16488 bytes --]
Hi Stefan,
> Am 10.04.25 um 15:37 schrieb Lukasz Majewski:
> > Hi Stefan,
> >
> >> Hi Lukasz,
> >>
> >> thanks for sending this to linux-arm-kernel
> >>
> >> Am 07.04.25 um 16:51 schrieb Lukasz Majewski:
> >>> This patch series provides support for More Than IP L2 switch
> >>> embedded in the imx287 SoC.
> >>>
> >>> This is a two port switch (placed between uDMA[01] and
> >>> MAC-NET[01]), which can be used for offloading the network
> >>> traffic.
> >>>
> >>> It can be used interchangeably with current FEC driver - to be
> >>> more specific: one can use either of it, depending on the
> >>> requirements.
> >>>
> >>> The biggest difference is the usage of DMA - when FEC is used,
> >>> separate DMAs are available for each ENET-MAC block.
> >>> However, with switch enabled - only the DMA0 is used to
> >>> send/receive data to/form switch (and then switch sends them to
> >>> respecitive ports).
> >>>
> >>> Signed-off-by: Lukasz Majewski<lukma@denx.de>
> >>> ---
> >>> Changes for v2:
> >>>
> >>> - Remove not needed comments
> >>> - Restore udelay(10) for switch reset (such delay is explicitly
> >>> specifed in the documentation
> >>> - Add COMPILE_TEST
> >>> - replace pr_* with dev_*
> >>> - Use for_each_available_child_of_node_scoped()
> >>> - Use devm_* function for memory allocation
> >>> - Remove printing information about the HW and SW revision of the
> >>> driver
> >>> - Use devm_regulator_get_optional()
> >>> - Change compatible prefix from 'fsl' to more up to date 'nxp'
> >>> - Remove .owner = THIS_MODULE
> >>> - Use devm_platform_ioremap_resource(pdev, 0);
> >>> - Use devm_request_irq()
> >>> - Use devm_regulator_get_enable_optional()
> >>> - Replace clk_prepare_enable() and devm_clk_get() with single
> >>> call to devm_clk_get_optional_enabled()
> >>> - Cleanup error patch when function calls in probe fail
> >>> - Refactor the mtip_reset_phy() to serve as mdio bus reset
> >>> callback
> >>> - Add myself as the MTIP L2 switch maintainer (squashed the
> >>> separated commit)
> >>> - More descriptive help paragraphs (> 4 lines)
> >>>
> >>> Changes for v3:
> >>> - Remove 'bridge_offloading' module parameter (to bridge ports
> >>> just after probe)
> >>> - Remove forward references
> >>> - Fix reverse christmas tree formatting in functions
> >>> - Convert eligible comments to kernel doc format
> >>> - Remove extra MAC address validation check at
> >>> esw_mac_addr_static()
> >>> - Remove mtip_print_link_status() and replace it with
> >>> phy_print_status()
> >>> - Avoid changing phy device state in the driver (instead use
> >>> functions exported by the phy API)
> >>> - Do not print extra information regarding PHY (which is printed
> >>> by phylib) - e.g. net lan0: lan0: MTIP eth L2 switch
> >>> 1e:ce:a5:0b:4c:12
> >>> - Remove VERSION from the driver - now we rely on the SHA1 in
> >>> Linux mainline tree
> >>> - Remove zeroing of the net device private area (shall be already
> >>> done during allocation)
> >>> - Refactor the code to remove mtip_ndev_setup()
> >>> - Use -ENOMEM instead of -1 return code when allocation fails
> >>> - Replace dev_info() with dev_dbg() to reduce number of
> >>> information print on normal operation
> >>> - Return ret instead of 0 from mtip_ndev_init()
> >>> - Remove fep->mii_timeout flag from the driver
> >>> - Remove not used stop_gpr_* fields in mtip_devinfo struct
> >>> - Remove platform_device_id description for mtipl2sw driver
> >>> - Add MODULE_DEVICE_TABLE() for mtip_of_match
> >>> - Remove MODULE_ALIAS()
> >>>
> >>> Changes for v4:
> >>> - Rename imx287 with imx28 (as the former is not used in kernel
> >>> anymore)
> >>> - Reorder the place where ENET interface is initialized - without
> >>> this change the enet_out clock has default (25 MHz) value, which
> >>> causes issues during reset (RMII's 50 MHz is required for proper
> >>> PHY reset).
> >>> - Use PAUR instead of PAUR register to program MAC address
> >>> - Replace eth_mac_addr() with eth_hw_addr_set()
> >>> - Write to HW the randomly generated MAC address (if required)
> >>> - Adjust the reset code
> >>> - s/read_atable/mtip_read_atable/g and
> >>> s/write_atable/mtip_write_atable/g
> >>> - Add clk_disable() and netif_napi_del() when errors occur during
> >>> mtip_open() - refactor the error handling path.
> >>> - Refactor the mtip_set_multicast_list() to write (now) correct
> >>> values to ENET-FEC registers.
> >>> - Replace dev_warn() with dev_err()
> >>> - Use GPIO_ACTIVE_LOW to indicate polarity in DTS
> >>> - Refactor code to check if network device is the switch device
> >>> - Remove mtip_port_dev_check()
> >>> - Refactor mtip_ndev_port_link() avoid starting HW offloading for
> >>> bridge when MTIP ports are parts of two distinct bridges
> >>> - Replace del_timer() with timer_delete_sync()
> >>> ---
> >>> MAINTAINERS | 7 +
> >>> drivers/net/ethernet/freescale/Kconfig | 1 +
> >>> drivers/net/ethernet/freescale/Makefile | 1 +
> >>> drivers/net/ethernet/freescale/mtipsw/Kconfig | 13 +
> >>> .../net/ethernet/freescale/mtipsw/Makefile | 3 +
> >>> .../net/ethernet/freescale/mtipsw/mtipl2sw.c | 1970
> >>> +++++++++++++++++ .../net/ethernet/freescale/mtipsw/mtipl2sw.h |
> >>> 782 +++++++ .../ethernet/freescale/mtipsw/mtipl2sw_br.c | 122 +
> >>> .../ethernet/freescale/mtipsw/mtipl2sw_mgnt.c | 449 ++++
> >>> 9 files changed, 3348 insertions(+)
> >>> create mode 100644
> >>> drivers/net/ethernet/freescale/mtipsw/Kconfig create mode 100644
> >>> drivers/net/ethernet/freescale/mtipsw/Makefile create mode 100644
> >>> drivers/net/ethernet/freescale/mtipsw/mtipl2sw.c create mode
> >>> 100644 drivers/net/ethernet/freescale/mtipsw/mtipl2sw.h create
> >>> mode 100644 drivers/net/ethernet/freescale/mtipsw/mtipl2sw_br.c
> >>> create mode 100644
> >>> drivers/net/ethernet/freescale/mtipsw/mtipl2sw_mgnt.c
> >>>
> >>> diff --git a/MAINTAINERS b/MAINTAINERS
> >>> index 4c5c2e2c1278..9c5626c2b3b7 100644
> >>> --- a/MAINTAINERS
> >>> +++ b/MAINTAINERS
> >>> @@ -9455,6 +9455,13 @@ S: Maintained
> >>> F: Documentation/devicetree/bindings/i2c/i2c-mpc.yaml
> >>> F: drivers/i2c/busses/i2c-mpc.c
> >>>
> >>> +FREESCALE MTIP ETHERNET SWITCH DRIVER
> >>> +M: Lukasz Majewski<lukma@denx.de>
> >>> +L: netdev@vger.kernel.org
> >>> +S: Maintained
> >>> +F:
> >>> Documentation/devicetree/bindings/net/nxp,imx28-mtip-switch.yaml
> >>> +F: drivers/net/ethernet/freescale/mtipsw/* +
> >>> FREESCALE QORIQ DPAA ETHERNET DRIVER
> >>> M: Madalin Bucur<madalin.bucur@nxp.com>
> >>> L: netdev@vger.kernel.org
> >>> diff --git a/drivers/net/ethernet/freescale/Kconfig
> >>> b/drivers/net/ethernet/freescale/Kconfig index
> >>> a2d7300925a8..056a11c3a74e 100644 ---
> >>> a/drivers/net/ethernet/freescale/Kconfig +++
> >>> b/drivers/net/ethernet/freescale/Kconfig @@ -60,6 +60,7 @@ config
> >>> FEC_MPC52xx_MDIO
> >>>
> >>> source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
> >>> source "drivers/net/ethernet/freescale/fman/Kconfig"
> >>> +source "drivers/net/ethernet/freescale/mtipsw/Kconfig"
> >>>
> >>> config FSL_PQ_MDIO
> >>> tristate "Freescale PQ MDIO" diff --git
> >>> a/drivers/net/ethernet/freescale/Makefile
> >>> b/drivers/net/ethernet/freescale/Makefile index
> >>> de7b31842233..0e6cacb0948a 100644 ---
> >>> a/drivers/net/ethernet/freescale/Makefile +++
> >>> b/drivers/net/ethernet/freescale/Makefile @@ -25,3 +25,4 @@
> >>> obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/ obj-$(CONFIG_FSL_DPAA2_ETH) +=
> >>> dpaa2/ obj-y += enetc/ +obj-y += mtipsw/ diff --git
> >>> a/drivers/net/ethernet/freescale/mtipsw/Kconfig
> >>> b/drivers/net/ethernet/freescale/mtipsw/Kconfig new file mode
> >>> 100644 index 000000000000..450ff734a321 --- /dev/null +++
> >>> b/drivers/net/ethernet/freescale/mtipsw/Kconfig @@ -0,0 +1,13 @@
> >>> +# SPDX-License-Identifier: GPL-2.0-only +config FEC_MTIP_L2SW +
> >>> tristate "MoreThanIP L2 switch support to FEC driver"
> >>> + depends on OF
> >>> + depends on NET_SWITCHDEV
> >>> + depends on BRIDGE
> >>> + depends on ARCH_MXS || ARCH_MXC || COMPILE_TEST
> >>> + help
> >>> + This enables support for the MoreThan IP L2 switch on
> >>> i.MX
> >>> + SoCs (e.g. iMX28, vf610). It offloads bridging to this
> >>> IP block's
> >> This is confusing. The Kconfig and most of the code looks prepared
> >> for other platforms than i.MX28, but there is only a i.MX28 OF
> >> compatible.
> > I've took the approach to upstream the driver in several steps.
> > The first step is this patch set - add the code for a single
> > platform (imx28).
> >
> > And Yes, I also have on my desk another board with soc having this
> > IP block (vf610).
> >
> > However, I will not start any other upstream work until patches from
> > this "step" are not pulled.
> >
> > (To follow "one things at a time" principle)
> >
> >> I don't like that Kconfig pretent something, which is not
> >> true.
> > If you prefer I can remove 'depends on ARCH_MXC' and the vf610
> > SoC... (only to add it afterwards).
> In case you want to do "one thing at a time", please remove this.
+1
> >>> +
> >>> +static void mtip_config_switch(struct switch_enet_private *fep)
> >>> +{
> >>> + struct switch_t *fecp = fep->hwp;
> >>> +
> >>> + esw_mac_addr_static(fep);
> >>> +
> >>> + writel(0, &fecp->ESW_BKLR);
> >>> +
> >>> + /* Do NOT disable learning */
> >>> + mtip_port_learning_config(fep, 0, 0, 0);
> >>> + mtip_port_learning_config(fep, 1, 0, 0);
> >>> + mtip_port_learning_config(fep, 2, 0, 0);
> >> Looks like the last 2 parameter are always 0?
> > Those functions are defined in mtipl2sw_mgnt.c file.
> >
> > I've followed the way legacy (i.e. vendor) driver has defined them.
> > In this particular case the last '0' is to not enable interrupt for
> > learning.
> This wasn't my concern. The question was "why do we need a parameter
> if it's always the same?". But you answered this further below, so
> i'm fine.
Ok.
> >>> +
> >>> +static irqreturn_t mtip_interrupt(int irq, void *ptr_fep)
> >>> +{
> >>> + struct switch_enet_private *fep = ptr_fep;
> >>> + struct switch_t *fecp = fep->hwp;
> >>> + irqreturn_t ret = IRQ_NONE;
> >>> + u32 int_events, int_imask;
> >>> +
> >>> + /* Get the interrupt events that caused us to be here */
> >>> + do {
> >>> + int_events = readl(&fecp->ESW_ISR);
> >>> + writel(int_events, &fecp->ESW_ISR);
> >>> +
> >>> + if (int_events & (MCF_ESW_ISR_RXF |
> >>> MCF_ESW_ISR_TXF)) {
> >>> + ret = IRQ_HANDLED;
> >>> + /* Disable the RX interrupt */
> >>> + if (napi_schedule_prep(&fep->napi)) {
> >>> + int_imask =
> >>> readl(&fecp->ESW_IMR);
> >>> + int_imask &= ~MCF_ESW_IMR_RXF;
> >>> + writel(int_imask,
> >>> &fecp->ESW_IMR);
> >>> + __napi_schedule(&fep->napi);
> >>> + }
> >>> + }
> >>> + } while (int_events);
> >> This looks bad, in case of bad hardware / timing behavior this
> >> interrupt handler will loop forever.
> > The 'writel(int_events, &fecp->ESW_ISR);'
> >
> > clears the interrupts, so after reading them and clearing (by
> > writing the same value), the int_events shall be 0.
> >
> > Also, during probe the IRQ mask for switch IRQ is written, so only
> > expected (and served) interrupts are delivered.
> This was not my point. A possible endless loop especially in a
> interrupt handler should be avoided. The kernel shouldn't trust the
> hardware and the driver should be fair to all the other interrupts
> which might have occurred.
Ok.
> > +
> > +static int mtip_rx_napi(struct napi_struct *napi, int budget)
> > +{
> > + struct mtip_ndev_priv *priv = netdev_priv(napi->dev);
> > + struct switch_enet_private *fep = priv->fep;
> > + struct switch_t *fecp = fep->hwp;
> > + int pkts, port;
> > +
> > + pkts = mtip_switch_rx(napi->dev, budget, &port);
> > + if (!fep->br_offload &&
> > + (port == 1 || port == 2) && fep->ndev[port - 1])
> >> (port > 0) && fep->ndev[port - 1])
> > This needs to be kept as is - only when port is set to 1 or 2 (after
> > reading the switch internal register) this shall be executed.
> Oops, missed that
> > (port also can be 0xFF or 0x3 -> then we shall send frame to both
> > egress ports).
> Maybe we should use defines for such special values
Port = 1 or port = 2 seems to be self explanatory.
Nonetheless, I've added MTIP_PORT_FORWARDING_INIT for 0xFF initial
forwarding value.
> > This code is responsible for port separation when bridge HW
> > offloading is disabled.
> >
> >
> >>> + of_get_mac_address(port, &fep->mac[port_num -
> >>> 1][0]);
> >> This can fail
> > I will add:
> >
> > ret = of_get_mac_address(port, &fep->mac[port_num - 1][0]);
> > if (ret)
> > dev_warn(dev, "of_get_mac_address(%pOF) failed\n", port);
> >
> > as it is also valid to not have the mac address defined in DTS (then
> > some random based value is generated).
> AFAIK this is a little bit more complex. It's possible that the MAC is
> stored within a NVMEM and the driver isn't ready (EPROBE_DEFER).
>
In my use case - always the local mac address is provided during
production (to ethernet-port nodes).
The other possibility is no MAC address provided, that is why there is
dev_warn().
> Are you sure about the randomize fallback behavior of
> of_get_mac_address() ?
>
> I tought you still need to call eth_random_addr().
>
The "random" MAC address is generated in another place - namely
mtip_setup_mac();
>
> >>> +
> >>> +int mtip_set_vlan_verification(struct switch_enet_private *fep,
> >>> int port,
> >>> + int vlan_domain_verify_en,
> >>> + int vlan_discard_unknown_en)
> >>> +{
> >>> + struct switch_t *fecp = fep->hwp;
> >>> +
> >>> + if (port < 0 || port > 2) {
> >>> + dev_err(&fep->pdev->dev, "%s: Port (%d) not
> >>> supported!\n",
> >>> + __func__, port);
> >>> + return -EINVAL;
> >>> + }
> >>> +
> >>> + if (vlan_domain_verify_en == 1) {
> >>> + if (port == 0)
> >>> + writel(readl(&fecp->ESW_VLANV) |
> >>> MCF_ESW_VLANV_VV0,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 1)
> >>> + writel(readl(&fecp->ESW_VLANV) |
> >>> MCF_ESW_VLANV_VV1,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 2)
> >>> + writel(readl(&fecp->ESW_VLANV) |
> >>> MCF_ESW_VLANV_VV2,
> >>> + &fecp->ESW_VLANV);
> >>> + } else if (vlan_domain_verify_en == 0) {
> >>> + if (port == 0)
> >>> + writel(readl(&fecp->ESW_VLANV) &
> >>> ~MCF_ESW_VLANV_VV0,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 1)
> >>> + writel(readl(&fecp->ESW_VLANV) &
> >>> ~MCF_ESW_VLANV_VV1,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 2)
> >>> + writel(readl(&fecp->ESW_VLANV) &
> >>> ~MCF_ESW_VLANV_VV2,
> >>> + &fecp->ESW_VLANV);
> >>> + }
> >>> +
> >>> + if (vlan_discard_unknown_en == 1) {
> >>> + if (port == 0)
> >>> + writel(readl(&fecp->ESW_VLANV) |
> >>> MCF_ESW_VLANV_DU0,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 1)
> >>> + writel(readl(&fecp->ESW_VLANV) |
> >>> MCF_ESW_VLANV_DU1,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 2)
> >>> + writel(readl(&fecp->ESW_VLANV) |
> >>> MCF_ESW_VLANV_DU2,
> >>> + &fecp->ESW_VLANV);
> >>> + } else if (vlan_discard_unknown_en == 0) {
> >>> + if (port == 0)
> >>> + writel(readl(&fecp->ESW_VLANV) &
> >>> ~MCF_ESW_VLANV_DU0,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 1)
> >>> + writel(readl(&fecp->ESW_VLANV) &
> >>> ~MCF_ESW_VLANV_DU1,
> >>> + &fecp->ESW_VLANV);
> >>> + else if (port == 2)
> >>> + writel(readl(&fecp->ESW_VLANV) &
> >>> ~MCF_ESW_VLANV_DU2,
> >>> + &fecp->ESW_VLANV);
> >>> + }
> >> This looks like a lot of copy & paste
> > IMHO, the readability of the code is OK.
> Actually the concern was about maintenance.
IMHO, (for me) the maintenance cost of this code is acceptable.
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next prev parent reply other threads:[~2025-04-11 16:23 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-07 14:51 [net-next v4 0/5] net: mtip: Add support for MTIP imx287 L2 switch driver Lukasz Majewski
2025-04-07 14:51 ` [net-next v4 1/5] dt-bindings: net: Add MTIP L2 switch description Lukasz Majewski
2025-04-10 20:59 ` Rob Herring
2025-04-11 10:36 ` Lukasz Majewski
2025-04-07 14:51 ` [net-next v4 2/5] ARM: dts: nxp: mxs: Adjust the imx28.dtsi " Lukasz Majewski
2025-04-07 14:51 ` [net-next v4 3/5] ARM: dts: nxp: mxs: Adjust XEA board's DTS to support L2 switch Lukasz Majewski
2025-04-09 21:06 ` Andrew Lunn
2025-04-11 13:32 ` Fabio Estevam
2025-04-11 15:45 ` Lukasz Majewski
2025-04-07 14:51 ` [net-next v4 4/5] net: mtip: The L2 switch driver for imx287 Lukasz Majewski
2025-04-08 15:14 ` Simon Horman
2025-04-09 14:28 ` Lukasz Majewski
2025-04-11 12:54 ` Lukasz Majewski
2025-04-09 17:53 ` Stefan Wahren
2025-04-10 13:37 ` Lukasz Majewski
2025-04-11 13:29 ` Stefan Wahren
2025-04-11 16:23 ` Lukasz Majewski [this message]
2025-04-09 21:26 ` Andrew Lunn
2025-04-10 7:35 ` Lukasz Majewski
2025-04-07 14:51 ` [net-next v4 5/5] ARM: mxs_defconfig: Enable CONFIG_FEC_MTIP_L2SW to support MTIP L2 switch Lukasz Majewski
2025-04-09 16:01 ` Stefan Wahren
2025-04-10 7:01 ` Lukasz Majewski
2025-04-10 7:08 ` Krzysztof Kozlowski
2025-04-10 9:23 ` Lukasz Majewski
2025-04-10 7:58 ` Stefan Wahren
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250411182315.17b18a7f@wsk \
--to=lukma@denx.de \
--cc=andrew+netdev@lunn.ch \
--cc=conor+dt@kernel.org \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=edumazet@google.com \
--cc=festevam@gmail.com \
--cc=imx@lists.linux.dev \
--cc=kernel@pengutronix.de \
--cc=krzk+dt@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=richardcochran@gmail.com \
--cc=robh@kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
--cc=wahrenst@gmx.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.