diff options
-rw-r--r-- | drivers/net/dsa/ocelot/felix_vsc9959.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 12810fea2075..26a35ae322d1 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1194,6 +1194,14 @@ static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc) } } +static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc) +{ + if (!taprio || !taprio->max_sdu[tc]) + return 0; + + return taprio->max_sdu[tc] + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN; +} + /* Update QSYS_PORT_MAX_SDU to make sure the static guard bands added by the * switch (see the ALWAYS_GUARD_BAND_SCH_Q comment) are correct at all MTU * values (the default value is 1518). Also, for traffic class windows smaller @@ -1203,6 +1211,7 @@ static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc) static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) { struct ocelot_port *ocelot_port = ocelot->ports[port]; + struct tc_taprio_qopt_offload *taprio; u64 min_gate_len[OCELOT_NUM_TC]; int speed, picos_per_byte; u64 needed_bit_time_ps; @@ -1212,6 +1221,8 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) lockdep_assert_held(&ocelot->tas_lock); + taprio = ocelot_port->taprio; + val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port); tas_speed = QSYS_TAG_CONFIG_LINK_SPEED_X(val); @@ -1248,11 +1259,12 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) "port %d: max frame size %d needs %llu ps at speed %d\n", port, maxlen, needed_bit_time_ps, speed); - vsc9959_tas_min_gate_lengths(ocelot_port->taprio, min_gate_len); + vsc9959_tas_min_gate_lengths(taprio, min_gate_len); mutex_lock(&ocelot->fwd_domain_lock); for (tc = 0; tc < OCELOT_NUM_TC; tc++) { + u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc); u64 remaining_gate_len_ps; u32 max_sdu; @@ -1263,7 +1275,7 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) /* Setting QMAXSDU_CFG to 0 disables oversized frame * dropping. */ - max_sdu = 0; + max_sdu = requested_max_sdu; dev_dbg(ocelot->dev, "port %d tc %d min gate len %llu" ", sending all frames\n", @@ -1294,6 +1306,10 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) */ if (max_sdu > 20) max_sdu -= 20; + + if (requested_max_sdu && requested_max_sdu < max_sdu) + max_sdu = requested_max_sdu; + dev_info(ocelot->dev, "port %d tc %d min gate length %llu" " ns not enough for max frame size %d at %d" @@ -1583,6 +1599,21 @@ static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port, return 0; } +static int vsc9959_qos_query_caps(struct tc_query_caps_base *base) +{ + switch (base->type) { + case TC_SETUP_QDISC_TAPRIO: { + struct tc_taprio_caps *caps = base->caps; + + caps->supports_queue_max_sdu = true; + + return 0; + } + default: + return -EOPNOTSUPP; + } +} + static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, enum tc_setup_type type, void *type_data) @@ -1590,6 +1621,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, struct ocelot *ocelot = ds->priv; switch (type) { + case TC_QUERY_CAPS: + 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_CBS: |