From: Stefan Wahren <wahrenst@gmx.net>
To: Lukasz Majewski <lukma@denx.de>
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 15:29:08 +0200 [thread overview]
Message-ID: <90c19e6e-235e-465d-9e1e-1ebef49156a0@gmx.net> (raw)
In-Reply-To: <20250410153744.17e6ee5b@wsk>
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.
>>> +
>>> +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.
>>> +
>>> +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.
> +
> +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
> 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).
Are you sure about the randomize fallback behavior of of_get_mac_address() ?
I tought you still need to call eth_random_addr().
>>> +
>>> +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.
next prev parent reply other threads:[~2025-04-11 13:29 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 [this message]
2025-04-11 16:23 ` Lukasz Majewski
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=90c19e6e-235e-465d-9e1e-1ebef49156a0@gmx.net \
--to=wahrenst@gmx.net \
--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=lukma@denx.de \
--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 \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).