Commit fe2b8a88 authored by David S. Miller's avatar David S. Miller

Merge branch 'Accomodate-DSA-front-end-into-Ocelot'

Vladimir Oltean says:

====================
Accomodate DSA front-end into Ocelot

After the nice "change-my-mind" discussion about Ocelot, Felix and
LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
we have decided to take the route of reworking the Ocelot implementation
in a way that is DSA-compatible.

This is a large series, but hopefully is easy enough to digest, since it
contains mostly code refactoring. What needs to be changed:
- The struct net_device, phy_device needs to be isolated from Ocelot
  private structures (struct ocelot, struct ocelot_port). These will
  live as 1-to-1 equivalents to struct dsa_switch and struct dsa_port.
- The function prototypes need to be compatible with DSA (of course,
  struct dsa_switch will become struct ocelot).
- The CPU port needs to be assigned via a higher-level API, not
  hardcoded in the driver.

What is going to be interesting is that the new DSA front-end of Ocelot
will need to have features in lockstep with the DSA core itself. At the
moment, some more advanced tc offloading features of Ocelot (tc-flower,
etc) are not available in the DSA front-end due to lack of API in the
DSA core. It also means that Ocelot practically re-implements large
parts of DSA (although it is not a DSA switch per se) - see the FDB API
for example.

The code has been only compile-tested on Ocelot, since I don't have
access to any VSC7514 hardware. It was proven to work on NXP LS1028A,
which instantiates a DSA derivative of Ocelot. So I would like to ask
Alex Belloni if you could confirm this series causes no regression on
the Ocelot MIPS SoC.

The goal is to get this rework upstream as quickly as possible,
precisely because it is a large volume of code that risks gaining merge
conflicts if we keep it for too long.

