164 lines
5.8 KiB
Diff
164 lines
5.8 KiB
Diff
|
From c6f39379529e74eccbe317e70bb11d18110c63d4 Mon Sep 17 00:00:00 2001
|
||
|
From: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||
|
Date: Sat, 9 Nov 2019 15:03:00 +0200
|
||
|
Subject: [PATCH] net: mscc: ocelot: split assignment of the cpu port into a
|
||
|
separate function
|
||
|
|
||
|
Now that the places that configure routing destinations for the CPU port
|
||
|
have been marked as such, allow callers to specify their own CPU port
|
||
|
that is different than ocelot->num_phys_ports. A user will be the Felix
|
||
|
DSA driver, where the CPU port is one of the physical ports (NPI mode).
|
||
|
|
||
|
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||
|
---
|
||
|
drivers/net/ethernet/mscc/ocelot.c | 65 +++++++++++++++++++++-----------
|
||
|
drivers/net/ethernet/mscc/ocelot.h | 12 ++++++
|
||
|
drivers/net/ethernet/mscc/ocelot_board.c | 2 +
|
||
|
3 files changed, 57 insertions(+), 22 deletions(-)
|
||
|
|
||
|
--- a/drivers/net/ethernet/mscc/ocelot.c
|
||
|
+++ b/drivers/net/ethernet/mscc/ocelot.c
|
||
|
@@ -380,12 +380,6 @@ static void ocelot_vlan_init(struct ocel
|
||
|
ocelot->vlan_mask[0] = GENMASK(ocelot->num_phys_ports - 1, 0);
|
||
|
ocelot_vlant_set_mask(ocelot, 0, ocelot->vlan_mask[0]);
|
||
|
|
||
|
- /* Configure the CPU port to be VLAN aware */
|
||
|
- ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
|
||
|
- ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
|
||
|
- ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
|
||
|
- ANA_PORT_VLAN_CFG, ocelot->num_phys_ports);
|
||
|
-
|
||
|
/* Set vlan ingress filter mask to all ports but the CPU port by
|
||
|
* default.
|
||
|
*/
|
||
|
@@ -2228,11 +2222,52 @@ int ocelot_probe_port(struct ocelot *oce
|
||
|
}
|
||
|
EXPORT_SYMBOL(ocelot_probe_port);
|
||
|
|
||
|
+void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
|
||
|
+ enum ocelot_tag_prefix injection,
|
||
|
+ enum ocelot_tag_prefix extraction)
|
||
|
+{
|
||
|
+ /* Configure and enable the CPU port. */
|
||
|
+ ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
|
||
|
+ ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
|
||
|
+ ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
|
||
|
+ ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
|
||
|
+ ANA_PORT_PORT_CFG, cpu);
|
||
|
+
|
||
|
+ /* If the CPU port is a physical port, set up the port in Node
|
||
|
+ * Processor Interface (NPI) mode. This is the mode through which
|
||
|
+ * frames can be injected from and extracted to an external CPU.
|
||
|
+ * Only one port can be an NPI at the same time.
|
||
|
+ */
|
||
|
+ if (cpu < ocelot->num_phys_ports) {
|
||
|
+ ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
|
||
|
+ QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu),
|
||
|
+ QSYS_EXT_CPU_CFG);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* CPU port Injection/Extraction configuration */
|
||
|
+ ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
|
||
|
+ QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
|
||
|
+ QSYS_SWITCH_PORT_MODE_PORT_ENA,
|
||
|
+ QSYS_SWITCH_PORT_MODE, cpu);
|
||
|
+ ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(extraction) |
|
||
|
+ SYS_PORT_MODE_INCL_INJ_HDR(injection),
|
||
|
+ SYS_PORT_MODE, cpu);
|
||
|
+
|
||
|
+ /* Configure the CPU port to be VLAN aware */
|
||
|
+ ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
|
||
|
+ ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
|
||
|
+ ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
|
||
|
+ ANA_PORT_VLAN_CFG, cpu);
|
||
|
+
|
||
|
+ ocelot->cpu = cpu;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL(ocelot_set_cpu_port);
|
||
|
+
|
||
|
int ocelot_init(struct ocelot *ocelot)
|
||
|
{
|
||
|
- u32 port;
|
||
|
- int i, ret, cpu = ocelot->num_phys_ports;
|
||
|
char queue_name[32];
|
||
|
+ int i, ret;
|
||
|
+ u32 port;
|
||
|
|
||
|
ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
|
||
|
sizeof(u32), GFP_KERNEL);
|
||
|
@@ -2312,13 +2347,6 @@ int ocelot_init(struct ocelot *ocelot)
|
||
|
ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_SRC + port);
|
||
|
}
|
||
|
|
||
|
- /* Configure and enable the CPU port. */
|
||
|
- ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
|
||
|
- ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
|
||
|
- ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
|
||
|
- ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
|
||
|
- ANA_PORT_PORT_CFG, cpu);
|
||
|
-
|
||
|
/* Allow broadcast MAC frames. */
|
||
|
for (i = ocelot->num_phys_ports + 1; i < PGID_CPU; i++) {
|
||
|
u32 val = ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports - 1, 0));
|
||
|
@@ -2331,13 +2359,6 @@ int ocelot_init(struct ocelot *ocelot)
|
||
|
ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV4);
|
||
|
ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV6);
|
||
|
|
||
|
- /* CPU port Injection/Extraction configuration */
|
||
|
- ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
|
||
|
- QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
|
||
|
- QSYS_SWITCH_PORT_MODE_PORT_ENA,
|
||
|
- QSYS_SWITCH_PORT_MODE, cpu);
|
||
|
- ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(1) |
|
||
|
- SYS_PORT_MODE_INCL_INJ_HDR(1), SYS_PORT_MODE, cpu);
|
||
|
/* Allow manual injection via DEVCPU_QS registers, and byte swap these
|
||
|
* registers endianness.
|
||
|
*/
|
||
|
--- a/drivers/net/ethernet/mscc/ocelot.h
|
||
|
+++ b/drivers/net/ethernet/mscc/ocelot.h
|
||
|
@@ -427,6 +427,13 @@ struct ocelot_multicast {
|
||
|
u16 ports;
|
||
|
};
|
||
|
|
||
|
+enum ocelot_tag_prefix {
|
||
|
+ OCELOT_TAG_PREFIX_DISABLED = 0,
|
||
|
+ OCELOT_TAG_PREFIX_NONE,
|
||
|
+ OCELOT_TAG_PREFIX_SHORT,
|
||
|
+ OCELOT_TAG_PREFIX_LONG,
|
||
|
+};
|
||
|
+
|
||
|
struct ocelot_port;
|
||
|
|
||
|
struct ocelot_stat_layout {
|
||
|
@@ -455,6 +462,7 @@ struct ocelot {
|
||
|
|
||
|
u8 num_phys_ports;
|
||
|
u8 num_cpu_ports;
|
||
|
+ u8 cpu;
|
||
|
struct ocelot_port **ports;
|
||
|
|
||
|
u32 *lags;
|
||
|
@@ -552,6 +560,10 @@ int ocelot_probe_port(struct ocelot *oce
|
||
|
void __iomem *regs,
|
||
|
struct phy_device *phy);
|
||
|
|
||
|
+void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
|
||
|
+ enum ocelot_tag_prefix injection,
|
||
|
+ enum ocelot_tag_prefix extraction);
|
||
|
+
|
||
|
extern struct notifier_block ocelot_netdevice_nb;
|
||
|
extern struct notifier_block ocelot_switchdev_nb;
|
||
|
extern struct notifier_block ocelot_switchdev_blocking_nb;
|
||
|
--- a/drivers/net/ethernet/mscc/ocelot_board.c
|
||
|
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
|
||
|
@@ -373,6 +373,8 @@ static int mscc_ocelot_probe(struct plat
|
||
|
sizeof(struct ocelot_port *), GFP_KERNEL);
|
||
|
|
||
|
ocelot_init(ocelot);
|
||
|
+ ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports,
|
||
|
+ OCELOT_TAG_PREFIX_NONE, OCELOT_TAG_PREFIX_NONE);
|
||
|
|
||
|
for_each_available_child_of_node(ports, portnp) {
|
||
|
struct ocelot_port_private *priv;
|