Commit 7925c2d9 authored by David S. Miller's avatar David S. Miller

Merge branch 'qca8k_preiv-shrink'

Ansuel Smith says:

====================
net: Reduce qca8k_priv space usage

These 6 patch is a first attempt at reducting qca8k_priv space.
The code changed a lot during times and we have many old logic
that can be replaced with new implementation

The first patch drop the tracking of MTU. We mimic what was done
for mtk and we change MTU only when CPU port is changed.

The second patch finally drop a piece of story of this driver.
The ar8xxx_port_status struct was used by the first implementation
of this driver to put all sort of status data for the port...
With the evolution of DSA all that stuff got dropped till only
the enabled state was the only part of the that struct.
Since it's overkill to keep an array of int, we convert the variable
to a simple u8 where we store the status of each port. This is needed
to don't reanable ports on system resume.

The third patch is a preparation for patch 4. As Vladimir explained
in another patch, we waste a tons of space by keeping a duplicate of
the switch dsa ops in qca8k_priv. The only reason for this is to
dynamically set the correct mdiobus configuration (a legacy dsa one,
or a custom dedicated one)
To solve this problem, we just drop the phy_read/phy_write and we
declare a custom mdiobus in any case.
This way we can use a static dsa switch ops struct and we can drop it
from qca8k_priv

Patch 4 drop the duplicated dsa_switch_ops.

Patch 5 is a fixup for mdio read error.

Patch 6 is an effort to standardize how bus name are done.

This series is just a start of more cleanup.

The idea is to move this driver to the qca dir and split common code
from specific code. Also the mgmt eth code still requires some love
and can totally be optimized by recycling the same skb over time.

Also while working on the MTU it was notice some problem with
the stmmac driver and with the reloading phase that cause all
sort of problems with qca8k.

I'm sending this here just to try to keep small series instead of
proposing monster series hard to review.

