diff options
Diffstat (limited to 'drivers/net/dsa/ocelot')
-rw-r--r-- | drivers/net/dsa/ocelot/felix.c | 24 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/felix.h | 7 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/felix_vsc9959.c | 43 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/ocelot_ext.c | 18 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/seville_vsc9953.c | 2 |
5 files changed, 69 insertions, 25 deletions
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index d4cc9e60f369..80861ac090ae 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1056,6 +1056,17 @@ static void felix_phylink_get_caps(struct dsa_switch *ds, int port, config->supported_interfaces); } +static void felix_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + + if (felix->info->phylink_mac_config) + felix->info->phylink_mac_config(ocelot, port, mode, state); +} + static struct phylink_pcs *felix_phylink_mac_select_pcs(struct dsa_switch *ds, int port, phy_interface_t iface) @@ -1539,11 +1550,6 @@ static int felix_connect_tag_protocol(struct dsa_switch *ds, } } -/* Hardware initialization done here so that we can allocate structures with - * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing - * us to allocate structures twice (leak memory) and map PCI memory twice - * (which will not work). - */ static int felix_setup(struct dsa_switch *ds) { struct ocelot *ocelot = ds->priv; @@ -1555,6 +1561,9 @@ static int felix_setup(struct dsa_switch *ds) if (err) return err; + if (ocelot->targets[HSIO]) + ocelot_pll5_init(ocelot); + err = ocelot_init(ocelot); if (err) goto out_mdiobus_free; @@ -1571,6 +1580,10 @@ static int felix_setup(struct dsa_switch *ds) dsa_switch_for_each_available_port(dp, ds) { ocelot_init_port(ocelot, dp->index); + if (felix->info->configure_serdes) + felix->info->configure_serdes(ocelot, dp->index, + dp->dn); + /* Set the default QoS Classification based on PCP and DEI * bits of vlan tag. */ @@ -2085,6 +2098,7 @@ const struct dsa_switch_ops felix_switch_ops = { .get_sset_count = felix_get_sset_count, .get_ts_info = felix_get_ts_info, .phylink_get_caps = felix_phylink_get_caps, + .phylink_mac_config = felix_phylink_mac_config, .phylink_mac_select_pcs = felix_phylink_mac_select_pcs, .phylink_mac_link_down = felix_phylink_mac_link_down, .phylink_mac_link_up = felix_phylink_mac_link_up, diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index d5d0b30c0b75..96008c046da5 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -15,6 +15,8 @@ #define OCELOT_PORT_MODE_USXGMII BIT(4) #define OCELOT_PORT_MODE_1000BASEX BIT(5) +struct device_node; + /* Platform-specific information */ struct felix_info { /* Hardcoded resources provided by the hardware instantiation. */ @@ -58,6 +60,11 @@ struct felix_info { void (*tas_guard_bands_update)(struct ocelot *ocelot, int port); void (*port_sched_speed_set)(struct ocelot *ocelot, int port, u32 speed); + void (*phylink_mac_config)(struct ocelot *ocelot, int port, + unsigned int mode, + const struct phylink_link_state *state); + int (*configure_serdes)(struct ocelot *ocelot, int port, + struct device_node *portnp); }; /* Methods for initializing the hardware resources specific to a tagging diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index dddb28984bdf..cfb3faeaa5bf 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1424,6 +1424,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, mutex_lock(&ocelot->tas_lock); if (!taprio->enable) { + ocelot_port_mqprio(ocelot, port, &taprio->mqprio); ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE, QSYS_TAG_CONFIG, port); @@ -1436,15 +1437,19 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, return 0; } + ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio); + if (ret) + goto err_unlock; + if (taprio->cycle_time > NSEC_PER_SEC || taprio->cycle_time_extension >= NSEC_PER_SEC) { ret = -EINVAL; - goto err; + goto err_reset_tc; } if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX) { ret = -ERANGE; - goto err; + goto err_reset_tc; } /* Enable guard band. The switch will schedule frames without taking @@ -1468,7 +1473,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8); if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING) { ret = -EBUSY; - goto err; + goto err_reset_tc; } ocelot_rmw_rix(ocelot, @@ -1503,12 +1508,19 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, !(val & QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE), 10, 100000); if (ret) - goto err; + goto err_reset_tc; ocelot_port->taprio = taprio_offload_get(taprio); vsc9959_tas_guard_bands_update(ocelot, port); -err: + mutex_unlock(&ocelot->tas_lock); + + return 0; + +err_reset_tc: + taprio->mqprio.qopt.num_tc = 0; + ocelot_port_mqprio(ocelot, port, &taprio->mqprio); +err_unlock: mutex_unlock(&ocelot->tas_lock); return ret; @@ -1612,6 +1624,13 @@ static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port, static int vsc9959_qos_query_caps(struct tc_query_caps_base *base) { switch (base->type) { + case TC_SETUP_QDISC_MQPRIO: { + struct tc_mqprio_caps *caps = base->caps; + + caps->validate_queue_counts = true; + + return 0; + } case TC_SETUP_QDISC_TAPRIO: { struct tc_taprio_caps *caps = base->caps; @@ -1635,6 +1654,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, return vsc9959_qos_query_caps(type_data); case TC_SETUP_QDISC_TAPRIO: return vsc9959_qos_port_tas_set(ocelot, port, type_data); + case TC_SETUP_QDISC_MQPRIO: + return ocelot_port_mqprio(ocelot, port, type_data); case TC_SETUP_QDISC_CBS: return vsc9959_qos_port_cbs_set(ds, port, type_data); default: @@ -2498,6 +2519,7 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot) for (port = 0; port < ocelot->num_phys_ports; port++) { struct ocelot_port *ocelot_port = ocelot->ports[port]; + struct ocelot_mm_state *mm = &ocelot->mm[port]; int min_speed = ocelot_port->speed; unsigned long mask = 0; u32 tmp, val = 0; @@ -2538,10 +2560,12 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot) /* Enable cut-through forwarding for all traffic classes that * don't have oversized dropping enabled, since this check is - * bypassed in cut-through mode. + * bypassed in cut-through mode. Also exclude preemptible + * traffic classes, since these would hang the port for some + * reason, if sent as cut-through. */ if (ocelot_port->speed == min_speed) { - val = GENMASK(7, 0); + val = GENMASK(7, 0) & ~mm->active_preemptible_tcs; for (tc = 0; tc < OCELOT_NUM_TC; tc++) if (vsc9959_port_qmaxsdu_get(ocelot, port, tc)) @@ -2610,12 +2634,9 @@ static const struct felix_info felix_info_vsc9959 = { static irqreturn_t felix_irq_handler(int irq, void *data) { struct ocelot *ocelot = (struct ocelot *)data; - int port; ocelot_get_txtstamp(ocelot); - - for (port = 0; port < ocelot->num_phys_ports; port++) - ocelot_port_mm_irq(ocelot, port); + ocelot_mm_irq(ocelot); return IRQ_HANDLED; } diff --git a/drivers/net/dsa/ocelot/ocelot_ext.c b/drivers/net/dsa/ocelot/ocelot_ext.c index 063150659816..c29bee5a5c48 100644 --- a/drivers/net/dsa/ocelot/ocelot_ext.c +++ b/drivers/net/dsa/ocelot/ocelot_ext.c @@ -20,13 +20,13 @@ static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = { OCELOT_PORT_MODE_INTERNAL, OCELOT_PORT_MODE_INTERNAL, OCELOT_PORT_MODE_INTERNAL, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SGMII, + OCELOT_PORT_MODE_SERDES, }; static const struct ocelot_ops ocelot_ext_ops = { @@ -59,6 +59,8 @@ static const struct felix_info vsc7512_info = { .num_ports = VSC7514_NUM_PORTS, .num_tx_queues = OCELOT_NUM_TC, .port_modes = vsc7512_port_modes, + .phylink_mac_config = ocelot_phylink_mac_config, + .configure_serdes = ocelot_port_configure_serdes, }; static int ocelot_ext_probe(struct platform_device *pdev) @@ -149,7 +151,7 @@ MODULE_DEVICE_TABLE(of, ocelot_ext_switch_of_match); static struct platform_driver ocelot_ext_switch_driver = { .driver = { .name = "ocelot-ext-switch", - .of_match_table = of_match_ptr(ocelot_ext_switch_of_match), + .of_match_table = ocelot_ext_switch_of_match, }, .probe = ocelot_ext_probe, .remove = ocelot_ext_remove, diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 563ad338da25..96d4972a62f0 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1079,7 +1079,7 @@ static struct platform_driver seville_vsc9953_driver = { .shutdown = seville_shutdown, .driver = { .name = "mscc_seville", - .of_match_table = of_match_ptr(seville_of_match), + .of_match_table = seville_of_match, }, }; module_platform_driver(seville_vsc9953_driver); |