This is but the first chunk of the LS1028A Felix DSA driver upstreaming.
For those who are interested, the concept can be seen on my private
Github repo, the user of this reworked Ocelot driver living under
drivers/net/dsa/vitesse/:
https://github.com/vladimiroltean/ls1028ardb-linux
====================
Acked-by: default avatarHoratiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c82488df c9d2203b
This diff is collapsed.
...@@ -427,6 +427,13 @@ struct ocelot_multicast { ...@@ -427,6 +427,13 @@ struct ocelot_multicast {
u16 ports; u16 ports;
}; };
enum ocelot_tag_prefix {
OCELOT_TAG_PREFIX_DISABLED = 0,
OCELOT_TAG_PREFIX_NONE,
OCELOT_TAG_PREFIX_SHORT,
OCELOT_TAG_PREFIX_LONG,
};
struct ocelot_port; struct ocelot_port;
struct ocelot_stat_layout { struct ocelot_stat_layout {
...@@ -455,6 +462,7 @@ struct ocelot { ...@@ -455,6 +462,7 @@ struct ocelot {
u8 num_phys_ports; u8 num_phys_ports;
u8 num_cpu_ports; u8 num_cpu_ports;
u8 cpu;
struct ocelot_port **ports; struct ocelot_port **ports;
u32 *lags; u32 *lags;
...@@ -479,11 +487,9 @@ struct ocelot { ...@@ -479,11 +487,9 @@ struct ocelot {
}; };
struct ocelot_port { struct ocelot_port {
struct net_device *dev;
struct ocelot *ocelot; struct ocelot *ocelot;
struct phy_device *phy;
void __iomem *regs; void __iomem *regs;
u8 chip_port;
/* Ingress default VLAN (pvid) */ /* Ingress default VLAN (pvid) */
u16 pvid; u16 pvid;
...@@ -491,18 +497,23 @@ struct ocelot_port { ...@@ -491,18 +497,23 @@ struct ocelot_port {
/* Egress default VLAN (vid) */ /* Egress default VLAN (vid) */
u16 vid; u16 vid;
u8 vlan_aware; u8 ptp_cmd;
struct list_head skbs;
u8 ts_id;
};
u64 *stats; struct ocelot_port_private {
struct ocelot_port port;
struct net_device *dev;
struct phy_device *phy;
u8 chip_port;
u8 vlan_aware;
phy_interface_t phy_mode; phy_interface_t phy_mode;
struct phy *serdes; struct phy *serdes;
struct ocelot_port_tc tc; struct ocelot_port_tc tc;
u8 ptp_cmd;
struct list_head skbs;
u8 ts_id;
}; };
struct ocelot_skb { struct ocelot_skb {
...@@ -549,6 +560,10 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port, ...@@ -549,6 +560,10 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
void __iomem *regs, void __iomem *regs,
struct phy_device *phy); struct phy_device *phy);
void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
enum ocelot_tag_prefix injection,
enum ocelot_tag_prefix extraction);
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;
extern struct notifier_block ocelot_switchdev_blocking_nb; extern struct notifier_block ocelot_switchdev_blocking_nb;
......
...@@ -224,9 +224,9 @@ int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule); ...@@ -224,9 +224,9 @@ int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule);
int ocelot_ace_init(struct ocelot *ocelot); int ocelot_ace_init(struct ocelot *ocelot);
void ocelot_ace_deinit(void); void ocelot_ace_deinit(void);
int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port, int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
struct flow_block_offload *f); struct flow_block_offload *f);
void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port, void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
struct flow_block_offload *f); struct flow_block_offload *f);
#endif /* _MSCC_OCELOT_ACE_H_ */ #endif /* _MSCC_OCELOT_ACE_H_ */
...@@ -95,6 +95,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) ...@@ -95,6 +95,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
do { do {
struct skb_shared_hwtstamps *shhwtstamps; struct skb_shared_hwtstamps *shhwtstamps;
struct ocelot_port_private *priv;
struct ocelot_port *ocelot_port;
u64 tod_in_ns, full_ts_in_ns; u64 tod_in_ns, full_ts_in_ns;
struct frame_info info = {}; struct frame_info info = {};
struct net_device *dev; struct net_device *dev;
...@@ -114,7 +116,10 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) ...@@ -114,7 +116,10 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
ocelot_parse_ifh(ifh, &info); ocelot_parse_ifh(ifh, &info);
dev = ocelot->ports[info.port]->dev; ocelot_port = ocelot->ports[info.port];
priv = container_of(ocelot_port, struct ocelot_port_private,
port);
dev = priv->dev;
skb = netdev_alloc_skb(dev, info.len); skb = netdev_alloc_skb(dev, info.len);
...@@ -359,10 +364,13 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -359,10 +364,13 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports, ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
sizeof(struct ocelot_port *), GFP_KERNEL); sizeof(struct ocelot_port *), GFP_KERNEL);
INIT_LIST_HEAD(&ocelot->multicast);
ocelot_init(ocelot); ocelot_init(ocelot);
ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports,
OCELOT_TAG_PREFIX_NONE, OCELOT_TAG_PREFIX_NONE);
for_each_available_child_of_node(ports, portnp) { for_each_available_child_of_node(ports, portnp) {
struct ocelot_port_private *priv;
struct ocelot_port *ocelot_port;
struct device_node *phy_node; struct device_node *phy_node;
phy_interface_t phy_mode; phy_interface_t phy_mode;
struct phy_device *phy; struct phy_device *phy;
...@@ -398,13 +406,17 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -398,13 +406,17 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
goto out_put_ports; goto out_put_ports;
} }
ocelot_port = ocelot->ports[port];
priv = container_of(ocelot_port, struct ocelot_port_private,
port);
err = of_get_phy_mode(portnp, &phy_mode); err = of_get_phy_mode(portnp, &phy_mode);
if (err && err != -ENODEV) if (err && err != -ENODEV)
goto out_put_ports; goto out_put_ports;
ocelot->ports[port]->phy_mode = phy_mode; priv->phy_mode = phy_mode;
switch (ocelot->ports[port]->phy_mode) { switch (priv->phy_mode) {
case PHY_INTERFACE_MODE_NA: case PHY_INTERFACE_MODE_NA:
continue; continue;
case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_SGMII:
...@@ -413,7 +425,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -413,7 +425,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
/* Ensure clock signals and speed is set on all /* Ensure clock signals and speed is set on all
* QSGMII links * QSGMII links
*/ */
ocelot_port_writel(ocelot->ports[port], ocelot_port_writel(ocelot_port,
DEV_CLOCK_CFG_LINK_SPEED DEV_CLOCK_CFG_LINK_SPEED
(OCELOT_SPEED_1000), (OCELOT_SPEED_1000),
DEV_CLOCK_CFG); DEV_CLOCK_CFG);
...@@ -441,7 +453,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -441,7 +453,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
goto out_put_ports; goto out_put_ports;
} }
ocelot->ports[port]->serdes = serdes; priv->serdes = serdes;
} }
register_netdevice_notifier(&ocelot_netdevice_nb); register_netdevice_notifier(&ocelot_netdevice_nb);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
struct ocelot_port_block { struct ocelot_port_block {
struct ocelot_acl_block *block; struct ocelot_acl_block *block;
struct ocelot_port *port; struct ocelot_port_private *priv;
}; };
static int ocelot_flower_parse_action(struct flow_cls_offload *f, static int ocelot_flower_parse_action(struct flow_cls_offload *f,
...@@ -177,8 +177,8 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f, ...@@ -177,8 +177,8 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
if (!rule) if (!rule)
return NULL; return NULL;
rule->port = block->port; rule->port = &block->priv->port;
rule->chip_port = block->port->chip_port; rule->chip_port = block->priv->chip_port;
return rule; return rule;
} }
...@@ -202,7 +202,7 @@ static int ocelot_flower_replace(struct flow_cls_offload *f, ...@@ -202,7 +202,7 @@ static int ocelot_flower_replace(struct flow_cls_offload *f,
if (ret) if (ret)
return ret; return ret;
port_block->port->tc.offload_cnt++; port_block->priv->tc.offload_cnt++;
return 0; return 0;
} }
...@@ -213,14 +213,14 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f, ...@@ -213,14 +213,14 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
int ret; int ret;
rule.prio = f->common.prio; rule.prio = f->common.prio;
rule.port = port_block->port; rule.port = &port_block->priv->port;
rule.id = f->cookie; rule.id = f->cookie;
ret = ocelot_ace_rule_offload_del(&rule); ret = ocelot_ace_rule_offload_del(&rule);
if (ret) if (ret)
return ret; return ret;
port_block->port->tc.offload_cnt--; port_block->priv->tc.offload_cnt--;
return 0; return 0;
} }
...@@ -231,7 +231,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f, ...@@ -231,7 +231,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
int ret; int ret;
rule.prio = f->common.prio; rule.prio = f->common.prio;
rule.port = port_block->port; rule.port = &port_block->priv->port;
rule.id = f->cookie; rule.id = f->cookie;
ret = ocelot_ace_rule_stats_update(&rule); ret = ocelot_ace_rule_stats_update(&rule);
if (ret) if (ret)
...@@ -261,7 +261,7 @@ static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type, ...@@ -261,7 +261,7 @@ static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
{ {
struct ocelot_port_block *port_block = cb_priv; struct ocelot_port_block *port_block = cb_priv;
if (!tc_cls_can_offload_and_chain0(port_block->port->dev, type_data)) if (!tc_cls_can_offload_and_chain0(port_block->priv->dev, type_data))
return -EOPNOTSUPP; return -EOPNOTSUPP;
switch (type) { switch (type) {
...@@ -275,7 +275,7 @@ static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type, ...@@ -275,7 +275,7 @@ static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
} }
static struct ocelot_port_block* static struct ocelot_port_block*
ocelot_port_block_create(struct ocelot_port *port) ocelot_port_block_create(struct ocelot_port_private *priv)
{ {
struct ocelot_port_block *port_block; struct ocelot_port_block *port_block;
...@@ -283,7 +283,7 @@ ocelot_port_block_create(struct ocelot_port *port) ...@@ -283,7 +283,7 @@ ocelot_port_block_create(struct ocelot_port *port)
if (!port_block) if (!port_block)
return NULL; return NULL;
port_block->port = port; port_block->priv = priv;
return port_block; return port_block;
} }
...@@ -300,7 +300,7 @@ static void ocelot_tc_block_unbind(void *cb_priv) ...@@ -300,7 +300,7 @@ static void ocelot_tc_block_unbind(void *cb_priv)
ocelot_port_block_destroy(port_block); ocelot_port_block_destroy(port_block);
} }
int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port, int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
struct flow_block_offload *f) struct flow_block_offload *f)
{ {
struct ocelot_port_block *port_block; struct ocelot_port_block *port_block;
...@@ -311,14 +311,14 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port, ...@@ -311,14 +311,14 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
return -EOPNOTSUPP; return -EOPNOTSUPP;
block_cb = flow_block_cb_lookup(f->block, block_cb = flow_block_cb_lookup(f->block,
ocelot_setup_tc_block_cb_flower, port); ocelot_setup_tc_block_cb_flower, priv);
if (!block_cb) { if (!block_cb) {
port_block = ocelot_port_block_create(port); port_block = ocelot_port_block_create(priv);
if (!port_block) if (!port_block)
return -ENOMEM; return -ENOMEM;
block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower, block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower,
port, port_block, priv, port_block,
ocelot_tc_block_unbind); ocelot_tc_block_unbind);
if (IS_ERR(block_cb)) { if (IS_ERR(block_cb)) {
ret = PTR_ERR(block_cb); ret = PTR_ERR(block_cb);
...@@ -339,13 +339,13 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port, ...@@ -339,13 +339,13 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
return ret; return ret;
} }
void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port, void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
struct flow_block_offload *f) struct flow_block_offload *f)
{ {
struct flow_block_cb *block_cb; struct flow_block_cb *block_cb;
block_cb = flow_block_cb_lookup(f->block, block_cb = flow_block_cb_lookup(f->block,
ocelot_setup_tc_block_cb_flower, port); ocelot_setup_tc_block_cb_flower, priv);
if (!block_cb) if (!block_cb)
return; return;
......
...@@ -40,13 +40,12 @@ struct qos_policer_conf { ...@@ -40,13 +40,12 @@ struct qos_policer_conf {
u8 ipg; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */ u8 ipg; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */
}; };
static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix, static int qos_policer_conf_set(struct ocelot *ocelot, int port, u32 pol_ix,
struct qos_policer_conf *conf) struct qos_policer_conf *conf)
{ {
u32 cf = 0, cir_ena = 0, frm_mode = POL_MODE_LINERATE; u32 cf = 0, cir_ena = 0, frm_mode = POL_MODE_LINERATE;
u32 cir = 0, cbs = 0, pir = 0, pbs = 0; u32 cir = 0, cbs = 0, pir = 0, pbs = 0;
bool cir_discard = 0, pir_discard = 0; bool cir_discard = 0, pir_discard = 0;
struct ocelot *ocelot = port->ocelot;
u32 pbs_max = 0, cbs_max = 0; u32 pbs_max = 0, cbs_max = 0;
u8 ipg = 20; u8 ipg = 20;
u32 value; u32 value;
...@@ -123,22 +122,26 @@ static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix, ...@@ -123,22 +122,26 @@ static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
/* Check limits */ /* Check limits */
if (pir > GENMASK(15, 0)) { if (pir > GENMASK(15, 0)) {
netdev_err(port->dev, "Invalid pir\n"); dev_err(ocelot->dev, "Invalid pir for port %d: %u (max %lu)\n",
port, pir, GENMASK(15, 0));
return -EINVAL; return -EINVAL;
} }
if (cir > GENMASK(15, 0)) { if (cir > GENMASK(15, 0)) {
netdev_err(port->dev, "Invalid cir\n"); dev_err(ocelot->dev, "Invalid cir for port %d: %u (max %lu)\n",
port, cir, GENMASK(15, 0));
return -EINVAL; return -EINVAL;
} }
if (pbs > pbs_max) { if (pbs > pbs_max) {
netdev_err(port->dev, "Invalid pbs\n"); dev_err(ocelot->dev, "Invalid pbs for port %d: %u (max %u)\n",
port, pbs, pbs_max);
return -EINVAL; return -EINVAL;
} }
if (cbs > cbs_max) { if (cbs > cbs_max) {
netdev_err(port->dev, "Invalid cbs\n"); dev_err(ocelot->dev, "Invalid cbs for port %d: %u (max %u)\n",
port, cbs, cbs_max);
return -EINVAL; return -EINVAL;
} }
...@@ -171,10 +174,9 @@ static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix, ...@@ -171,10 +174,9 @@ static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
return 0; return 0;
} }
int ocelot_port_policer_add(struct ocelot_port *port, int ocelot_port_policer_add(struct ocelot *ocelot, int port,
struct ocelot_policer *pol) struct ocelot_policer *pol)
{ {
struct ocelot *ocelot = port->ocelot;
struct qos_policer_conf pp = { 0 }; struct qos_policer_conf pp = { 0 };
int err; int err;
...@@ -185,11 +187,10 @@ int ocelot_port_policer_add(struct ocelot_port *port, ...@@ -185,11 +187,10 @@ int ocelot_port_policer_add(struct ocelot_port *port,
pp.pir = pol->rate; pp.pir = pol->rate;
pp.pbs = pol->burst; pp.pbs = pol->burst;
netdev_dbg(port->dev, dev_dbg(ocelot->dev, "%s: port %u pir %u kbps, pbs %u bytes\n",
"%s: port %u pir %u kbps, pbs %u bytes\n", __func__, port, pp.pir, pp.pbs);
__func__, port->chip_port, pp.pir, pp.pbs);
err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp); err = qos_policer_conf_set(ocelot, port, POL_IX_PORT + port, &pp);
if (err) if (err)
return err; return err;
...@@ -198,22 +199,21 @@ int ocelot_port_policer_add(struct ocelot_port *port, ...@@ -198,22 +199,21 @@ int ocelot_port_policer_add(struct ocelot_port *port,
ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER), ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
ANA_PORT_POL_CFG_PORT_POL_ENA | ANA_PORT_POL_CFG_PORT_POL_ENA |
ANA_PORT_POL_CFG_POL_ORDER_M, ANA_PORT_POL_CFG_POL_ORDER_M,
ANA_PORT_POL_CFG, port->chip_port); ANA_PORT_POL_CFG, port);
return 0; return 0;
} }
int ocelot_port_policer_del(struct ocelot_port *port) int ocelot_port_policer_del(struct ocelot *ocelot, int port)
{ {
struct ocelot *ocelot = port->ocelot;
struct qos_policer_conf pp = { 0 }; struct qos_policer_conf pp = { 0 };
int err; int err;
netdev_dbg(port->dev, "%s: port %u\n", __func__, port->chip_port); dev_dbg(ocelot->dev, "%s: port %u\n", __func__, port);
pp.mode = MSCC_QOS_RATE_MODE_DISABLED; pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp); err = qos_policer_conf_set(ocelot, port, POL_IX_PORT + port, &pp);
if (err) if (err)
return err; return err;
...@@ -221,7 +221,7 @@ int ocelot_port_policer_del(struct ocelot_port *port) ...@@ -221,7 +221,7 @@ int ocelot_port_policer_del(struct ocelot_port *port)
ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER), ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
ANA_PORT_POL_CFG_PORT_POL_ENA | ANA_PORT_POL_CFG_PORT_POL_ENA |
ANA_PORT_POL_CFG_POL_ORDER_M, ANA_PORT_POL_CFG_POL_ORDER_M,
ANA_PORT_POL_CFG, port->chip_port); ANA_PORT_POL_CFG, port);
return 0; return 0;
} }
...@@ -14,9 +14,9 @@ struct ocelot_policer { ...@@ -14,9 +14,9 @@ struct ocelot_policer {
u32 burst; /* bytes */ u32 burst; /* bytes */
}; };
int ocelot_port_policer_add(struct ocelot_port *port, int ocelot_port_policer_add(struct ocelot *ocelot, int port,
struct ocelot_policer *pol); struct ocelot_policer *pol);
int ocelot_port_policer_del(struct ocelot_port *port); int ocelot_port_policer_del(struct ocelot *ocelot, int port);
#endif /* _MSCC_OCELOT_POLICE_H_ */ #endif /* _MSCC_OCELOT_POLICE_H_ */
...@@ -9,17 +9,19 @@ ...@@ -9,17 +9,19 @@
#include "ocelot_ace.h" #include "ocelot_ace.h"
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port, static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv,
struct tc_cls_matchall_offload *f, struct tc_cls_matchall_offload *f,
bool ingress) bool ingress)
{ {
struct netlink_ext_ack *extack = f->common.extack; struct netlink_ext_ack *extack = f->common.extack;
struct ocelot *ocelot = priv->port.ocelot;
struct ocelot_policer pol = { 0 }; struct ocelot_policer pol = { 0 };
struct flow_action_entry *action; struct flow_action_entry *action;
int port = priv->chip_port;
int err; int err;
netdev_dbg(port->dev, "%s: port %u command %d cookie %lu\n", netdev_dbg(priv->dev, "%s: port %u command %d cookie %lu\n",
__func__, port->chip_port, f->command, f->cookie); __func__, port, f->command, f->cookie);
if (!ingress) { if (!ingress) {
NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported"); NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported");
...@@ -34,7 +36,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port, ...@@ -34,7 +36,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (port->tc.block_shared) { if (priv->tc.block_shared) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"Rate limit is not supported on shared blocks"); "Rate limit is not supported on shared blocks");
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -47,7 +49,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port, ...@@ -47,7 +49,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (port->tc.police_id && port->tc.police_id != f->cookie) { if (priv->tc.police_id && priv->tc.police_id != f->cookie) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"Only one policer per port is supported\n"); "Only one policer per port is supported\n");
return -EEXIST; return -EEXIST;
...@@ -58,27 +60,27 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port, ...@@ -58,27 +60,27 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
PSCHED_NS2TICKS(action->police.burst), PSCHED_NS2TICKS(action->police.burst),
PSCHED_TICKS_PER_SEC); PSCHED_TICKS_PER_SEC);
err = ocelot_port_policer_add(port, &pol); err = ocelot_port_policer_add(ocelot, port, &pol);
if (err) { if (err) {
NL_SET_ERR_MSG_MOD(extack, "Could not add policer\n"); NL_SET_ERR_MSG_MOD(extack, "Could not add policer\n");
return err; return err;
} }
port->tc.police_id = f->cookie; priv->tc.police_id = f->cookie;
port->tc.offload_cnt++; priv->tc.offload_cnt++;
return 0; return 0;
case TC_CLSMATCHALL_DESTROY: case TC_CLSMATCHALL_DESTROY:
if (port->tc.police_id != f->cookie) if (priv->tc.police_id != f->cookie)
return -ENOENT; return -ENOENT;
err = ocelot_port_policer_del(port); err = ocelot_port_policer_del(ocelot, port);
if (err) { if (err) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"Could not delete policer\n"); "Could not delete policer\n");
return err; return err;
} }
port->tc.police_id = 0; priv->tc.police_id = 0;
port->tc.offload_cnt--; priv->tc.offload_cnt--;
return 0; return 0;
case TC_CLSMATCHALL_STATS: /* fall through */ case TC_CLSMATCHALL_STATS: /* fall through */
default: default:
...@@ -90,21 +92,21 @@ static int ocelot_setup_tc_block_cb(enum tc_setup_type type, ...@@ -90,21 +92,21 @@ static int ocelot_setup_tc_block_cb(enum tc_setup_type type,
void *type_data, void *type_data,
void *cb_priv, bool ingress) void *cb_priv, bool ingress)
{ {
struct ocelot_port *port = cb_priv; struct ocelot_port_private *priv = cb_priv;
if (!tc_cls_can_offload_and_chain0(port->dev, type_data)) if (!tc_cls_can_offload_and_chain0(priv->dev, type_data))
return -EOPNOTSUPP; return -EOPNOTSUPP;
switch (type) { switch (type) {
case TC_SETUP_CLSMATCHALL: case TC_SETUP_CLSMATCHALL:
netdev_dbg(port->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n", netdev_dbg(priv->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n",
ingress ? "ingress" : "egress"); ingress ? "ingress" : "egress");
return ocelot_setup_tc_cls_matchall(port, type_data, ingress); return ocelot_setup_tc_cls_matchall(priv, type_data, ingress);
case TC_SETUP_CLSFLOWER: case TC_SETUP_CLSFLOWER:
return 0; return 0;
default: default:
netdev_dbg(port->dev, "tc_block_cb: type %d %s\n", netdev_dbg(priv->dev, "tc_block_cb: type %d %s\n",
type, type,
ingress ? "ingress" : "egress"); ingress ? "ingress" : "egress");
...@@ -130,19 +132,19 @@ static int ocelot_setup_tc_block_cb_eg(enum tc_setup_type type, ...@@ -130,19 +132,19 @@ static int ocelot_setup_tc_block_cb_eg(enum tc_setup_type type,
static LIST_HEAD(ocelot_block_cb_list); static LIST_HEAD(ocelot_block_cb_list);
static int ocelot_setup_tc_block(struct ocelot_port *port, static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
struct flow_block_offload *f) struct flow_block_offload *f)
{ {
struct flow_block_cb *block_cb; struct flow_block_cb *block_cb;
flow_setup_cb_t *cb; flow_setup_cb_t *cb;
int err; int err;
netdev_dbg(port->dev, "tc_block command %d, binder_type %d\n", netdev_dbg(priv->dev, "tc_block command %d, binder_type %d\n",
f->command, f->binder_type); f->command, f->binder_type);
if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) { if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
cb = ocelot_setup_tc_block_cb_ig; cb = ocelot_setup_tc_block_cb_ig;
port->tc.block_shared = f->block_shared; priv->tc.block_shared = f->block_shared;
} else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) { } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
cb = ocelot_setup_tc_block_cb_eg; cb = ocelot_setup_tc_block_cb_eg;
} else { } else {
...@@ -153,14 +155,14 @@ static int ocelot_setup_tc_block(struct ocelot_port *port, ...@@ -153,14 +155,14 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
switch (f->command) { switch (f->command) {
case FLOW_BLOCK_BIND: case FLOW_BLOCK_BIND:
if (flow_block_cb_is_busy(cb, port, &ocelot_block_cb_list)) if (flow_block_cb_is_busy(cb, priv, &ocelot_block_cb_list))
return -EBUSY; return -EBUSY;
block_cb = flow_block_cb_alloc(cb, port, port, NULL); block_cb = flow_block_cb_alloc(cb, priv, priv, NULL);
if (IS_ERR(block_cb)) if (IS_ERR(block_cb))
return PTR_ERR(block_cb); return PTR_ERR(block_cb);
err = ocelot_setup_tc_block_flower_bind(port, f); err = ocelot_setup_tc_block_flower_bind(priv, f);
if (err < 0) { if (err < 0) {
flow_block_cb_free(block_cb); flow_block_cb_free(block_cb);
return err; return err;
...@@ -169,11 +171,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port, ...@@ -169,11 +171,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
list_add_tail(&block_cb->driver_list, f->driver_block_list); list_add_tail(&block_cb->driver_list, f->driver_block_list);
return 0; return 0;
case FLOW_BLOCK_UNBIND: case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f->block, cb, port); block_cb = flow_block_cb_lookup(f->block, cb, priv);
if (!block_cb) if (!block_cb)
return -ENOENT; return -ENOENT;
ocelot_setup_tc_block_flower_unbind(port, f); ocelot_setup_tc_block_flower_unbind(priv, f);
flow_block_cb_remove(block_cb, f); flow_block_cb_remove(block_cb, f);
list_del(&block_cb->driver_list); list_del(&block_cb->driver_list);
return 0; return 0;
...@@ -185,11 +187,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port, ...@@ -185,11 +187,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
int ocelot_setup_tc(struct net_device *dev, enum tc_setup_type type, int ocelot_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data) void *type_data)
{ {
struct ocelot_port *port = netdev_priv(dev); struct ocelot_port_private *priv = netdev_priv(dev);
switch (type) { switch (type) {
case TC_SETUP_BLOCK: case TC_SETUP_BLOCK:
return ocelot_setup_tc_block(port, type_data); return ocelot_setup_tc_block(priv, type_data);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
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