Commit 3684a23b authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'ocelot-felix-driver-support-for-preemptible-traffic-classes'

Vladimir Oltean says:

====================
Ocelot/Felix driver support for preemptible traffic classes

The series "Add tc-mqprio and tc-taprio support for preemptible traffic
classes" from:
https://lore.kernel.org/netdev/20230220122343.1156614-1-vladimir.oltean@nxp.com/

was eventually submitted in a form without the support for the
Ocelot/Felix switch driver. This patch set picks up that work again,
and presents a fairly modified form compared to the original.
====================

Link: https://lore.kernel.org/r/20230415170551.3939607-1-vladimir.oltean@nxp.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 3b53ada5 403ffc2c
...@@ -1424,6 +1424,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1424,6 +1424,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
mutex_lock(&ocelot->tas_lock); mutex_lock(&ocelot->tas_lock);
if (!taprio->enable) { if (!taprio->enable) {
ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE, ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port); QSYS_TAG_CONFIG, port);
...@@ -1436,15 +1437,19 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1436,15 +1437,19 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
return 0; return 0;
} }
ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
if (ret)
goto err_unlock;
if (taprio->cycle_time > NSEC_PER_SEC || if (taprio->cycle_time > NSEC_PER_SEC ||
taprio->cycle_time_extension >= NSEC_PER_SEC) { taprio->cycle_time_extension >= NSEC_PER_SEC) {
ret = -EINVAL; ret = -EINVAL;
goto err; goto err_reset_tc;
} }
if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX) { if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX) {
ret = -ERANGE; ret = -ERANGE;
goto err; goto err_reset_tc;
} }
/* Enable guard band. The switch will schedule frames without taking /* 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, ...@@ -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); val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8);
if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING) { if (val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING) {
ret = -EBUSY; ret = -EBUSY;
goto err; goto err_reset_tc;
} }
ocelot_rmw_rix(ocelot, ocelot_rmw_rix(ocelot,
...@@ -1503,12 +1508,19 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1503,12 +1508,19 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
!(val & QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE), !(val & QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE),
10, 100000); 10, 100000);
if (ret) if (ret)
goto err; goto err_reset_tc;
ocelot_port->taprio = taprio_offload_get(taprio); ocelot_port->taprio = taprio_offload_get(taprio);
vsc9959_tas_guard_bands_update(ocelot, port); 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); mutex_unlock(&ocelot->tas_lock);
return ret; return ret;
...@@ -1612,6 +1624,13 @@ static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port, ...@@ -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) static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)
{ {
switch (base->type) { 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: { case TC_SETUP_QDISC_TAPRIO: {
struct tc_taprio_caps *caps = base->caps; struct tc_taprio_caps *caps = base->caps;
...@@ -1635,6 +1654,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, ...@@ -1635,6 +1654,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
return vsc9959_qos_query_caps(type_data); return vsc9959_qos_query_caps(type_data);
case TC_SETUP_QDISC_TAPRIO: case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data); 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: case TC_SETUP_QDISC_CBS:
return vsc9959_qos_port_cbs_set(ds, port, type_data); return vsc9959_qos_port_cbs_set(ds, port, type_data);
default: default:
...@@ -2498,6 +2519,7 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot) ...@@ -2498,6 +2519,7 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot)
for (port = 0; port < ocelot->num_phys_ports; port++) { for (port = 0; port < ocelot->num_phys_ports; port++) {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
struct ocelot_mm_state *mm = &ocelot->mm[port];
int min_speed = ocelot_port->speed; int min_speed = ocelot_port->speed;
unsigned long mask = 0; unsigned long mask = 0;
u32 tmp, val = 0; u32 tmp, val = 0;
...@@ -2538,10 +2560,12 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot) ...@@ -2538,10 +2560,12 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot)
/* Enable cut-through forwarding for all traffic classes that /* Enable cut-through forwarding for all traffic classes that
* don't have oversized dropping enabled, since this check is * 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) { 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++) for (tc = 0; tc < OCELOT_NUM_TC; tc++)
if (vsc9959_port_qmaxsdu_get(ocelot, port, tc)) if (vsc9959_port_qmaxsdu_get(ocelot, port, tc))
...@@ -2610,12 +2634,9 @@ static const struct felix_info felix_info_vsc9959 = { ...@@ -2610,12 +2634,9 @@ static const struct felix_info felix_info_vsc9959 = {
static irqreturn_t felix_irq_handler(int irq, void *data) static irqreturn_t felix_irq_handler(int irq, void *data)
{ {
struct ocelot *ocelot = (struct ocelot *)data; struct ocelot *ocelot = (struct ocelot *)data;
int port;
ocelot_get_txtstamp(ocelot); ocelot_get_txtstamp(ocelot);
ocelot_mm_irq(ocelot);
for (port = 0; port < ocelot->num_phys_ports; port++)
ocelot_port_mm_irq(ocelot, port);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <net/pkt_sched.h>
#include <soc/mscc/ocelot_hsio.h> #include <soc/mscc/ocelot_hsio.h>
#include <soc/mscc/ocelot_vcap.h> #include <soc/mscc/ocelot_vcap.h>
#include "ocelot.h" #include "ocelot.h"
...@@ -1005,7 +1006,12 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, ...@@ -1005,7 +1006,12 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
*/ */
if (ocelot->ops->cut_through_fwd) { if (ocelot->ops->cut_through_fwd) {
mutex_lock(&ocelot->fwd_domain_lock); 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); mutex_unlock(&ocelot->fwd_domain_lock);
} }
...@@ -2699,6 +2705,58 @@ void ocelot_port_mirror_del(struct ocelot *ocelot, int from, bool ingress) ...@@ -2699,6 +2705,58 @@ void ocelot_port_mirror_del(struct ocelot *ocelot, int from, bool ingress)
} }
EXPORT_SYMBOL_GPL(ocelot_port_mirror_del); EXPORT_SYMBOL_GPL(ocelot_port_mirror_del);
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,
struct tc_mqprio_qopt_offload *mqprio)
{
struct net_device *dev = ocelot->ops->port_to_netdev(ocelot, port);
struct netlink_ext_ack *extack = mqprio->extack;
struct tc_mqprio_qopt *qopt = &mqprio->qopt;
int num_tc = qopt->num_tc;
int tc, err;
if (!num_tc) {
ocelot_port_reset_mqprio(ocelot, port);
return 0;
}
err = netdev_set_num_tc(dev, num_tc);
if (err)
return err;
for (tc = 0; tc < num_tc; tc++) {
if (qopt->count[tc] != 1) {
NL_SET_ERR_MSG_MOD(extack,
"Only one TXQ per TC supported");
return -EINVAL;
}
err = netdev_set_tc_queue(dev, tc, 1, qopt->offset[tc]);
if (err)
goto err_reset_tc;
}
err = netif_set_real_num_tx_queues(dev, num_tc);
if (err)
goto err_reset_tc;
ocelot_port_change_fp(ocelot, port, mqprio->preemptible_tcs);
return 0;
err_reset_tc:
ocelot_port_reset_mqprio(ocelot, port);
return err;
}
EXPORT_SYMBOL_GPL(ocelot_port_mqprio);
void ocelot_init_port(struct ocelot *ocelot, int port) void ocelot_init_port(struct ocelot *ocelot, int port)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
......
...@@ -119,6 +119,9 @@ int ocelot_stats_init(struct ocelot *ocelot); ...@@ -119,6 +119,9 @@ int ocelot_stats_init(struct ocelot *ocelot);
void ocelot_stats_deinit(struct ocelot *ocelot); void ocelot_stats_deinit(struct ocelot *ocelot);
int ocelot_mm_init(struct ocelot *ocelot); int ocelot_mm_init(struct ocelot *ocelot);
void ocelot_port_change_fp(struct ocelot *ocelot, int port,
unsigned long preemptible_tcs);
void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port);
extern struct notifier_block ocelot_netdevice_nb; extern struct notifier_block ocelot_netdevice_nb;
extern struct notifier_block ocelot_switchdev_nb; extern struct notifier_block ocelot_switchdev_nb;
......
...@@ -49,14 +49,68 @@ static enum ethtool_mm_verify_status ocelot_mm_verify_status(u32 val) ...@@ -49,14 +49,68 @@ static enum ethtool_mm_verify_status ocelot_mm_verify_status(u32 val)
} }
} }
void ocelot_port_mm_irq(struct ocelot *ocelot, int port) void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
struct ocelot_mm_state *mm = &ocelot->mm[port];
u32 val = 0;
lockdep_assert_held(&ocelot->fwd_domain_lock);
/* Only commit preemptible TCs when MAC Merge is active.
* On NXP LS1028A, when using QSGMII, the port hangs if transmitting
* preemptible frames at any other link speed than gigabit, so avoid
* preemption at lower speeds in this PHY mode.
*/
if ((ocelot_port->phy_mode != PHY_INTERFACE_MODE_QSGMII ||
ocelot_port->speed == SPEED_1000) && mm->tx_active)
val = mm->preemptible_tcs;
/* Cut through switching doesn't work for preemptible priorities,
* so first make sure it is disabled.
*/
mm->active_preemptible_tcs = val;
ocelot->ops->cut_through_fwd(ocelot);
dev_dbg(ocelot->dev,
"port %d %s/%s, MM TX %s, preemptible TCs 0x%x, active 0x%x\n",
port, phy_modes(ocelot_port->phy_mode),
phy_speed_to_str(ocelot_port->speed),
mm->tx_active ? "active" : "inactive", mm->preemptible_tcs,
mm->active_preemptible_tcs);
ocelot_rmw_rix(ocelot, QSYS_PREEMPTION_CFG_P_QUEUES(val),
QSYS_PREEMPTION_CFG_P_QUEUES_M,
QSYS_PREEMPTION_CFG, port);
}
void ocelot_port_change_fp(struct ocelot *ocelot, int port,
unsigned long preemptible_tcs)
{
struct ocelot_mm_state *mm = &ocelot->mm[port];
mutex_lock(&ocelot->fwd_domain_lock);
if (mm->preemptible_tcs == preemptible_tcs)
goto out_unlock;
mm->preemptible_tcs = preemptible_tcs;
ocelot_port_update_active_preemptible_tcs(ocelot, port);
out_unlock:
mutex_unlock(&ocelot->fwd_domain_lock);
}
static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
struct ocelot_mm_state *mm = &ocelot->mm[port]; struct ocelot_mm_state *mm = &ocelot->mm[port];
enum ethtool_mm_verify_status verify_status; enum ethtool_mm_verify_status verify_status;
u32 val; u32 val, ack = 0;
mutex_lock(&mm->lock); if (!mm->tx_enabled)
return;
val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS); val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS);
...@@ -73,25 +127,43 @@ void ocelot_port_mm_irq(struct ocelot *ocelot, int port) ...@@ -73,25 +127,43 @@ void ocelot_port_mm_irq(struct ocelot *ocelot, int port)
dev_dbg(ocelot->dev, "Port %d TX preemption %s\n", dev_dbg(ocelot->dev, "Port %d TX preemption %s\n",
port, mm->tx_active ? "active" : "inactive"); port, mm->tx_active ? "active" : "inactive");
ocelot_port_update_active_preemptible_tcs(ocelot, port);
ack |= DEV_MM_STAT_MM_STATUS_PRMPT_ACTIVE_STICKY;
} }
if (val & DEV_MM_STAT_MM_STATUS_UNEXP_RX_PFRM_STICKY) { if (val & DEV_MM_STAT_MM_STATUS_UNEXP_RX_PFRM_STICKY) {
dev_err(ocelot->dev, dev_err(ocelot->dev,
"Unexpected P-frame received on port %d while verification was unsuccessful or not yet verified\n", "Unexpected P-frame received on port %d while verification was unsuccessful or not yet verified\n",
port); port);
ack |= DEV_MM_STAT_MM_STATUS_UNEXP_RX_PFRM_STICKY;
} }
if (val & DEV_MM_STAT_MM_STATUS_UNEXP_TX_PFRM_STICKY) { if (val & DEV_MM_STAT_MM_STATUS_UNEXP_TX_PFRM_STICKY) {
dev_err(ocelot->dev, dev_err(ocelot->dev,
"Unexpected P-frame requested to be transmitted on port %d while verification was unsuccessful or not yet verified, or MM_TX_ENA=0\n", "Unexpected P-frame requested to be transmitted on port %d while verification was unsuccessful or not yet verified, or MM_TX_ENA=0\n",
port); port);
ack |= DEV_MM_STAT_MM_STATUS_UNEXP_TX_PFRM_STICKY;
} }
ocelot_port_writel(ocelot_port, val, DEV_MM_STATUS); if (ack)
ocelot_port_writel(ocelot_port, ack, DEV_MM_STATUS);
}
mutex_unlock(&mm->lock); void ocelot_mm_irq(struct ocelot *ocelot)
{
int port;
mutex_lock(&ocelot->fwd_domain_lock);
for (port = 0; port < ocelot->num_phys_ports; port++)
ocelot_mm_update_port_status(ocelot, port);
mutex_unlock(&ocelot->fwd_domain_lock);
} }
EXPORT_SYMBOL_GPL(ocelot_port_mm_irq); EXPORT_SYMBOL_GPL(ocelot_mm_irq);
int ocelot_port_set_mm(struct ocelot *ocelot, int port, int ocelot_port_set_mm(struct ocelot *ocelot, int port,
struct ethtool_mm_cfg *cfg, struct ethtool_mm_cfg *cfg,
...@@ -121,7 +193,7 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port, ...@@ -121,7 +193,7 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port,
if (!cfg->verify_enabled) if (!cfg->verify_enabled)
verify_disable = DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS; verify_disable = DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS;
mutex_lock(&mm->lock); mutex_lock(&ocelot->fwd_domain_lock);
ocelot_port_rmwl(ocelot_port, mm_enable, ocelot_port_rmwl(ocelot_port, mm_enable,
DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA | DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA |
...@@ -140,7 +212,20 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port, ...@@ -140,7 +212,20 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port,
QSYS_PREEMPTION_CFG, QSYS_PREEMPTION_CFG,
port); port);
mutex_unlock(&mm->lock); /* The switch will emit an IRQ when TX is disabled, to notify that it
* has become inactive. We optimize ocelot_mm_update_port_status() to
* not bother processing MM IRQs at all for ports with TX disabled,
* but we need to ACK this IRQ now, while mm->tx_enabled is still set,
* otherwise we get an IRQ storm.
*/
if (mm->tx_enabled && !cfg->tx_enabled) {
ocelot_mm_update_port_status(ocelot, port);
WARN_ON(mm->tx_active);
}
mm->tx_enabled = cfg->tx_enabled;
mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
} }
...@@ -158,7 +243,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port, ...@@ -158,7 +243,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port,
mm = &ocelot->mm[port]; mm = &ocelot->mm[port];
mutex_lock(&mm->lock); mutex_lock(&ocelot->fwd_domain_lock);
val = ocelot_port_readl(ocelot_port, DEV_MM_ENABLE_CONFIG); val = ocelot_port_readl(ocelot_port, DEV_MM_ENABLE_CONFIG);
state->pmac_enabled = !!(val & DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA); state->pmac_enabled = !!(val & DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA);
...@@ -174,10 +259,11 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port, ...@@ -174,10 +259,11 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port,
state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size); state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size);
state->rx_min_frag_size = ETH_ZLEN; state->rx_min_frag_size = ETH_ZLEN;
ocelot_mm_update_port_status(ocelot, port);
state->verify_status = mm->verify_status; state->verify_status = mm->verify_status;
state->tx_active = mm->tx_active; state->tx_active = mm->tx_active;
mutex_unlock(&mm->lock); mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
} }
...@@ -201,7 +287,6 @@ int ocelot_mm_init(struct ocelot *ocelot) ...@@ -201,7 +287,6 @@ int ocelot_mm_init(struct ocelot *ocelot)
u32 val; u32 val;
mm = &ocelot->mm[port]; mm = &ocelot->mm[port];
mutex_init(&mm->lock);
ocelot_port = ocelot->ports[port]; ocelot_port = ocelot->ports[port];
/* Update initial status variable for the /* Update initial status variable for the
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <net/dsa.h> #include <net/dsa.h>
struct tc_mqprio_qopt_offload;
/* Port Group IDs (PGID) are masks of destination ports. /* Port Group IDs (PGID) are masks of destination ports.
* *
* For L2 forwarding, the switch performs 3 lookups in the PGID table for each * For L2 forwarding, the switch performs 3 lookups in the PGID table for each
...@@ -744,9 +746,11 @@ struct ocelot_mirror { ...@@ -744,9 +746,11 @@ struct ocelot_mirror {
}; };
struct ocelot_mm_state { struct ocelot_mm_state {
struct mutex lock;
enum ethtool_mm_verify_status verify_status; enum ethtool_mm_verify_status verify_status;
bool tx_enabled;
bool tx_active; bool tx_active;
u8 preemptible_tcs;
u8 active_preemptible_tcs;
}; };
struct ocelot_port; struct ocelot_port;
...@@ -1148,12 +1152,15 @@ int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix, ...@@ -1148,12 +1152,15 @@ int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
struct ocelot_policer *pol); struct ocelot_policer *pol);
int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix); int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix);
void ocelot_port_mm_irq(struct ocelot *ocelot, int port); void ocelot_mm_irq(struct ocelot *ocelot);
int ocelot_port_set_mm(struct ocelot *ocelot, int port, int ocelot_port_set_mm(struct ocelot *ocelot, int port,
struct ethtool_mm_cfg *cfg, struct ethtool_mm_cfg *cfg,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int ocelot_port_get_mm(struct ocelot *ocelot, int port, int ocelot_port_get_mm(struct ocelot *ocelot, int port,
struct ethtool_mm_state *state); struct ethtool_mm_state *state);
int ocelot_port_mqprio(struct ocelot *ocelot, int port,
struct tc_mqprio_qopt_offload *mqprio);
void ocelot_port_update_preemptible_tcs(struct ocelot *ocelot, int port);
#if IS_ENABLED(CONFIG_BRIDGE_MRP) #if IS_ENABLED(CONFIG_BRIDGE_MRP)
int ocelot_mrp_add(struct ocelot *ocelot, int port, int ocelot_mrp_add(struct ocelot *ocelot, int port,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment