From: John Crispin <john@phrozen.org>
To: Andrew Lunn <andrew@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Florian Fainelli <f.fainelli@gmail.com>,
Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Cc: netdev@vger.kernel.org, John Crispin <john@phrozen.org>
Subject: [RFC 4/4] net-next: dsa: qca8k: add support for multiple cpu ports
Date: Wed, 4 Jan 2017 08:38:04 +0100 [thread overview]
Message-ID: <1483515484-21793-5-git-send-email-john@phrozen.org> (raw)
In-Reply-To: <1483515484-21793-1-git-send-email-john@phrozen.org>
With the subsystem now supporting multiple cpu ports, we need to make some
changes to the driver as it currently has the cpu port hardcoded as port0.
The patch moves the setup logic for the cpu port into one loop which
iterates over all cpu ports and sets them up. Additionally the bridge
join/leave logic needs a small fix to work with having a cpu port other
than 0.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/dsa/qca8k.c | 135 +++++++++++++++++++++++++++--------------------
drivers/net/dsa/qca8k.h | 2 -
2 files changed, 78 insertions(+), 59 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index b3df70d..1693388 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -486,11 +486,25 @@
qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
}
+static void
+qca8k_setup_flooding(struct qca8k_priv *priv, int port_mask, int enable)
+{
+ u32 mask = (port_mask << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S) |
+ (port_mask << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S) |
+ (port_mask << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S) |
+ (port_mask << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
+
+ if (enable)
+ qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL1, mask);
+ else
+ qca8k_reg_clear(priv, QCA8K_REG_GLOBAL_FW_CTRL1, mask);
+}
+
static int
qca8k_setup(struct dsa_switch *ds)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
- int ret, i, phy_mode = -1;
+ int ret, i;
/* Make sure that port 0 is the cpu port */
if (!dsa_is_cpu_port(ds, 0)) {
@@ -506,29 +520,49 @@
if (IS_ERR(priv->regmap))
pr_warn("regmap initialization failed");
- /* Initialize CPU port pad mode (xMII type, delays...) */
- phy_mode = of_get_phy_mode(ds->ports[ds->dst->cpu_port].dn);
- if (phy_mode < 0) {
- pr_err("Can't find phy-mode for master device\n");
- return phy_mode;
- }
- ret = qca8k_set_pad_ctrl(priv, QCA8K_CPU_PORT, phy_mode);
- if (ret < 0)
- return ret;
-
- /* Enable CPU Port */
+ /* Tell the switch that port0 is a cpu port */
qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
- qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1);
- priv->port_sts[QCA8K_CPU_PORT].enabled = 1;
/* Enable MIB counters */
qca8k_mib_init(priv);
- /* Enable QCA header mode on the cpu port */
- qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
+ /* Setup the cpu ports */
+ for (i = 0; i < DSA_MAX_PORTS; i++) {
+ struct net_device *netdev;
+ int phy_mode = -1;
+
+ if (!dsa_is_cpu_port(ds, i))
+ continue;
+
+ netdev = ds->dst->pd->chip->port_ethernet[i];
+ if (!netdev) {
+ pr_err("Can't find netdev for port%d\n", i);
+ return -ENODEV;
+ }
+
+ /* Initialize CPU port pad mode (xMII type, delays...) */
+ phy_mode = of_get_phy_mode(netdev->dev.parent->of_node);
+ if (phy_mode < 0) {
+ pr_err("Can't find phy-mode for port:%d\n", i);
+ return phy_mode;
+ }
+ ret = qca8k_set_pad_ctrl(priv, i, phy_mode);
+ if (ret < 0)
+ return ret;
+
+ /* Enable QCA header mode on the cpu port */
+ qca8k_write(priv,
+ QCA8K_REG_PORT_HDR_CTRL(i),
+ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
+ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
+
+ qca8k_port_set_status(priv, i, 1);
+ priv->port_sts[i].enabled = 1;
+
+ /* Forward all unknown frames to CPU port for Linux processing */
+ qca8k_setup_flooding(priv, BIT(i), 1);
+ }
/* Disable forwarding by default on all ports */
for (i = 0; i < QCA8K_NUM_PORTS; i++)
@@ -540,43 +574,30 @@
if (ds->enabled_port_mask & BIT(i))
qca8k_port_set_status(priv, i, 0);
- /* Forward all unknown frames to CPU port for Linux processing */
- qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
-
- /* Setup connection between CPU port & user ports */
+ /* Setup user ports and connections to CPU ports */
for (i = 0; i < DSA_MAX_PORTS; i++) {
- /* CPU port gets connected to all user ports of the switch */
- if (dsa_is_cpu_port(ds, i)) {
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
- QCA8K_PORT_LOOKUP_MEMBER,
- ds->enabled_port_mask);
- }
+ int shift = 16 * (i % 2);
+ int cpu_port;
- /* Invividual user ports get connected to CPU port only */
- if (ds->enabled_port_mask & BIT(i)) {
- int shift = 16 * (i % 2);
-
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
- QCA8K_PORT_LOOKUP_MEMBER,
- BIT(QCA8K_CPU_PORT));
-
- /* Enable ARP Auto-learning by default */
- qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
- QCA8K_PORT_LOOKUP_LEARN);
-
- /* For port based vlans to work we need to set the
- * default egress vid
- */
- qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
- 0xffff << shift, 1 << shift);
- qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
- QCA8K_PORT_VLAN_CVID(1) |
- QCA8K_PORT_VLAN_SVID(1));
- }
+ if (!(ds->enabled_port_mask & BIT(i)))
+ continue;
+
+ cpu_port = dsa_port_upstream_port(ds, i);
+ qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), BIT(cpu_port));
+ qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), BIT(i));
+
+ /* Enable ARP Auto-learning by default */
+ qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
+ QCA8K_PORT_LOOKUP_LEARN);
+
+ /* For port based vlans to work we need to set the
+ * default egress vid
+ */
+ qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
+ 0xffff << shift, 1 << shift);
+ qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
+ QCA8K_PORT_VLAN_CVID(1) |
+ QCA8K_PORT_VLAN_SVID(1));
}
/* Flush the FDB table */
@@ -750,7 +771,7 @@
struct net_device *bridge)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
- int port_mask = BIT(QCA8K_CPU_PORT);
+ int port_mask = 0;
int i;
priv->port_sts[port].bridge_dev = bridge;
@@ -768,8 +789,7 @@
port_mask |= BIT(i);
}
/* Add all other ports to this ports portvlan mask */
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
- QCA8K_PORT_LOOKUP_MEMBER, port_mask);
+ qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(port), port_mask);
return 0;
}
@@ -796,7 +816,8 @@
* this port
*/
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
- QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT));
+ QCA8K_PORT_LOOKUP_MEMBER,
+ BIT(dsa_port_upstream_port(ds, i)));
}
static int
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index 2014647..aca6abb 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -26,8 +26,6 @@
#define QCA8K_NUM_FDB_RECORDS 2048
-#define QCA8K_CPU_PORT 0
-
/* Global control registers */
#define QCA8K_REG_MASK_CTRL 0x000
#define QCA8K_MASK_CTRL_ID_M 0xff
--
1.7.10.4
next prev parent reply other threads:[~2017-01-04 7:38 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-04 7:38 [RFC 0/4] net-next: dsa: add support for multiple cpu ports John Crispin
2017-01-04 7:38 ` [RFC 1/4] Documentation: devicetree: add multiple cpu port DSA binding John Crispin
2017-01-04 12:58 ` Andrew Lunn
2017-01-04 7:38 ` [RFC 2/4] net-next: dsa: Refactor DT probing of a switch port John Crispin
2017-01-04 13:30 ` Andrew Lunn
2017-01-04 7:38 ` [RFC 3/4] net-next: dsa: Add support for multiple cpu ports John Crispin
2017-01-04 13:22 ` Andrew Lunn
2017-01-04 14:01 ` Andrew Lunn
2017-01-04 14:40 ` Florian Fainelli
2017-01-04 15:22 ` Andrew Lunn
2017-01-04 7:38 ` John Crispin [this message]
2017-01-04 14:12 ` [RFC 4/4] net-next: dsa: qca8k: add " Andrew Lunn
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=1483515484-21793-5-git-send-email-john@phrozen.org \
--to=john@phrozen.org \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=f.fainelli@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=vivien.didelot@savoirfairelinux.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;
as well as URLs for NNTP newsgroup(s).