From: Krzysztof Kozlowski <krzk@kernel.org>
To: Lukasz Majewski <lukma@denx.de>,
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>
Cc: 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,
Stefan Wahren <wahrenst@gmx.net>, Simon Horman <horms@kernel.org>,
Andrew Lunn <andrew@lunn.ch>
Subject: Re: [net-next v10 4/7] net: mtip: The L2 switch driver for imx287
Date: Fri, 2 May 2025 16:33:50 +0200 [thread overview]
Message-ID: <a01df80b-c1ee-4c36-b400-e3044a0156e2@kernel.org> (raw)
In-Reply-To: <20250502074447.2153837-5-lukma@denx.de>
On 02/05/2025 09:44, Lukasz Majewski wrote:
> +
> +static int mtip_parse_of(struct switch_enet_private *fep,
> + struct device_node *np)
> +{
> + struct device_node *p;
> + unsigned int port_num;
> + int ret = 0;
> +
> + p = of_find_node_by_name(np, "ethernet-ports");
This should be looking for children, not any nodes. Otherwise you will
take the ethernet ports from a next device as well.
> +
> + for_each_available_child_of_node_scoped(p, port) {
> + if (of_property_read_u32(port, "reg", &port_num))
> + continue;
> +
> + if (port_num > SWITCH_EPORT_NUMBER) {
> + dev_err(&fep->pdev->dev,
> + "%s: The switch supports up to %d ports!\n",
> + __func__, SWITCH_EPORT_NUMBER);
> + goto of_get_err;
> + }
> +
> + fep->n_ports = port_num;
> + ret = of_get_mac_address(port, &fep->mac[port_num - 1][0]);
> + if (ret)
> + dev_dbg(&fep->pdev->dev,
> + "of_get_mac_address(%pOF) failed (%d)!\n",
> + port, ret);
> +
> + ret = of_property_read_string(port, "label",
> + &fep->ndev_name[port_num - 1]);
> + if (ret < 0) {
> + dev_err(&fep->pdev->dev,
> + "%s: Cannot get ethernet port name (%d)!\n",
> + __func__, ret);
> + goto of_get_err;
> + }
> +
> + ret = of_get_phy_mode(port, &fep->phy_interface[port_num - 1]);
> + if (ret < 0) {
> + dev_err(&fep->pdev->dev,
> + "%s: Cannot get PHY mode (%d)!\n", __func__,
> + ret);
> + goto of_get_err;
> + }
> +
> + fep->phy_np[port_num - 1] = of_parse_phandle(port,
> + "phy-handle", 0);
> + }
> +
> + of_get_err:
> + of_node_put(p);
> +
> + return ret;
> +}
> +
> +static int mtip_sw_learning(void *arg)
> +{
> + struct switch_enet_private *fep = arg;
> +
> + while (!kthread_should_stop()) {
> + set_current_state(TASK_INTERRUPTIBLE);
> + /* check learning record valid */
> + mtip_atable_dynamicms_learn_migration(fep, fep->curr_time,
> + NULL, NULL);
> + schedule_timeout(HZ / 100);
> + }
> +
> + return 0;
> +}
> +
> +static void mtip_mii_unregister(struct switch_enet_private *fep)
> +{
> + mdiobus_unregister(fep->mii_bus);
> + mdiobus_free(fep->mii_bus);
> +}
> +
> +static const struct mtip_devinfo mtip_imx28_l2switch_info = {
> + .quirks = FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_SINGLE_MDIO |
> + FEC_QUIRK_SWAP_FRAME,
> +};
> +
> +static const struct of_device_id mtipl2_of_match[] = {
> + { .compatible = "nxp,imx28-mtip-switch",
> + .data = &mtip_imx28_l2switch_info},
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, mtipl2_of_match);
> +
> +static int mtip_sw_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + const struct of_device_id *of_id;
> + struct switch_enet_private *fep;
> + struct mtip_devinfo *dev_info;
> + int ret;
> +
> + fep = devm_kzalloc(&pdev->dev, sizeof(*fep), GFP_KERNEL);
> + if (!fep)
> + return -ENOMEM;
> +
> + of_id = of_match_node(mtipl2_of_match, pdev->dev.of_node);
> + if (of_id) {
> + dev_info = (struct mtip_devinfo *)of_id->data;
Do not open-code of_device_get_match_data().
> + if (dev_info)
> + fep->quirks = dev_info->quirks;
> + }
> +
> + fep->pdev = pdev;
> + platform_set_drvdata(pdev, fep);
> +
> + fep->enet_addr = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(fep->enet_addr))
> + return PTR_ERR(fep->enet_addr);
> +
> + fep->irq = platform_get_irq_byname(pdev, "enet_switch");
> + if (fep->irq < 0)
> + return fep->irq;
> +
> + ret = mtip_parse_of(fep, np);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "%s: OF parse error (%d)!\n", __func__,
> + ret);
Syntax is:
return dev_err_probe
just like you have in other places
> + return ret;
> + }
> +
> + /* Create an Ethernet device instance.
> + * The switch lookup address memory starts at 0x800FC000
> + */
> + fep->hwp_enet = fep->enet_addr;
> + fep->hwp = fep->enet_addr + ENET_SWI_PHYS_ADDR_OFFSET;
> + fep->hwentry = (struct mtip_addr_table __iomem *)
> + (fep->hwp + MCF_ESW_LOOKUP_MEM_OFFSET);
> +
> + ret = devm_regulator_get_enable_optional(&pdev->dev, "phy");
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "Unable to get and enable 'phy'\n");
> +
> + fep->clk_ipg = devm_clk_get_enabled(&pdev->dev, "ipg");
> + if (IS_ERR(fep->clk_ipg))
> + return dev_err_probe(&pdev->dev, PTR_ERR(fep->clk_ipg),
> + "Unable to acquire 'ipg' clock\n");
> +
> + fep->clk_ahb = devm_clk_get_enabled(&pdev->dev, "ahb");
> + if (IS_ERR(fep->clk_ahb))
> + return dev_err_probe(&pdev->dev, PTR_ERR(fep->clk_ahb),
> + "Unable to acquire 'ahb' clock\n");
> +
> + fep->clk_enet_out = devm_clk_get_optional_enabled(&pdev->dev,
> + "enet_out");
> + if (IS_ERR(fep->clk_enet_out))
> + return dev_err_probe(&pdev->dev, PTR_ERR(fep->clk_enet_out),
> + "Unable to acquire 'enet_out' clock\n");
> +
> + /* setup MII interface for external switch ports */
> + mtip_enet_init(fep, 1);
> + mtip_enet_init(fep, 2);
> +
> + spin_lock_init(&fep->learn_lock);
> + spin_lock_init(&fep->hw_lock);
> + spin_lock_init(&fep->mii_lock);
> +
> + ret = devm_request_irq(&pdev->dev, fep->irq, mtip_interrupt, 0,
> + dev_name(&pdev->dev), fep);
> + if (ret)
> + return dev_err_probe(&pdev->dev, fep->irq,
> + "Could not alloc IRQ\n");
> +
> + ret = mtip_register_notifiers(fep);
> + if (ret)
> + return ret;
> +
> + ret = mtip_ndev_init(fep, pdev);
> + if (ret) {
> + dev_err(&pdev->dev, "%s: Failed to create virtual ndev (%d)\n",
> + __func__, ret);
> + goto ndev_init_err;
> + }
> +
> + ret = mtip_switch_dma_init(fep);
> + if (ret) {
> + dev_err(&pdev->dev, "%s: ethernet switch init fail (%d)!\n",
> + __func__, ret);
> + goto dma_init_err;
> + }
> +
> + ret = mtip_mii_init(fep, pdev);
> + if (ret) {
> + dev_err(&pdev->dev, "%s: Cannot init phy bus (%d)!\n", __func__,
> + ret);
> + goto mii_init_err;
> + }
> + /* setup timer for learning aging function */
> + timer_setup(&fep->timer_aging, mtip_aging_timer, 0);
> + mod_timer(&fep->timer_aging,
> + jiffies + msecs_to_jiffies(LEARNING_AGING_INTERVAL));
> +
> + fep->task = kthread_run(mtip_sw_learning, fep, "mtip_l2sw_learning");
> + if (IS_ERR(fep->task)) {
> + ret = PTR_ERR(fep->task);
> + dev_err(&pdev->dev, "%s: learning kthread_run error (%d)!\n",
> + __func__, ret);
ret = dev_err_probe
> + goto task_learning_err;
> + }
> +
> + return 0;
> +
> + task_learning_err:
> + timer_delete_sync(&fep->timer_aging);
> + mtip_mii_unregister(fep);
> + mii_init_err:
> + dma_init_err:
> + mtip_ndev_cleanup(fep);
> + ndev_init_err:
> + mtip_unregister_notifiers(fep);
> +
> + return ret;
> +}
> +
> +static void mtip_sw_remove(struct platform_device *pdev)
> +{
> + struct switch_enet_private *fep = platform_get_drvdata(pdev);
> +
> + mtip_unregister_notifiers(fep);
> + mtip_ndev_cleanup(fep);
> +
> + mtip_mii_remove(fep);
> +
> + kthread_stop(fep->task);
> + timer_delete_sync(&fep->timer_aging);
> + platform_set_drvdata(pdev, NULL);
> +
> + kfree(fep);
Jakub already pointed out that tools would find this bug but also
testing. This was not ever tested. If it was, you would see nice clear
double free.
All last three versions had trivial issues which are pointed out by
tooling, compilers, static analyzers. Before you post next version.
please run standard kernel tools for static analysis, like coccinelle,
smatch and sparse, and fix reported warnings. Also please check for
warnings when building with W=1 with clang. Most of these commands
(checks or W=1 build) can build specific targets, like some directory,
to narrow the scope to only your code. The code here looks like it needs
a fix. Feel free to get in touch if the warning is not clear.
You do not nede the the top-level, one of the most busy maintainers to
point out the issues which compilers find as well. Using reviewers
instead of automated tools is the easiest way to get grumpy responses.
Best regards,
Krzysztof
next prev parent reply other threads:[~2025-05-02 14:33 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-02 7:44 [net-next v10 0/7] net: mtip: Add support for MTIP imx287 L2 switch driver Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 1/7] dt-bindings: net: Add MTIP L2 switch description Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 2/7] ARM: dts: nxp: mxs: Adjust the imx28.dtsi " Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 3/7] ARM: dts: nxp: mxs: Adjust XEA board's DTS to support L2 switch Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 4/7] net: mtip: The L2 switch driver for imx287 Lukasz Majewski
2025-05-02 14:13 ` Jakub Kicinski
2025-05-04 6:28 ` Lukasz Majewski
2025-05-05 20:16 ` Jakub Kicinski
2025-05-06 11:30 ` Lukasz Majewski
2025-05-02 14:33 ` Krzysztof Kozlowski [this message]
2025-05-04 10:47 ` Lukasz Majewski
2025-05-02 17:05 ` Simon Horman
2025-05-04 10:48 ` Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 5/7] ARM: mxs_defconfig: Enable CONFIG_NFS_FSCACHE Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 6/7] ARM: mxs_defconfig: Update mxs_defconfig to 6.15-rc1 Lukasz Majewski
2025-05-02 7:44 ` [net-next v10 7/7] ARM: mxs_defconfig: Enable CONFIG_FEC_MTIP_L2SW to support MTIP L2 switch Lukasz Majewski
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=a01df80b-c1ee-4c36-b400-e3044a0156e2@kernel.org \
--to=krzk@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=andrew@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=horms@kernel.org \
--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 \
--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 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).