/tools/perf/scripts/python/Perf-Trace-Util/lib/

linux/netdevice.h> #include #include #include "cpsw.h" #include "cpsw_ale.h" #include "cpsw_priv.h" #include "cpsw_switchdev.h" struct cpsw_switchdev_event_work { struct work_struct work; struct switchdev_notifier_fdb_info fdb_info; struct cpsw_priv *priv; unsigned long event; }; static int cpsw_port_stp_state_set(struct cpsw_priv *priv, u8 state) { struct cpsw_common *cpsw = priv->cpsw; u8 cpsw_state; int ret = 0; switch (state) { case BR_STATE_FORWARDING: cpsw_state = ALE_PORT_STATE_FORWARD; break; case BR_STATE_LEARNING: cpsw_state = ALE_PORT_STATE_LEARN; break; case BR_STATE_DISABLED: cpsw_state = ALE_PORT_STATE_DISABLE; break; case BR_STATE_LISTENING: case BR_STATE_BLOCKING: cpsw_state = ALE_PORT_STATE_BLOCK; break; default: return -EOPNOTSUPP; } ret = cpsw_ale_control_set(cpsw->ale, priv->emac_port, ALE_PORT_STATE, cpsw_state); dev_dbg(priv->dev, "ale state: %u\n", cpsw_state); return ret; } static int cpsw_port_attr_br_flags_set(struct cpsw_priv *priv, struct net_device *orig_dev, struct switchdev_brport_flags flags) { struct cpsw_common *cpsw = priv->cpsw; if (flags.mask & BR_MCAST_FLOOD) { bool unreg_mcast_add = false; if (flags.val & BR_MCAST_FLOOD) unreg_mcast_add = true; dev_dbg(priv->dev, "BR_MCAST_FLOOD: %d port %u\n", unreg_mcast_add, priv->emac_port); cpsw_ale_set_unreg_mcast(cpsw->ale, BIT(priv->emac_port), unreg_mcast_add); } return 0; } static int cpsw_port_attr_br_flags_pre_set(struct net_device *netdev, struct switchdev_brport_flags flags) { if (flags.mask & ~(BR_LEARNING | BR_MCAST_FLOOD)) return -EINVAL; return 0; } static int cpsw_port_attr_set(struct net_device *ndev, const void *ctx, const struct switchdev_attr *attr, struct netlink_ext_ack *extack) { struct cpsw_priv *priv = netdev_priv(ndev); int ret; dev_dbg(priv->dev, "attr: id %u port: %u\n", attr->id, priv->emac_port); switch (attr->id) { case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: ret = cpsw_port_attr_br_flags_pre_set(ndev, attr->u.brport_flags); break; case SWITCHDEV_ATTR_ID_PORT_STP_STATE: ret = cpsw_port_stp_state_set(priv, attr->u.stp_state); dev_dbg(priv->dev, "stp state: %u\n", attr->u.stp_state); break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: ret = cpsw_port_attr_br_flags_set(priv, attr->orig_dev, attr->u.brport_flags); break; default: ret = -EOPNOTSUPP; break; } return ret; } static u16 cpsw_get_pvid(struct cpsw_priv *priv) { struct cpsw_common *cpsw = priv->cpsw; u32 __iomem *port_vlan_reg; u32 pvid; if (priv->emac_port) { int reg = CPSW2_PORT_VLAN; if (cpsw->version == CPSW_VERSION_1) reg = CPSW1_PORT_VLAN; pvid = slave_read(cpsw->slaves + (priv->emac_port - 1), reg); } else { port_vlan_reg = &cpsw->host_port_regs->port_vlan; pvid = readl(port_vlan_reg); } pvid = pvid & 0xfff; return pvid; } static void cpsw_set_pvid(struct cpsw_priv *priv, u16 vid, bool cfi, u32 cos) { struct cpsw_common *cpsw = priv->cpsw; void __iomem *port_vlan_reg; u32 pvid; pvid = vid; pvid |= cfi ? BIT(12) : 0; pvid |= (cos & 0x7) << 13; if (priv->emac_port) { int reg = CPSW2_PORT_VLAN; if (cpsw->version == CPSW_VERSION_1) reg = CPSW1_PORT_VLAN; /* no barrier */ slave_write(cpsw->slaves + (priv->emac_port - 1), pvid, reg); } else { /* CPU port */ port_vlan_reg = &c