Initial Felix-driver products (VSC9959 and VSC9953) both had quirks where the PCS was in charge of rate adaptation. In the case of the VSC7512 there is a differnce in that some ports (ports 0-3) don't have a PCS and others might have different quirks based on how they are configured. This adds a generic method by which any port can have any quirks that are handled by each device's driver. Signed-off-by: Colin Foster <colin.foster@xxxxxxxxxxxxxxxx> --- drivers/net/dsa/ocelot/felix.c | 20 +++++++++++++++++--- drivers/net/dsa/ocelot/felix.h | 4 ++++ drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + drivers/net/dsa/ocelot/seville_vsc9953.c | 1 + 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 615f6b84c688..f53db233148d 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -824,14 +824,25 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port, phylink_set_pcs(dp->pl, &felix->pcs[port]->pcs); } +unsigned long felix_quirks_have_rate_adaptation(struct ocelot *ocelot, + int port) +{ + return FELIX_MAC_QUIRKS; +} +EXPORT_SYMBOL(felix_quirks_have_rate_adaptation); + static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int link_an_mode, phy_interface_t interface) { struct ocelot *ocelot = ds->priv; + unsigned long quirks; + struct felix *felix; + felix = ocelot_to_felix(ocelot); + quirks = felix->info->get_quirk_for_port(ocelot, port); ocelot_phylink_mac_link_down(ocelot, port, link_an_mode, interface, - FELIX_MAC_QUIRKS); + quirks); } static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, @@ -842,11 +853,14 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, bool tx_pause, bool rx_pause) { struct ocelot *ocelot = ds->priv; - struct felix *felix = ocelot_to_felix(ocelot); + unsigned long quirks; + struct felix *felix; + felix = ocelot_to_felix(ocelot); + quirks = felix->info->get_quirk_for_port(ocelot, port); ocelot_phylink_mac_link_up(ocelot, port, phydev, link_an_mode, interface, speed, duplex, tx_pause, rx_pause, - FELIX_MAC_QUIRKS); + quirks); if (felix->info->port_sched_speed_set) felix->info->port_sched_speed_set(ocelot, port, speed); diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 81a86bd60f03..b5fa5b7325b1 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -48,6 +48,7 @@ struct felix_info { u32 speed); struct regmap *(*init_regmap)(struct ocelot *ocelot, struct resource *res); + unsigned long (*get_quirk_for_port)(struct ocelot *ocelot, int port); }; extern const struct dsa_switch_ops felix_switch_ops; @@ -68,4 +69,7 @@ struct felix { struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port); int felix_netdev_to_port(struct net_device *dev); +unsigned long felix_quirks_have_rate_adaptation(struct ocelot *ocelot, + int port); + #endif diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 789e1ff0d13b..5056f39dc47e 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1368,6 +1368,7 @@ static const struct felix_info felix_info_vsc9959 = { .port_setup_tc = vsc9959_port_setup_tc, .port_sched_speed_set = vsc9959_sched_speed_set, .init_regmap = ocelot_regmap_init, + .get_quirk_for_port = felix_quirks_have_rate_adaptation, }; static irqreturn_t felix_irq_handler(int irq, void *data) diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 47da279a8ff7..362ba66401d8 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1088,6 +1088,7 @@ static const struct felix_info seville_info_vsc9953 = { .phylink_validate = vsc9953_phylink_validate, .prevalidate_phy_mode = vsc9953_prevalidate_phy_mode, .init_regmap = ocelot_regmap_init, + .get_quirk_for_port = felix_quirks_have_rate_adaptation, }; static int seville_probe(struct platform_device *pdev) -- 2.25.1