Re: [RFC v7 net-next 13/13] net: dsa: ocelot: add external ocelot switch control

Vladimir Oltean
2022-03-08T14:14:48Z

On Sun, Mar 06, 2022 at 06:12:08PM -0800, Colin Foster wrote:
> +static const struct reg_field vsc7512_regfields[REGFIELD_MAX] = {
> + [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11),
> + [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10),
> + [ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27),
> + [ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26),
> + [ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25),
> + [ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24),
> + [ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23),
> + [ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22),
> + [ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21),
> + [ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20),
> + [ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19),
> + [ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18),
> + [ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17),
> + [ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16),
> + [ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15),
> + [ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14),
> + [ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13),
> + [ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12),
> + [ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11),
> + [ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10),
> + [ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9),
> + [ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8),
> + [ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7),
> + [ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),
> + [ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),
> + [ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4),
> + [ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3),
> + [ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2),
> + [ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1),
> + [ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0),
> + [ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18),
> + [ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11),
> + [ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9),
> + [GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 1, 1),

If you add GCB_SOFT_RST_SWC_RST to ocelot_regfields, can't you just use that?

> + [QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20),
> + [QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19),
> + [QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7),
> + [QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3),
> + [QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0),
> + [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2),
> + [SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1),
> + [SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0),
> + /* Replicated per number of ports (12), register size 4 per port */
> + [QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4),
> + [QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4),
> + [QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4),
> + [QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4),
> + [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4),
> + [QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4),
> + [SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4),
> + [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4),
> + [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4),
> + [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4),
> + [SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4),
> + [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4),
> + [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4),
> +};
> +
> +static const struct ocelot_stat_layout vsc7512_stats_layout[] = {

Why not use ocelot_stats_layout?

> + { .offset = 0x00, .name = "rx_octets", },
> + { .offset = 0x01, .name = "rx_unicast", },
> + { .offset = 0x02, .name = "rx_multicast", },
> + { .offset = 0x03, .name = "rx_broadcast", },
> + { .offset = 0x04, .name = "rx_shorts", },
> + { .offset = 0x05, .name = "rx_fragments", },
> + { .offset = 0x06, .name = "rx_jabbers", },
> + { .offset = 0x07, .name = "rx_crc_align_errs", },
> + { .offset = 0x08, .name = "rx_sym_errs", },
> + { .offset = 0x09, .name = "rx_frames_below_65_octets", },
> + { .offset = 0x0A, .name = "rx_frames_65_to_127_octets", },
> + { .offset = 0x0B, .name = "rx_frames_128_to_255_octets", },
> + { .offset = 0x0C, .name = "rx_frames_256_to_511_octets", },
> + { .offset = 0x0D, .name = "rx_frames_512_to_1023_octets", },
> + { .offset = 0x0E, .name = "rx_frames_1024_to_1526_octets", },
> + { .offset = 0x0F, .name = "rx_frames_over_1526_octets", },
> + { .offset = 0x10, .name = "rx_pause", },
> + { .offset = 0x11, .name = "rx_control", },
> + { .offset = 0x12, .name = "rx_longs", },
> + { .offset = 0x13, .name = "rx_classified_drops", },
> + { .offset = 0x14, .name = "rx_red_prio_0", },
> + { .offset = 0x15, .name = "rx_red_prio_1", },
> + { .offset = 0x16, .name = "rx_red_prio_2", },
> + { .offset = 0x17, .name = "rx_red_prio_3", },
> + { .offset = 0x18, .name = "rx_red_prio_4", },
> + { .offset = 0x19, .name = "rx_red_prio_5", },
> + { .offset = 0x1A, .name = "rx_red_prio_6", },
> + { .offset = 0x1B, .name = "rx_red_prio_7", },
> + { .offset = 0x1C, .name = "rx_yellow_prio_0", },
> + { .offset = 0x1D, .name = "rx_yellow_prio_1", },
> + { .offset = 0x1E, .name = "rx_yellow_prio_2", },
> + { .offset = 0x1F, .name = "rx_yellow_prio_3", },
> + { .offset = 0x20, .name = "rx_yellow_prio_4", },
> + { .offset = 0x21, .name = "rx_yellow_prio_5", },
> + { .offset = 0x22, .name = "rx_yellow_prio_6", },
> + { .offset = 0x23, .name = "rx_yellow_prio_7", },
> + { .offset = 0x24, .name = "rx_green_prio_0", },
> + { .offset = 0x25, .name = "rx_green_prio_1", },
> + { .offset = 0x26, .name = "rx_green_prio_2", },
> + { .offset = 0x27, .name = "rx_green_prio_3", },
> + { .offset = 0x28, .name = "rx_green_prio_4", },
> + { .offset = 0x29, .name = "rx_green_prio_5", },
> + { .offset = 0x2A, .name = "rx_green_prio_6", },
> + { .offset = 0x2B, .name = "rx_green_prio_7", },
> + { .offset = 0x40, .name = "tx_octets", },
> + { .offset = 0x41, .name = "tx_unicast", },
> + { .offset = 0x42, .name = "tx_multicast", },
> + { .offset = 0x43, .name = "tx_broadcast", },
> + { .offset = 0x44, .name = "tx_collision", },
> + { .offset = 0x45, .name = "tx_drops", },
> + { .offset = 0x46, .name = "tx_pause", },
> + { .offset = 0x47, .name = "tx_frames_below_65_octets", },
> + { .offset = 0x48, .name = "tx_frames_65_to_127_octets", },
> + { .offset = 0x49, .name = "tx_frames_128_255_octets", },
> + { .offset = 0x4A, .name = "tx_frames_256_511_octets", },
> + { .offset = 0x4B, .name = "tx_frames_512_1023_octets", },
> + { .offset = 0x4C, .name = "tx_frames_1024_1526_octets", },
> + { .offset = 0x4D, .name = "tx_frames_over_1526_octets", },
> + { .offset = 0x4E, .name = "tx_yellow_prio_0", },
> + { .offset = 0x4F, .name = "tx_yellow_prio_1", },
> + { .offset = 0x50, .name = "tx_yellow_prio_2", },
> + { .offset = 0x51, .name = "tx_yellow_prio_3", },
> + { .offset = 0x52, .name = "tx_yellow_prio_4", },
> + { .offset = 0x53, .name = "tx_yellow_prio_5", },
> + { .offset = 0x54, .name = "tx_yellow_prio_6", },
> + { .offset = 0x55, .name = "tx_yellow_prio_7", },
> + { .offset = 0x56, .name = "tx_green_prio_0", },
> + { .offset = 0x57, .name = "tx_green_prio_1", },
> + { .offset = 0x58, .name = "tx_green_prio_2", },
> + { .offset = 0x59, .name = "tx_green_prio_3", },
> + { .offset = 0x5A, .name = "tx_green_prio_4", },
> + { .offset = 0x5B, .name = "tx_green_prio_5", },
> + { .offset = 0x5C, .name = "tx_green_prio_6", },
> + { .offset = 0x5D, .name = "tx_green_prio_7", },
> + { .offset = 0x5E, .name = "tx_aged", },
> + { .offset = 0x80, .name = "drop_local", },
> + { .offset = 0x81, .name = "drop_tail", },
> + { .offset = 0x82, .name = "drop_yellow_prio_0", },
> + { .offset = 0x83, .name = "drop_yellow_prio_1", },
> + { .offset = 0x84, .name = "drop_yellow_prio_2", },
> + { .offset = 0x85, .name = "drop_yellow_prio_3", },
> + { .offset = 0x86, .name = "drop_yellow_prio_4", },
> + { .offset = 0x87, .name = "drop_yellow_prio_5", },
> + { .offset = 0x88, .name = "drop_yellow_prio_6", },
> + { .offset = 0x89, .name = "drop_yellow_prio_7", },
> + { .offset = 0x8A, .name = "drop_green_prio_0", },
> + { .offset = 0x8B, .name = "drop_green_prio_1", },
> + { .offset = 0x8C, .name = "drop_green_prio_2", },
> + { .offset = 0x8D, .name = "drop_green_prio_3", },
> + { .offset = 0x8E, .name = "drop_green_prio_4", },
> + { .offset = 0x8F, .name = "drop_green_prio_5", },
> + { .offset = 0x90, .name = "drop_green_prio_6", },
> + { .offset = 0x91, .name = "drop_green_prio_7", },
> +};
> +
> +static void ocelot_ext_phylink_validate(struct ocelot *ocelot, int port,
> + unsigned long *supported,
> + struct phylink_link_state *state)
> +{
> + struct ocelot_port *ocelot_port = ocelot->ports[port];
> +
> + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
> +
> + if (state->interface != PHY_INTERFACE_MODE_NA &&
> + state->interface != ocelot_port->phy_mode) {
> + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
> + return;
> + }

You might want to check
git log -4 --author="Russell King" drivers/net/dsa/ocelot/
especially commit e57a15401e82 ("net: dsa: ocelot: remove interface checks").
And you can/should in fact use phylink_generic_validate, since there
aren't any special constraints that I know of.

> +
> + phylink_set_port_modes(mask);
> +
> + phylink_set(mask, Pause);
> + phylink_set(mask, Autoneg);
> + phylink_set(mask, Asym_Pause);
> + phylink_set(mask, 10baseT_Half);
> + phylink_set(mask, 10baseT_Full);
> + phylink_set(mask, 100baseT_Half);
> + phylink_set(mask, 100baseT_Full);
> + phylink_set(mask, 1000baseT_Half);
> + phylink_set(mask, 1000baseT_Full);
> +
> + bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
> + bitmap_and(state->advertising, state->advertising, mask,
> + __ETHTOOL_LINK_MODE_MASK_NBITS);
> +}
> +
> +static struct vcap_props vsc7512_vcap_props[] = {

Why not vsc7514_vcap_props?

> + [VCAP_ES0] = {
> + .action_type_width = 0,
> + .action_table = {
> + [ES0_ACTION_TYPE_NORMAL] = {
> + .width = 73,
> + .count = 1,
> + },
> + },
> + .target = S0,
> + .keys = vsc7514_vcap_es0_keys,
> + .actions = vsc7514_vcap_es0_actions,
> + },
> + [VCAP_IS1] = {
> + .action_type_width = 0,
> + .action_table = {
> + [IS1_ACTION_TYPE_NORMAL] = {
> + .width = 78,
> + .count = 4,
> + },
> + },
> + .target = S1,
> + .keys = vsc7514_vcap_is1_keys,
> + .actions = vsc7514_vcap_is1_actions,
> + },
> + [VCAP_IS2] = {
> + .action_type_width = 1,
> + .action_table = {
> + [IS2_ACTION_TYPE_NORMAL] = {
> + .width = 49,
> + .count = 2,
> + },
> + [IS2_ACTION_TYPE_SMAC_SIP] = {
> + .width = 6,
> + .count = 4,
> + },
> + },
> + .target = S2,
> + .keys = vsc7514_vcap_is2_keys,
> + .actions = vsc7514_vcap_is2_actions,
> + },
> +};