Changing the DSA master means different things depending on the tagging
protocol in use.
For NPI mode ("ocelot" and "seville"), there is a single port which can
be configured as NPI, but DSA only permits changing the CPU port
affinity of user ports one by one. So changing a user port to a
different NPI port globally changes what the NPI port is, and breaks the
user ports still using the old one.
To address this while still permitting the change of the NPI port,
require that the user ports which are still affine to the old NPI port
are down, and cannot be brought up until they are all affine to the same
NPI port.
The tag_8021q mode ("ocelot-8021q") is more flexible, in that each user
port can be freely assigned to one CPU port or to the other. This works
by filtering host addresses towards both tag_8021q CPU ports, and then
restricting the forwarding from a certain user port only to one of the
two tag_8021q CPU ports.
Additionally, the 2 tag_8021q CPU ports can be placed in a LAG. This
works by enabling forwarding via PGID_SRC from a certain user port
towards the logical port ID containing both tag_8021q CPU ports, but
then restricting forwarding per packet, via the LAG hash codes in
PGID_AGGR, to either one or the other.
When we change the DSA master to a LAG device, DSA guarantees us that
the LAG has at least one lower interface as a physical DSA master.
But DSA masters can come and go as lowers of that LAG, and
ds->ops->port_change_master() will not get called, because the DSA
master is still the same (the LAG). So we need to hook into the
ds->ops->port_lag_{join,leave} calls on the CPU ports and update the
logical port ID of the LAG that user ports are assigned to.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
101 lines
3.5 KiB
C
101 lines
3.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright 2019 NXP
|
|
*/
|
|
#ifndef _MSCC_FELIX_H
|
|
#define _MSCC_FELIX_H
|
|
|
|
#define ocelot_to_felix(o) container_of((o), struct felix, ocelot)
|
|
#define FELIX_MAC_QUIRKS OCELOT_QUIRK_PCS_PERFORMS_RATE_ADAPTATION
|
|
|
|
#define OCELOT_PORT_MODE_INTERNAL BIT(0)
|
|
#define OCELOT_PORT_MODE_SGMII BIT(1)
|
|
#define OCELOT_PORT_MODE_QSGMII BIT(2)
|
|
#define OCELOT_PORT_MODE_2500BASEX BIT(3)
|
|
#define OCELOT_PORT_MODE_USXGMII BIT(4)
|
|
#define OCELOT_PORT_MODE_1000BASEX BIT(5)
|
|
|
|
/* Platform-specific information */
|
|
struct felix_info {
|
|
const struct resource *target_io_res;
|
|
const struct resource *port_io_res;
|
|
const struct resource *imdio_res;
|
|
const struct reg_field *regfields;
|
|
const u32 *const *map;
|
|
const struct ocelot_ops *ops;
|
|
const u32 *port_modes;
|
|
int num_mact_rows;
|
|
const struct ocelot_stat_layout *stats_layout;
|
|
int num_ports;
|
|
int num_tx_queues;
|
|
struct vcap_props *vcap;
|
|
u16 vcap_pol_base;
|
|
u16 vcap_pol_max;
|
|
u16 vcap_pol_base2;
|
|
u16 vcap_pol_max2;
|
|
const struct ptp_clock_info *ptp_caps;
|
|
|
|
/* Some Ocelot switches are integrated into the SoC without the
|
|
* extraction IRQ line connected to the ARM GIC. By enabling this
|
|
* workaround, the few packets that are delivered to the CPU port
|
|
* module (currently only PTP) are copied not only to the hardware CPU
|
|
* port module, but also to the 802.1Q Ethernet CPU port, and polling
|
|
* the extraction registers is triggered once the DSA tagger sees a PTP
|
|
* frame. The Ethernet frame is only used as a notification: it is
|
|
* dropped, and the original frame is extracted over MMIO and annotated
|
|
* with the RX timestamp.
|
|
*/
|
|
bool quirk_no_xtr_irq;
|
|
|
|
int (*mdio_bus_alloc)(struct ocelot *ocelot);
|
|
void (*mdio_bus_free)(struct ocelot *ocelot);
|
|
void (*phylink_validate)(struct ocelot *ocelot, int port,
|
|
unsigned long *supported,
|
|
struct phylink_link_state *state);
|
|
int (*port_setup_tc)(struct dsa_switch *ds, int port,
|
|
enum tc_setup_type type, void *type_data);
|
|
void (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
|
|
void (*port_sched_speed_set)(struct ocelot *ocelot, int port,
|
|
u32 speed);
|
|
struct regmap *(*init_regmap)(struct ocelot *ocelot,
|
|
struct resource *res);
|
|
};
|
|
|
|
/* Methods for initializing the hardware resources specific to a tagging
|
|
* protocol (like the NPI port, for "ocelot" or "seville", or the VCAP TCAMs,
|
|
* for "ocelot-8021q").
|
|
* It is important that the resources configured here do not have side effects
|
|
* for the other tagging protocols. If that is the case, their configuration
|
|
* needs to go to felix_tag_proto_setup_shared().
|
|
*/
|
|
struct felix_tag_proto_ops {
|
|
int (*setup)(struct dsa_switch *ds);
|
|
void (*teardown)(struct dsa_switch *ds);
|
|
unsigned long (*get_host_fwd_mask)(struct dsa_switch *ds);
|
|
int (*change_master)(struct dsa_switch *ds, int port,
|
|
struct net_device *master,
|
|
struct netlink_ext_ack *extack);
|
|
};
|
|
|
|
extern const struct dsa_switch_ops felix_switch_ops;
|
|
|
|
/* DSA glue / front-end for struct ocelot */
|
|
struct felix {
|
|
struct dsa_switch *ds;
|
|
const struct felix_info *info;
|
|
struct ocelot ocelot;
|
|
struct mii_bus *imdio;
|
|
struct phylink_pcs **pcs;
|
|
resource_size_t switch_base;
|
|
resource_size_t imdio_base;
|
|
enum dsa_tag_protocol tag_proto;
|
|
const struct felix_tag_proto_ops *tag_proto_ops;
|
|
struct kthread_worker *xmit_worker;
|
|
unsigned long host_flood_uc_mask;
|
|
unsigned long host_flood_mc_mask;
|
|
};
|
|
|
|
struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port);
|
|
int felix_netdev_to_port(struct net_device *dev);
|
|
|
|
#endif
|