v2:
- Rework MTU patch
v3:
- Drop unrealated changes from patch 3
- Add fixup patch for mdio read
- Unify bus name for legacy and OF mdio bus
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f9a2fb73 8d1af508
...@@ -1287,87 +1287,71 @@ qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) ...@@ -1287,87 +1287,71 @@ qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum)
if (ret >= 0) if (ret >= 0)
return ret; return ret;
return qca8k_mdio_read(priv, phy, regnum); ret = qca8k_mdio_read(priv, phy, regnum);
if (ret < 0)
return 0xffff;
return ret;
} }
static int static int
qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) qca8k_legacy_mdio_write(struct mii_bus *slave_bus, int port, int regnum, u16 data)
{ {
struct qca8k_priv *priv = ds->priv; port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
int ret;
/* Check if the legacy mapping should be used and the return qca8k_internal_mdio_write(slave_bus, port, regnum, data);
* port is not correctly mapped to the right PHY in the
* devicetree
*/
if (priv->legacy_phy_port_mapping)
port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
/* Use mdio Ethernet when available, fallback to legacy one on error */
ret = qca8k_phy_eth_command(priv, false, port, regnum, 0);
if (!ret)
return ret;
return qca8k_mdio_write(priv, port, regnum, data);
} }
static int static int
qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) qca8k_legacy_mdio_read(struct mii_bus *slave_bus, int port, int regnum)
{ {
struct qca8k_priv *priv = ds->priv; port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
int ret;
/* Check if the legacy mapping should be used and the return qca8k_internal_mdio_read(slave_bus, port, regnum);
* port is not correctly mapped to the right PHY in the
* devicetree
*/
if (priv->legacy_phy_port_mapping)
port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
/* Use mdio Ethernet when available, fallback to legacy one on error */
ret = qca8k_phy_eth_command(priv, true, port, regnum, 0);
if (ret >= 0)
return ret;
ret = qca8k_mdio_read(priv, port, regnum);
if (ret < 0)
return 0xffff;
return ret;
} }
static int static int
qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio) qca8k_mdio_register(struct qca8k_priv *priv)
{ {
struct dsa_switch *ds = priv->ds; struct dsa_switch *ds = priv->ds;
struct device_node *mdio;
struct mii_bus *bus; struct mii_bus *bus;
bus = devm_mdiobus_alloc(ds->dev); bus = devm_mdiobus_alloc(ds->dev);
if (!bus) if (!bus)
return -ENOMEM; return -ENOMEM;
bus->priv = (void *)priv; bus->priv = (void *)priv;
bus->name = "qca8k slave mii"; snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d.%d",
bus->read = qca8k_internal_mdio_read; ds->dst->index, ds->index);
bus->write = qca8k_internal_mdio_write;
snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d",
ds->index);
bus->parent = ds->dev; bus->parent = ds->dev;
bus->phy_mask = ~ds->phys_mii_mask; bus->phy_mask = ~ds->phys_mii_mask;
ds->slave_mii_bus = bus; ds->slave_mii_bus = bus;
return devm_of_mdiobus_register(priv->dev, bus, mdio); /* Check if the devicetree declare the port:phy mapping */
mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
if (of_device_is_available(mdio)) {
bus->name = "qca8k slave mii";
bus->read = qca8k_internal_mdio_read;
bus->write = qca8k_internal_mdio_write;
return devm_of_mdiobus_register(priv->dev, bus, mdio);
}
/* If a mapping can't be found the legacy mapping is used,
* using the qca8k_port_to_phy function
*/
bus->name = "qca8k-legacy slave mii";
bus->read = qca8k_legacy_mdio_read;
bus->write = qca8k_legacy_mdio_write;
return devm_mdiobus_register(priv->dev, bus);
} }
static int static int
qca8k_setup_mdio_bus(struct qca8k_priv *priv) qca8k_setup_mdio_bus(struct qca8k_priv *priv)
{ {
u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg; u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg;
struct device_node *ports, *port, *mdio; struct device_node *ports, *port;
phy_interface_t mode; phy_interface_t mode;
int err; int err;
...@@ -1429,24 +1413,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv) ...@@ -1429,24 +1413,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
QCA8K_MDIO_MASTER_EN); QCA8K_MDIO_MASTER_EN);
} }
/* Check if the devicetree declare the port:phy mapping */ return qca8k_mdio_register(priv);
mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
if (of_device_is_available(mdio)) {
err = qca8k_mdio_register(priv, mdio);
if (err)
of_node_put(mdio);
return err;
}
/* If a mapping can't be found the legacy mapping is used,
* using the qca8k_port_to_phy function
*/
priv->legacy_phy_port_mapping = true;
priv->ops.phy_read = qca8k_phy_read;
priv->ops.phy_write = qca8k_phy_write;
return 0;
} }
static int static int
...@@ -2346,7 +2313,7 @@ qca8k_port_enable(struct dsa_switch *ds, int port, ...@@ -2346,7 +2313,7 @@ qca8k_port_enable(struct dsa_switch *ds, int port,
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
qca8k_port_set_status(priv, port, 1); qca8k_port_set_status(priv, port, 1);
priv->port_sts[port].enabled = 1; priv->port_enabled_map |= BIT(port);
if (dsa_is_user_port(ds, port)) if (dsa_is_user_port(ds, port))
phy_support_asym_pause(phy); phy_support_asym_pause(phy);
...@@ -2360,23 +2327,25 @@ qca8k_port_disable(struct dsa_switch *ds, int port) ...@@ -2360,23 +2327,25 @@ qca8k_port_disable(struct dsa_switch *ds, int port)
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
qca8k_port_set_status(priv, port, 0); qca8k_port_set_status(priv, port, 0);
priv->port_sts[port].enabled = 0; priv->port_enabled_map &= ~BIT(port);
} }
static int static int
qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{ {
struct qca8k_priv *priv = ds->priv; struct qca8k_priv *priv = ds->priv;
int i, mtu = 0;
priv->port_mtu[port] = new_mtu; /* We have only have a general MTU setting.
* DSA always set the CPU port's MTU to the largest MTU of the slave
for (i = 0; i < QCA8K_NUM_PORTS; i++) * ports.
if (priv->port_mtu[i] > mtu) * Setting MTU just for the CPU port is sufficient to correctly set a
mtu = priv->port_mtu[i]; * value for every port.
*/
if (!dsa_is_cpu_port(ds, port))
return 0;
/* Include L2 header / FCS length */ /* Include L2 header / FCS length */
return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN); return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, new_mtu + ETH_HLEN + ETH_FCS_LEN);
} }
static int static int
...@@ -3033,16 +3002,6 @@ qca8k_setup(struct dsa_switch *ds) ...@@ -3033,16 +3002,6 @@ qca8k_setup(struct dsa_switch *ds)
QCA8K_PORT_HOL_CTRL1_WRED_EN, QCA8K_PORT_HOL_CTRL1_WRED_EN,
mask); mask);
} }
/* Set initial MTU for every port.
* We have only have a general MTU setting. So track
* every port and set the max across all port.
* Set per port MTU to 1500 as the MTU change function
* will add the overhead and if its set to 1518 then it
* will apply the overhead again and we will end up with
* MTU of 1536 instead of 1518
*/
priv->port_mtu[i] = ETH_DATA_LEN;
} }
/* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */
...@@ -3202,8 +3161,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev) ...@@ -3202,8 +3161,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
priv->ds->dev = &mdiodev->dev; priv->ds->dev = &mdiodev->dev;
priv->ds->num_ports = QCA8K_NUM_PORTS; priv->ds->num_ports = QCA8K_NUM_PORTS;
priv->ds->priv = priv; priv->ds->priv = priv;
priv->ops = qca8k_switch_ops; priv->ds->ops = &qca8k_switch_ops;
priv->ds->ops = &priv->ops;
mutex_init(&priv->reg_mutex); mutex_init(&priv->reg_mutex);
dev_set_drvdata(&mdiodev->dev, priv); dev_set_drvdata(&mdiodev->dev, priv);
...@@ -3243,13 +3201,16 @@ static void qca8k_sw_shutdown(struct mdio_device *mdiodev) ...@@ -3243,13 +3201,16 @@ static void qca8k_sw_shutdown(struct mdio_device *mdiodev)
static void static void
qca8k_set_pm(struct qca8k_priv *priv, int enable) qca8k_set_pm(struct qca8k_priv *priv, int enable)
{ {
int i; int port;
for (i = 0; i < QCA8K_NUM_PORTS; i++) { for (port = 0; port < QCA8K_NUM_PORTS; port++) {
if (!priv->port_sts[i].enabled) /* Do not enable on resume if the port was
* disabled before.
*/
if (!(priv->port_enabled_map & BIT(port)))
continue; continue;
qca8k_port_set_status(priv, i, enable); qca8k_port_set_status(priv, port, enable);
} }
} }
......
...@@ -324,10 +324,6 @@ enum qca8k_mid_cmd { ...@@ -324,10 +324,6 @@ enum qca8k_mid_cmd {
QCA8K_MIB_CAST = 3, QCA8K_MIB_CAST = 3,
}; };
struct ar8xxx_port_status {
int enabled;
};
struct qca8k_match_data { struct qca8k_match_data {
u8 id; u8 id;
bool reduced_package; bool reduced_package;
...@@ -388,17 +384,17 @@ struct qca8k_priv { ...@@ -388,17 +384,17 @@ struct qca8k_priv {
u8 mirror_rx; u8 mirror_rx;
u8 mirror_tx; u8 mirror_tx;
u8 lag_hash_mode; u8 lag_hash_mode;
bool legacy_phy_port_mapping; /* Each bit correspond to a port. This switch can support a max of 7 port.
* Bit 1: port enabled. Bit 0: port disabled.
*/
u8 port_enabled_map;
struct qca8k_ports_config ports_config; struct qca8k_ports_config ports_config;
struct regmap *regmap; struct regmap *regmap;
struct mii_bus *bus; struct mii_bus *bus;
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
struct dsa_switch *ds; struct dsa_switch *ds;
struct mutex reg_mutex; struct mutex reg_mutex;
struct device *dev; struct device *dev;
struct dsa_switch_ops ops;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
unsigned int port_mtu[QCA8K_NUM_PORTS];
struct net_device *mgmt_master; /* Track if mdio/mib Ethernet is available */ struct net_device *mgmt_master; /* Track if mdio/mib Ethernet is available */
struct qca8k_mgmt_eth_data mgmt_eth_data; struct qca8k_mgmt_eth_data mgmt_eth_data;
struct qca8k_mib_eth_data mib_eth_data; struct qca8k_mib_eth_data mib_eth_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment