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
| ||
|
Message-Id: <20230216075321.2898003-7-colin.foster@in-advantage.com> Date: Wed, 15 Feb 2023 23:53:20 -0800 From: Colin Foster <colin.foster@...advantage.com> To: linux-phy@...ts.infradead.org, netdev@...r.kernel.org, linux-kernel@...r.kernel.org Cc: Russell King <linux@...linux.org.uk>, Kishon Vijay Abraham I <kishon@...nel.org>, Vinod Koul <vkoul@...nel.org>, Paolo Abeni <pabeni@...hat.com>, Jakub Kicinski <kuba@...nel.org>, Eric Dumazet <edumazet@...gle.com>, "David S. Miller" <davem@...emloft.net>, Florian Fainelli <f.fainelli@...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@...nel.org> Subject: [RFC v1 net-next 6/7] net: dsa: felix: allow external parsing of port nodes When the felix driver parses the device tree, it does so in such a way that every node is parsed in a loop. This is done in the felix_init_structs() function. After this is done, a separate loop will invoke ocelot_init_port() on each port. This causes problems if a user of the felix driver needs to retain some information from the device tree during port initialization. A driver might, for example, need to create call phylink_create() during ocelot_init_port(), which requires a reference to the fwnode_handle. Add a hook from felix into the sub-drivers, where they can optionally grab references to the device_node when needed. Signed-off-by: Colin Foster <colin.foster@...advantage.com> --- drivers/net/dsa/ocelot/felix.c | 54 +++++++++++++++++++++++++--------- drivers/net/dsa/ocelot/felix.h | 5 ++++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 21dcb9cadc12..b6e3a88addb8 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1245,7 +1245,8 @@ static int felix_parse_ports_node(struct felix *felix, struct device_node *ports_node, phy_interface_t *port_phy_modes) { - struct device *dev = felix->ocelot.dev; + struct ocelot *ocelot = &felix->ocelot; + struct device *dev = ocelot->dev; struct device_node *child; for_each_available_child_of_node(ports_node, child) { @@ -1285,6 +1286,19 @@ static int felix_parse_ports_node(struct felix *felix, } port_phy_modes[port] = phy_mode; + + if (dsa_is_cpu_port(felix->ds, port) || + !felix->info->parse_port_node) + continue; + + err = felix->info->parse_port_node(ocelot, child, phy_mode, + port); + if (err < 0) { + dev_err(dev, "Unable to create etherdev for port %d\n", + port); + of_node_put(child); + return err; + } } return 0; @@ -1396,8 +1410,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) err = felix_parse_dt(felix, port_phy_modes); if (err) { - kfree(port_phy_modes); - return err; + goto free_port_modes; } for (i = 0; i < TARGET_MAX; i++) { @@ -1406,8 +1419,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) dev_err(ocelot->dev, "Failed to map device memory space: %pe\n", target); - kfree(port_phy_modes); - return PTR_ERR(target); + err = PTR_ERR(target); + goto free_port_modes; } ocelot->targets[i] = target; @@ -1416,8 +1429,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) err = ocelot_regfields_init(ocelot, felix->info->regfields); if (err) { dev_err(ocelot->dev, "failed to init reg fields map\n"); - kfree(port_phy_modes); - return err; + goto free_port_modes; } for (port = 0; port < num_phys_ports; port++) { @@ -1429,8 +1441,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) if (!ocelot_port) { dev_err(ocelot->dev, "failed to allocate port memory\n"); - kfree(port_phy_modes); - return -ENOMEM; + err = -ENOMEM; + goto free_port_modes; } target = felix_request_port_regmap(felix, port); @@ -1438,8 +1450,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) dev_err(ocelot->dev, "Failed to map memory space for port %d: %pe\n", port, target); - kfree(port_phy_modes); - return PTR_ERR(target); + err = PTR_ERR(target); + goto free_port_modes; } ocelot_port->phy_mode = port_phy_modes[port]; @@ -1449,15 +1461,21 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ocelot->ports[port] = ocelot_port; } - kfree(port_phy_modes); - if (felix->info->mdio_bus_alloc) { err = felix->info->mdio_bus_alloc(ocelot); if (err < 0) - return err; + goto free_port_modes; } + kfree(port_phy_modes); + return 0; + +free_port_modes: + if (felix->info->phylink_of_cleanup) + felix->info->phylink_of_cleanup(ocelot); + kfree(port_phy_modes); + return err; } static void ocelot_port_purge_txtstamp_skb(struct ocelot *ocelot, int port, @@ -1574,12 +1592,18 @@ static int felix_setup(struct dsa_switch *ds) dsa_switch_for_each_available_port(dp, ds) { ocelot_init_port(ocelot, dp->index); + if (felix->info->phylink_create) + felix->info->phylink_create(ocelot, dp->index); + /* Set the default QoS Classification based on PCP and DEI * bits of vlan tag. */ felix_port_qos_map_init(ocelot, dp->index); } + if (felix->info->phylink_of_cleanup) + felix->info->phylink_of_cleanup(ocelot); + err = ocelot_devlink_sb_register(ocelot); if (err) goto out_deinit_ports; @@ -1604,6 +1628,8 @@ static int felix_setup(struct dsa_switch *ds) ocelot_deinit(ocelot); out_mdiobus_free: + if (felix->info->phylink_of_cleanup) + felix->info->phylink_of_cleanup(ocelot); if (felix->info->mdio_bus_free) felix->info->mdio_bus_free(ocelot); diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index d5d0b30c0b75..ffb60bcf1817 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -58,6 +58,11 @@ struct felix_info { void (*tas_guard_bands_update)(struct ocelot *ocelot, int port); void (*port_sched_speed_set)(struct ocelot *ocelot, int port, u32 speed); + int (*parse_port_node)(struct ocelot *ocelot, + struct device_node *ports_node, + phy_interface_t phy_mode, int port); + int (*phylink_create)(struct ocelot *ocelot, int port); + void (*phylink_of_cleanup)(struct ocelot *ocelot); }; /* Methods for initializing the hardware resources specific to a tagging -- 2.25.1
Powered by blists - more mailing lists