From: David Yang <mmyangfl@gmail.com>
To: netdev@vger.kernel.org
Cc: David Yang <mmyangfl@gmail.com>, Andrew Lunn <andrew@lunn.ch>,
Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-kernel@vger.kernel.org
Subject: [RFC net-next 3/4] net: dsa: motorcomm: Dynamically allocate port structures
Date: Fri, 19 Jun 2026 04:26:31 +0800 [thread overview]
Message-ID: <20260618202716.2166450-4-mmyangfl@gmail.com> (raw)
In-Reply-To: <20260618202716.2166450-1-mmyangfl@gmail.com>
With support for LED introduced later, struct yt921x_priv will be 17k
which is not very good for a single kmalloc(). Convert the ports array
to a array of pointers to stop bloating the priv struct.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/dsa/motorcomm/chip.c | 95 ++++++++++++++++++++++++--------
drivers/net/dsa/motorcomm/chip.h | 3 +-
2 files changed, 75 insertions(+), 23 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/chip.c
index 6dee25b6754a..d44f7749de02 100644
--- a/drivers/net/dsa/motorcomm/chip.c
+++ b/drivers/net/dsa/motorcomm/chip.c
@@ -548,11 +548,14 @@ yt921x_mbus_ext_init(struct yt921x_priv *priv, struct device_node *mnp)
/* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */
static int yt921x_read_mib(struct yt921x_priv *priv, int port)
{
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct device *dev = to_device(priv);
struct yt921x_mib *mib = &pp->mib;
int res = 0;
+ if (!pp)
+ return -ENODEV;
+
/* Reading of yt921x_port::mib is not protected by a lock and it's vain
* to keep its consistency, since we have to read registers one by one
* and there is no way to make a snapshot of MIB stats.
@@ -609,9 +612,8 @@ static void yt921x_poll_mib(struct work_struct *work)
{
struct yt921x_port *pp = container_of_const(work, struct yt921x_port,
mib_read.work);
- struct yt921x_priv *priv = (void *)(pp - pp->index) -
- offsetof(struct yt921x_priv, ports);
unsigned long delay = YT921X_STATS_INTERVAL_JIFFIES;
+ struct yt921x_priv *priv = pp->priv;
int port = pp->index;
int res;
@@ -643,10 +645,13 @@ static void
yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
size_t j;
+ if (!pp)
+ return;
+
mutex_lock(&priv->reg_lock);
yt921x_read_mib(priv, port);
mutex_unlock(&priv->reg_lock);
@@ -685,9 +690,12 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_mac_stats *mac_stats)
{
struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
+ if (!pp)
+ return;
+
mutex_lock(&priv->reg_lock);
yt921x_read_mib(priv, port);
mutex_unlock(&priv->reg_lock);
@@ -721,9 +729,12 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats)
{
struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
+ if (!pp)
+ return;
+
mutex_lock(&priv->reg_lock);
yt921x_read_mib(priv, port);
mutex_unlock(&priv->reg_lock);
@@ -750,9 +761,12 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
const struct ethtool_rmon_hist_range **ranges)
{
struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
+ if (!pp)
+ return;
+
mutex_lock(&priv->reg_lock);
yt921x_read_mib(priv, port);
mutex_unlock(&priv->reg_lock);
@@ -786,9 +800,12 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *stats)
{
struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
+ if (!pp)
+ return;
+
stats->rx_length_errors = mib->rx_undersize_errors +
mib->rx_fragment_errors;
stats->rx_over_errors = mib->rx_oversize_errors;
@@ -822,9 +839,12 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats)
{
struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
+ if (!pp)
+ return;
+
mutex_lock(&priv->reg_lock);
yt921x_read_mib(priv, port);
mutex_unlock(&priv->reg_lock);
@@ -3332,15 +3352,20 @@ static int yt921x_bridge(struct yt921x_priv *priv, u16 ports_mask)
isolated_mask = 0;
for_each_set_bit(port, &targets_mask, YT921X_PORT_NUM) {
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
+ if (!pp)
+ continue;
if (pp->isolated)
isolated_mask |= BIT(port);
}
/* Block from non-cpu bridge ports ... */
for_each_set_bit(port, &targets_mask, YT921X_PORT_NUM) {
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
+
+ if (!pp)
+ continue;
/* to non-bridge ports */
ctrl = ~ports_mask;
@@ -3397,11 +3422,14 @@ static int
yt921x_bridge_flags(struct yt921x_priv *priv, int port,
struct switchdev_brport_flags flags)
{
- struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_port *pp = priv->ports[port];
bool do_flush;
u32 mask;
int res;
+ if (!pp)
+ return -ENODEV;
+
if (flags.mask & BR_LEARNING) {
bool learning = flags.val & BR_LEARNING;
@@ -3954,11 +3982,16 @@ yt921x_phylink_mac_link_down(struct phylink_config *config, unsigned int mode,
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct yt921x_priv *priv = to_yt921x_priv(dp->ds);
+ struct yt921x_port *pp;
int port = dp->index;
int res;
+ pp = priv->ports[port];
+ if (!pp)
+ return;
+
/* No need to sync; port control block is hold until device remove */
- cancel_delayed_work(&priv->ports[port].mib_read);
+ cancel_delayed_work(&pp->mib_read);
mutex_lock(&priv->reg_lock);
res = yt921x_port_down(priv, port);
@@ -3977,9 +4010,14 @@ yt921x_phylink_mac_link_up(struct phylink_config *config,
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct yt921x_priv *priv = to_yt921x_priv(dp->ds);
+ struct yt921x_port *pp;
int port = dp->index;
int res;
+ pp = priv->ports[port];
+ if (!pp)
+ return;
+
mutex_lock(&priv->reg_lock);
res = yt921x_port_up(priv, port, mode, interface, speed, duplex,
tx_pause, rx_pause);
@@ -3989,7 +4027,7 @@ yt921x_phylink_mac_link_up(struct phylink_config *config,
dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring up",
port, res);
- schedule_delayed_work(&priv->ports[port].mib_read, 0);
+ schedule_delayed_work(&pp->mib_read, 0);
}
static void
@@ -4574,6 +4612,23 @@ static int yt921x_dsa_setup(struct dsa_switch *ds)
return -ENODEV;
}
+ for (int port = 0; port < YT921X_PORT_NUM; port++) {
+ struct yt921x_port *pp;
+
+ if (!(BIT(port) & (priv->info->internal_mask |
+ priv->info->external_mask)))
+ continue;
+
+ pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return -ENOMEM;
+ priv->ports[port] = pp;
+
+ pp->priv = priv;
+ pp->index = port;
+ INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib);
+ }
+
mutex_lock(&priv->reg_lock);
res = yt921x_chip_setup(priv);
mutex_unlock(&priv->reg_lock);
@@ -4682,7 +4737,10 @@ static void yt921x_mdio_remove(struct mdio_device *mdiodev)
return;
for (size_t i = ARRAY_SIZE(priv->ports); i-- > 0; ) {
- struct yt921x_port *pp = &priv->ports[i];
+ struct yt921x_port *pp = priv->ports[i];
+
+ if (!pp)
+ continue;
disable_delayed_work_sync(&pp->mib_read);
}
@@ -4730,13 +4788,6 @@ static int yt921x_mdio_probe(struct mdio_device *mdiodev)
priv->reg_ops = &yt921x_reg_ops_mdio;
priv->reg_ctx = mdio;
- for (size_t i = 0; i < ARRAY_SIZE(priv->ports); i++) {
- struct yt921x_port *pp = &priv->ports[i];
-
- pp->index = i;
- INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib);
- }
-
ds = &priv->ds;
ds->dev = dev;
ds->assisted_learning_on_cpu_port = true;
diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index 555046526669..950a5799f8b6 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -929,6 +929,7 @@ struct yt921x_acl_blk {
};
struct yt921x_port {
+ struct yt921x_priv *priv;
unsigned char index;
bool hairpin;
@@ -964,7 +965,7 @@ struct yt921x_priv {
struct mii_bus *mbus_int;
struct mii_bus *mbus_ext;
- struct yt921x_port ports[YT921X_PORT_NUM];
+ struct yt921x_port *ports[YT921X_PORT_NUM];
u16 eee_ports_mask;
--
2.53.0
next prev parent reply other threads:[~2026-06-18 20:27 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 20:26 [RFC net-next 0/4] net: dsa: motorcomm: Add LED support David Yang
2026-06-18 20:26 ` [RFC net-next 1/4] net: dsa: motorcomm: Move to subdirectory David Yang
2026-06-18 20:26 ` [RFC net-next 2/4] net: dsa: motorcomm: Split SMI module David Yang
2026-06-18 20:26 ` David Yang [this message]
2026-06-18 20:26 ` [RFC net-next 4/4] net: dsa: motorcomm: Add LED support David Yang
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=20260618202716.2166450-4-mmyangfl@gmail.com \
--to=mmyangfl@gmail.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
/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