diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2023-04-15 20:05:51 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-04-17 19:01:19 -0700 |
commit | 403ffc2c34de5297d007e0e169bf022094d444c2 (patch) | |
tree | 50c835cd0c7aaad2aedd9a49e5695f55c1e46523 /drivers/net/ethernet/mscc/ocelot.c | |
parent | a1ca9f8b07d865224a6e4b1c41692f10bd95a311 (diff) |
net: mscc: ocelot: add support for preemptible traffic classes
In order to not transmit (preemptible) frames which will be received by
the link partner as corrupted (because it doesn't support FP), the
hardware requires the driver to program the QSYS_PREEMPTION_CFG_P_QUEUES
register only after the MAC Merge layer becomes active (verification
succeeds, or was disabled).
There are some cases when FP is known (through experimentation) to be
broken. Give priority to FP over cut-through switching, and disable FP
for known broken link modes.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/mscc/ocelot.c')
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 8dc5fb1bc61b..1f5f00b30441 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1006,7 +1006,12 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, */ if (ocelot->ops->cut_through_fwd) { mutex_lock(&ocelot->fwd_domain_lock); - ocelot->ops->cut_through_fwd(ocelot); + /* Workaround for hardware bug - FP doesn't work + * at all link speeds for all PHY modes. The function + * below also calls ocelot->ops->cut_through_fwd(), + * so we don't need to do it twice. + */ + ocelot_port_update_active_preemptible_tcs(ocelot, port); mutex_unlock(&ocelot->fwd_domain_lock); } @@ -2705,6 +2710,7 @@ static void ocelot_port_reset_mqprio(struct ocelot *ocelot, int port) struct net_device *dev = ocelot->ops->port_to_netdev(ocelot, port); netdev_reset_tc(dev); + ocelot_port_change_fp(ocelot, port, 0); } int ocelot_port_mqprio(struct ocelot *ocelot, int port, @@ -2741,6 +2747,8 @@ int ocelot_port_mqprio(struct ocelot *ocelot, int port, if (err) goto err_reset_tc; + ocelot_port_change_fp(ocelot, port, mqprio->preemptible_tcs); + return 0; err_reset_tc: |