summaryrefslogtreecommitdiff
path: root/drivers/net/dsa/ocelot/felix_vsc9959.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dsa/ocelot/felix_vsc9959.c')
-rw-r--r--drivers/net/dsa/ocelot/felix_vsc9959.c684
1 files changed, 169 insertions, 515 deletions
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index f8f19a85744c..26a35ae322d1 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -348,7 +348,7 @@ static const u32 vsc9959_sys_regmap[] = {
REG(SYS_COUNT_TX_GREEN_PRIO_5, 0x00026c),
REG(SYS_COUNT_TX_GREEN_PRIO_6, 0x000270),
REG(SYS_COUNT_TX_GREEN_PRIO_7, 0x000274),
- REG(SYS_COUNT_TX_AGING, 0x000278),
+ REG(SYS_COUNT_TX_AGED, 0x000278),
REG(SYS_COUNT_DROP_LOCAL, 0x000400),
REG(SYS_COUNT_DROP_TAIL, 0x000404),
REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000408),
@@ -367,6 +367,10 @@ static const u32 vsc9959_sys_regmap[] = {
REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00043c),
REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000440),
REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000444),
+ REG(SYS_COUNT_SF_MATCHING_FRAMES, 0x000800),
+ REG(SYS_COUNT_SF_NOT_PASSING_FRAMES, 0x000804),
+ REG(SYS_COUNT_SF_NOT_PASSING_SDU, 0x000808),
+ REG(SYS_COUNT_SF_RED_FRAMES, 0x00080c),
REG(SYS_RESET_CFG, 0x000e00),
REG(SYS_SR_ETYPE_CFG, 0x000e04),
REG(SYS_VLAN_ETYPE_CFG, 0x000e08),
@@ -388,7 +392,6 @@ static const u32 vsc9959_sys_regmap[] = {
REG_RESERVED(SYS_MMGT_FAST),
REG_RESERVED(SYS_EVENTS_DIF),
REG_RESERVED(SYS_EVENTS_CORE),
- REG(SYS_CNT, 0x000000),
REG(SYS_PTP_STATUS, 0x000f14),
REG(SYS_PTP_TXSTAMP, 0x000f18),
REG(SYS_PTP_NXT, 0x000f1c),
@@ -474,100 +477,43 @@ static const u32 *vsc9959_regmap[TARGET_MAX] = {
};
/* Addresses are relative to the PCI device's base address */
-static const struct resource vsc9959_target_io_res[TARGET_MAX] = {
- [ANA] = {
- .start = 0x0280000,
- .end = 0x028ffff,
- .name = "ana",
- },
- [QS] = {
- .start = 0x0080000,
- .end = 0x00800ff,
- .name = "qs",
- },
- [QSYS] = {
- .start = 0x0200000,
- .end = 0x021ffff,
- .name = "qsys",
- },
- [REW] = {
- .start = 0x0030000,
- .end = 0x003ffff,
- .name = "rew",
- },
- [SYS] = {
- .start = 0x0010000,
- .end = 0x001ffff,
- .name = "sys",
- },
- [S0] = {
- .start = 0x0040000,
- .end = 0x00403ff,
- .name = "s0",
- },
- [S1] = {
- .start = 0x0050000,
- .end = 0x00503ff,
- .name = "s1",
- },
- [S2] = {
- .start = 0x0060000,
- .end = 0x00603ff,
- .name = "s2",
- },
- [PTP] = {
- .start = 0x0090000,
- .end = 0x00900cb,
- .name = "ptp",
- },
- [GCB] = {
- .start = 0x0070000,
- .end = 0x00701ff,
- .name = "devcpu_gcb",
- },
+static const struct resource vsc9959_resources[] = {
+ DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys"),
+ DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew"),
+ DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0"),
+ DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1"),
+ DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2"),
+ DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb"),
+ DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs"),
+ DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp"),
+ DEFINE_RES_MEM_NAMED(0x0100000, 0x0010000, "port0"),
+ DEFINE_RES_MEM_NAMED(0x0110000, 0x0010000, "port1"),
+ DEFINE_RES_MEM_NAMED(0x0120000, 0x0010000, "port2"),
+ DEFINE_RES_MEM_NAMED(0x0130000, 0x0010000, "port3"),
+ DEFINE_RES_MEM_NAMED(0x0140000, 0x0010000, "port4"),
+ DEFINE_RES_MEM_NAMED(0x0150000, 0x0010000, "port5"),
+ DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys"),
+ DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana"),
};
-static const struct resource vsc9959_port_io_res[] = {
- {
- .start = 0x0100000,
- .end = 0x010ffff,
- .name = "port0",
- },
- {
- .start = 0x0110000,
- .end = 0x011ffff,
- .name = "port1",
- },
- {
- .start = 0x0120000,
- .end = 0x012ffff,
- .name = "port2",
- },
- {
- .start = 0x0130000,
- .end = 0x013ffff,
- .name = "port3",
- },
- {
- .start = 0x0140000,
- .end = 0x014ffff,
- .name = "port4",
- },
- {
- .start = 0x0150000,
- .end = 0x015ffff,
- .name = "port5",
- },
+static const char * const vsc9959_resource_names[TARGET_MAX] = {
+ [SYS] = "sys",
+ [REW] = "rew",
+ [S0] = "s0",
+ [S1] = "s1",
+ [S2] = "s2",
+ [GCB] = "devcpu_gcb",
+ [QS] = "qs",
+ [PTP] = "ptp",
+ [QSYS] = "qsys",
+ [ANA] = "ana",
};
/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
* SGMII/QSGMII MAC PCS can be found.
*/
-static const struct resource vsc9959_imdio_res = {
- .start = 0x8030,
- .end = 0x8040,
- .name = "imdio",
-};
+static const struct resource vsc9959_imdio_res =
+ DEFINE_RES_MEM_NAMED(0x8030, 0x8040, "imdio");
static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = {
[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),
@@ -620,378 +566,7 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = {
};
static const struct ocelot_stat_layout vsc9959_stats_layout[OCELOT_NUM_STATS] = {
- [OCELOT_STAT_RX_OCTETS] = {
- .name = "rx_octets",
- .reg = SYS_COUNT_RX_OCTETS,
- },
- [OCELOT_STAT_RX_UNICAST] = {
- .name = "rx_unicast",
- .reg = SYS_COUNT_RX_UNICAST,
- },
- [OCELOT_STAT_RX_MULTICAST] = {
- .name = "rx_multicast",
- .reg = SYS_COUNT_RX_MULTICAST,
- },
- [OCELOT_STAT_RX_BROADCAST] = {
- .name = "rx_broadcast",
- .reg = SYS_COUNT_RX_BROADCAST,
- },
- [OCELOT_STAT_RX_SHORTS] = {
- .name = "rx_shorts",
- .reg = SYS_COUNT_RX_SHORTS,
- },
- [OCELOT_STAT_RX_FRAGMENTS] = {
- .name = "rx_fragments",
- .reg = SYS_COUNT_RX_FRAGMENTS,
- },
- [OCELOT_STAT_RX_JABBERS] = {
- .name = "rx_jabbers",
- .reg = SYS_COUNT_RX_JABBERS,
- },
- [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = {
- .name = "rx_crc_align_errs",
- .reg = SYS_COUNT_RX_CRC_ALIGN_ERRS,
- },
- [OCELOT_STAT_RX_SYM_ERRS] = {
- .name = "rx_sym_errs",
- .reg = SYS_COUNT_RX_SYM_ERRS,
- },
- [OCELOT_STAT_RX_64] = {
- .name = "rx_frames_below_65_octets",
- .reg = SYS_COUNT_RX_64,
- },
- [OCELOT_STAT_RX_65_127] = {
- .name = "rx_frames_65_to_127_octets",
- .reg = SYS_COUNT_RX_65_127,
- },
- [OCELOT_STAT_RX_128_255] = {
- .name = "rx_frames_128_to_255_octets",
- .reg = SYS_COUNT_RX_128_255,
- },
- [OCELOT_STAT_RX_256_511] = {
- .name = "rx_frames_256_to_511_octets",
- .reg = SYS_COUNT_RX_256_511,
- },
- [OCELOT_STAT_RX_512_1023] = {
- .name = "rx_frames_512_to_1023_octets",
- .reg = SYS_COUNT_RX_512_1023,
- },
- [OCELOT_STAT_RX_1024_1526] = {
- .name = "rx_frames_1024_to_1526_octets",
- .reg = SYS_COUNT_RX_1024_1526,
- },
- [OCELOT_STAT_RX_1527_MAX] = {
- .name = "rx_frames_over_1526_octets",
- .reg = SYS_COUNT_RX_1527_MAX,
- },
- [OCELOT_STAT_RX_PAUSE] = {
- .name = "rx_pause",
- .reg = SYS_COUNT_RX_PAUSE,
- },
- [OCELOT_STAT_RX_CONTROL] = {
- .name = "rx_control",
- .reg = SYS_COUNT_RX_CONTROL,
- },
- [OCELOT_STAT_RX_LONGS] = {
- .name = "rx_longs",
- .reg = SYS_COUNT_RX_LONGS,
- },
- [OCELOT_STAT_RX_CLASSIFIED_DROPS] = {
- .name = "rx_classified_drops",
- .reg = SYS_COUNT_RX_CLASSIFIED_DROPS,
- },
- [OCELOT_STAT_RX_RED_PRIO_0] = {
- .name = "rx_red_prio_0",
- .reg = SYS_COUNT_RX_RED_PRIO_0,
- },
- [OCELOT_STAT_RX_RED_PRIO_1] = {
- .name = "rx_red_prio_1",
- .reg = SYS_COUNT_RX_RED_PRIO_1,
- },
- [OCELOT_STAT_RX_RED_PRIO_2] = {
- .name = "rx_red_prio_2",
- .reg = SYS_COUNT_RX_RED_PRIO_2,
- },
- [OCELOT_STAT_RX_RED_PRIO_3] = {
- .name = "rx_red_prio_3",
- .reg = SYS_COUNT_RX_RED_PRIO_3,
- },
- [OCELOT_STAT_RX_RED_PRIO_4] = {
- .name = "rx_red_prio_4",
- .reg = SYS_COUNT_RX_RED_PRIO_4,
- },
- [OCELOT_STAT_RX_RED_PRIO_5] = {
- .name = "rx_red_prio_5",
- .reg = SYS_COUNT_RX_RED_PRIO_5,
- },
- [OCELOT_STAT_RX_RED_PRIO_6] = {
- .name = "rx_red_prio_6",
- .reg = SYS_COUNT_RX_RED_PRIO_6,
- },
- [OCELOT_STAT_RX_RED_PRIO_7] = {
- .name = "rx_red_prio_7",
- .reg = SYS_COUNT_RX_RED_PRIO_7,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_0] = {
- .name = "rx_yellow_prio_0",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_0,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_1] = {
- .name = "rx_yellow_prio_1",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_1,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_2] = {
- .name = "rx_yellow_prio_2",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_2,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_3] = {
- .name = "rx_yellow_prio_3",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_3,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_4] = {
- .name = "rx_yellow_prio_4",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_4,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_5] = {
- .name = "rx_yellow_prio_5",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_5,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_6] = {
- .name = "rx_yellow_prio_6",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_6,
- },
- [OCELOT_STAT_RX_YELLOW_PRIO_7] = {
- .name = "rx_yellow_prio_7",
- .reg = SYS_COUNT_RX_YELLOW_PRIO_7,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_0] = {
- .name = "rx_green_prio_0",
- .reg = SYS_COUNT_RX_GREEN_PRIO_0,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_1] = {
- .name = "rx_green_prio_1",
- .reg = SYS_COUNT_RX_GREEN_PRIO_1,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_2] = {
- .name = "rx_green_prio_2",
- .reg = SYS_COUNT_RX_GREEN_PRIO_2,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_3] = {
- .name = "rx_green_prio_3",
- .reg = SYS_COUNT_RX_GREEN_PRIO_3,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_4] = {
- .name = "rx_green_prio_4",
- .reg = SYS_COUNT_RX_GREEN_PRIO_4,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_5] = {
- .name = "rx_green_prio_5",
- .reg = SYS_COUNT_RX_GREEN_PRIO_5,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_6] = {
- .name = "rx_green_prio_6",
- .reg = SYS_COUNT_RX_GREEN_PRIO_6,
- },
- [OCELOT_STAT_RX_GREEN_PRIO_7] = {
- .name = "rx_green_prio_7",
- .reg = SYS_COUNT_RX_GREEN_PRIO_7,
- },
- [OCELOT_STAT_TX_OCTETS] = {
- .name = "tx_octets",
- .reg = SYS_COUNT_TX_OCTETS,
- },
- [OCELOT_STAT_TX_UNICAST] = {
- .name = "tx_unicast",
- .reg = SYS_COUNT_TX_UNICAST,
- },
- [OCELOT_STAT_TX_MULTICAST] = {
- .name = "tx_multicast",
- .reg = SYS_COUNT_TX_MULTICAST,
- },
- [OCELOT_STAT_TX_BROADCAST] = {
- .name = "tx_broadcast",
- .reg = SYS_COUNT_TX_BROADCAST,
- },
- [OCELOT_STAT_TX_COLLISION] = {
- .name = "tx_collision",
- .reg = SYS_COUNT_TX_COLLISION,
- },
- [OCELOT_STAT_TX_DROPS] = {
- .name = "tx_drops",
- .reg = SYS_COUNT_TX_DROPS,
- },
- [OCELOT_STAT_TX_PAUSE] = {
- .name = "tx_pause",
- .reg = SYS_COUNT_TX_PAUSE,
- },
- [OCELOT_STAT_TX_64] = {
- .name = "tx_frames_below_65_octets",
- .reg = SYS_COUNT_TX_64,
- },
- [OCELOT_STAT_TX_65_127] = {
- .name = "tx_frames_65_to_127_octets",
- .reg = SYS_COUNT_TX_65_127,
- },
- [OCELOT_STAT_TX_128_255] = {
- .name = "tx_frames_128_255_octets",
- .reg = SYS_COUNT_TX_128_255,
- },
- [OCELOT_STAT_TX_256_511] = {
- .name = "tx_frames_256_511_octets",
- .reg = SYS_COUNT_TX_256_511,
- },
- [OCELOT_STAT_TX_512_1023] = {
- .name = "tx_frames_512_1023_octets",
- .reg = SYS_COUNT_TX_512_1023,
- },
- [OCELOT_STAT_TX_1024_1526] = {
- .name = "tx_frames_1024_1526_octets",
- .reg = SYS_COUNT_TX_1024_1526,
- },
- [OCELOT_STAT_TX_1527_MAX] = {
- .name = "tx_frames_over_1526_octets",
- .reg = SYS_COUNT_TX_1527_MAX,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_0] = {
- .name = "tx_yellow_prio_0",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_0,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_1] = {
- .name = "tx_yellow_prio_1",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_1,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_2] = {
- .name = "tx_yellow_prio_2",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_2,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_3] = {
- .name = "tx_yellow_prio_3",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_3,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_4] = {
- .name = "tx_yellow_prio_4",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_4,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_5] = {
- .name = "tx_yellow_prio_5",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_5,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_6] = {
- .name = "tx_yellow_prio_6",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_6,
- },
- [OCELOT_STAT_TX_YELLOW_PRIO_7] = {
- .name = "tx_yellow_prio_7",
- .reg = SYS_COUNT_TX_YELLOW_PRIO_7,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_0] = {
- .name = "tx_green_prio_0",
- .reg = SYS_COUNT_TX_GREEN_PRIO_0,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_1] = {
- .name = "tx_green_prio_1",
- .reg = SYS_COUNT_TX_GREEN_PRIO_1,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_2] = {
- .name = "tx_green_prio_2",
- .reg = SYS_COUNT_TX_GREEN_PRIO_2,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_3] = {
- .name = "tx_green_prio_3",
- .reg = SYS_COUNT_TX_GREEN_PRIO_3,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_4] = {
- .name = "tx_green_prio_4",
- .reg = SYS_COUNT_TX_GREEN_PRIO_4,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_5] = {
- .name = "tx_green_prio_5",
- .reg = SYS_COUNT_TX_GREEN_PRIO_5,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_6] = {
- .name = "tx_green_prio_6",
- .reg = SYS_COUNT_TX_GREEN_PRIO_6,
- },
- [OCELOT_STAT_TX_GREEN_PRIO_7] = {
- .name = "tx_green_prio_7",
- .reg = SYS_COUNT_TX_GREEN_PRIO_7,
- },
- [OCELOT_STAT_TX_AGED] = {
- .name = "tx_aged",
- .reg = SYS_COUNT_TX_AGING,
- },
- [OCELOT_STAT_DROP_LOCAL] = {
- .name = "drop_local",
- .reg = SYS_COUNT_DROP_LOCAL,
- },
- [OCELOT_STAT_DROP_TAIL] = {
- .name = "drop_tail",
- .reg = SYS_COUNT_DROP_TAIL,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_0] = {
- .name = "drop_yellow_prio_0",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_0,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_1] = {
- .name = "drop_yellow_prio_1",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_1,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_2] = {
- .name = "drop_yellow_prio_2",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_2,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_3] = {
- .name = "drop_yellow_prio_3",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_3,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_4] = {
- .name = "drop_yellow_prio_4",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_4,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_5] = {
- .name = "drop_yellow_prio_5",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_5,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_6] = {
- .name = "drop_yellow_prio_6",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_6,
- },
- [OCELOT_STAT_DROP_YELLOW_PRIO_7] = {
- .name = "drop_yellow_prio_7",
- .reg = SYS_COUNT_DROP_YELLOW_PRIO_7,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_0] = {
- .name = "drop_green_prio_0",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_0,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_1] = {
- .name = "drop_green_prio_1",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_1,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_2] = {
- .name = "drop_green_prio_2",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_2,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_3] = {
- .name = "drop_green_prio_3",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_3,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_4] = {
- .name = "drop_green_prio_4",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_4,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_5] = {
- .name = "drop_green_prio_5",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_5,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_6] = {
- .name = "drop_green_prio_6",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_6,
- },
- [OCELOT_STAT_DROP_GREEN_PRIO_7] = {
- .name = "drop_green_prio_7",
- .reg = SYS_COUNT_DROP_GREEN_PRIO_7,
- },
+ OCELOT_COMMON_STATS,
};
static const struct vcap_field vsc9959_vcap_es0_keys[] = {
@@ -1371,9 +946,11 @@ static void vsc9959_wm_stat(u32 val, u32 *inuse, u32 *maxuse)
static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
{
+ struct pci_dev *pdev = to_pci_dev(ocelot->dev);
struct felix *felix = ocelot_to_felix(ocelot);
struct enetc_mdio_priv *mdio_priv;
struct device *dev = ocelot->dev;
+ resource_size_t imdio_base;
void __iomem *imdio_regs;
struct resource res;
struct enetc_hw *hw;
@@ -1389,10 +966,11 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
return -ENOMEM;
}
- memcpy(&res, felix->info->imdio_res, sizeof(res));
- res.flags = IORESOURCE_MEM;
- res.start += felix->imdio_base;
- res.end += felix->imdio_base;
+ imdio_base = pci_resource_start(pdev, VSC9959_IMDIO_PCI_BAR);
+
+ memcpy(&res, &vsc9959_imdio_res, sizeof(res));
+ res.start += imdio_base;
+ res.end += imdio_base;
imdio_regs = devm_ioremap_resource(dev, &res);
if (IS_ERR(imdio_regs))
@@ -1616,6 +1194,14 @@ static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc)
}
}
+static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc)
+{
+ if (!taprio || !taprio->max_sdu[tc])
+ return 0;
+
+ return taprio->max_sdu[tc] + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN;
+}
+
/* Update QSYS_PORT_MAX_SDU to make sure the static guard bands added by the
* switch (see the ALWAYS_GUARD_BAND_SCH_Q comment) are correct at all MTU
* values (the default value is 1518). Also, for traffic class windows smaller
@@ -1625,6 +1211,7 @@ static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc)
static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
+ struct tc_taprio_qopt_offload *taprio;
u64 min_gate_len[OCELOT_NUM_TC];
int speed, picos_per_byte;
u64 needed_bit_time_ps;
@@ -1634,6 +1221,8 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
lockdep_assert_held(&ocelot->tas_lock);
+ taprio = ocelot_port->taprio;
+
val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port);
tas_speed = QSYS_TAG_CONFIG_LINK_SPEED_X(val);
@@ -1670,11 +1259,12 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
"port %d: max frame size %d needs %llu ps at speed %d\n",
port, maxlen, needed_bit_time_ps, speed);
- vsc9959_tas_min_gate_lengths(ocelot_port->taprio, min_gate_len);
+ vsc9959_tas_min_gate_lengths(taprio, min_gate_len);
mutex_lock(&ocelot->fwd_domain_lock);
for (tc = 0; tc < OCELOT_NUM_TC; tc++) {
+ u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc);
u64 remaining_gate_len_ps;
u32 max_sdu;
@@ -1685,7 +1275,7 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
/* Setting QMAXSDU_CFG to 0 disables oversized frame
* dropping.
*/
- max_sdu = 0;
+ max_sdu = requested_max_sdu;
dev_dbg(ocelot->dev,
"port %d tc %d min gate len %llu"
", sending all frames\n",
@@ -1716,6 +1306,10 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
*/
if (max_sdu > 20)
max_sdu -= 20;
+
+ if (requested_max_sdu && requested_max_sdu < max_sdu)
+ max_sdu = requested_max_sdu;
+
dev_info(ocelot->dev,
"port %d tc %d min gate length %llu"
" ns not enough for max frame size %d at %d"
@@ -2005,6 +1599,21 @@ static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
return 0;
}
+static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)
+{
+ switch (base->type) {
+ case TC_SETUP_QDISC_TAPRIO: {
+ struct tc_taprio_caps *caps = base->caps;
+
+ caps->supports_queue_max_sdu = true;
+
+ return 0;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type,
void *type_data)
@@ -2012,6 +1621,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
struct ocelot *ocelot = ds->priv;
switch (type) {
+ case TC_QUERY_CAPS:
+ return vsc9959_qos_query_caps(type_data);
case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data);
case TC_SETUP_QDISC_CBS:
@@ -2043,7 +1654,15 @@ struct felix_stream {
u32 ssid;
};
+struct felix_stream_filter_counters {
+ u64 match;
+ u64 not_pass_gate;
+ u64 not_pass_sdu;
+ u64 red;
+};
+
struct felix_stream_filter {
+ struct felix_stream_filter_counters stats;
struct list_head list;
refcount_t refcount;
u32 index;
@@ -2058,13 +1677,6 @@ struct felix_stream_filter {
u32 maxsdu;
};
-struct felix_stream_filter_counters {
- u32 match;
- u32 not_pass_gate;
- u32 not_pass_sdu;
- u32 red;
-};
-
struct felix_stream_gate {
u32 index;
u8 enable;
@@ -2568,29 +2180,6 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,
}
}
-static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
- struct felix_stream_filter_counters *counters)
-{
- spin_lock(&ocelot->stats_lock);
-
- ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index),
- SYS_STAT_CFG_STAT_VIEW_M,
- SYS_STAT_CFG);
-
- counters->match = ocelot_read_gix(ocelot, SYS_CNT, 0x200);
- counters->not_pass_gate = ocelot_read_gix(ocelot, SYS_CNT, 0x201);
- counters->not_pass_sdu = ocelot_read_gix(ocelot, SYS_CNT, 0x202);
- counters->red = ocelot_read_gix(ocelot, SYS_CNT, 0x203);
-
- /* Clear the PSFP counter. */
- ocelot_write(ocelot,
- SYS_STAT_CFG_STAT_VIEW(index) |
- SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),
- SYS_STAT_CFG);
-
- spin_unlock(&ocelot->stats_lock);
-}
-
static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
struct flow_cls_offload *f)
{
@@ -2615,6 +2204,8 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
return ret;
}
+ mutex_lock(&psfp->lock);
+
flow_action_for_each(i, a, &f->rule->action) {
switch (a->id) {
case FLOW_ACTION_GATE:
@@ -2656,6 +2247,7 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
sfi.maxsdu = a->police.mtu;
break;
default:
+ mutex_unlock(&psfp->lock);
return -EOPNOTSUPP;
}
}
@@ -2725,6 +2317,8 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
goto err;
}
+ mutex_unlock(&psfp->lock);
+
return 0;
err:
@@ -2734,6 +2328,8 @@ err:
if (sfi.fm_valid)
ocelot_vcap_policer_del(ocelot, sfi.fmid);
+ mutex_unlock(&psfp->lock);
+
return ret;
}
@@ -2741,18 +2337,22 @@ static int vsc9959_psfp_filter_del(struct ocelot *ocelot,
struct flow_cls_offload *f)
{
struct felix_stream *stream, tmp, *stream_entry;
+ struct ocelot_psfp_list *psfp = &ocelot->psfp;
static struct felix_stream_filter *sfi;
- struct ocelot_psfp_list *psfp;
- psfp = &ocelot->psfp;
+ mutex_lock(&psfp->lock);
stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie);
- if (!stream)
+ if (!stream) {
+ mutex_unlock(&psfp->lock);
return -ENOMEM;
+ }
sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid);
- if (!sfi)
+ if (!sfi) {
+ mutex_unlock(&psfp->lock);
return -ENOMEM;
+ }
if (sfi->sg_valid)
vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid);
@@ -2778,27 +2378,83 @@ static int vsc9959_psfp_filter_del(struct ocelot *ocelot,
stream_entry->ports);
}
+ mutex_unlock(&psfp->lock);
+
return 0;
}
+static void vsc9959_update_sfid_stats(struct ocelot *ocelot,
+ struct felix_stream_filter *sfi)
+{
+ struct felix_stream_filter_counters *s = &sfi->stats;
+ u32 match, not_pass_gate, not_pass_sdu, red;
+ u32 sfid = sfi->index;
+
+ lockdep_assert_held(&ocelot->stat_view_lock);
+
+ ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(sfid),
+ SYS_STAT_CFG_STAT_VIEW_M,
+ SYS_STAT_CFG);
+
+ match = ocelot_read(ocelot, SYS_COUNT_SF_MATCHING_FRAMES);
+ not_pass_gate = ocelot_read(ocelot, SYS_COUNT_SF_NOT_PASSING_FRAMES);
+ not_pass_sdu = ocelot_read(ocelot, SYS_COUNT_SF_NOT_PASSING_SDU);
+ red = ocelot_read(ocelot, SYS_COUNT_SF_RED_FRAMES);
+
+ /* Clear the PSFP counter. */
+ ocelot_write(ocelot,
+ SYS_STAT_CFG_STAT_VIEW(sfid) |
+ SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),
+ SYS_STAT_CFG);
+
+ s->match += match;
+ s->not_pass_gate += not_pass_gate;
+ s->not_pass_sdu += not_pass_sdu;
+ s->red += red;
+}
+
+/* Caller must hold &ocelot->stat_view_lock */
+static void vsc9959_update_stats(struct ocelot *ocelot)
+{
+ struct ocelot_psfp_list *psfp = &ocelot->psfp;
+ struct felix_stream_filter *sfi;
+
+ mutex_lock(&psfp->lock);
+
+ list_for_each_entry(sfi, &psfp->sfi_list, list)
+ vsc9959_update_sfid_stats(ocelot, sfi);
+
+ mutex_unlock(&psfp->lock);
+}
+
static int vsc9959_psfp_stats_get(struct ocelot *ocelot,
struct flow_cls_offload *f,
struct flow_stats *stats)
{
- struct felix_stream_filter_counters counters;
- struct ocelot_psfp_list *psfp;
+ struct ocelot_psfp_list *psfp = &ocelot->psfp;
+ struct felix_stream_filter_counters *s;
+ static struct felix_stream_filter *sfi;
struct felix_stream *stream;
- psfp = &ocelot->psfp;
stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie);
if (!stream)
return -ENOMEM;
- vsc9959_psfp_counters_get(ocelot, stream->sfid, &counters);
+ sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid);
+ if (!sfi)
+ return -EINVAL;
+
+ mutex_lock(&ocelot->stat_view_lock);
+
+ vsc9959_update_sfid_stats(ocelot, sfi);
+
+ s = &sfi->stats;
+ stats->pkts = s->match;
+ stats->drops = s->not_pass_gate + s->not_pass_sdu + s->red;
- stats->pkts = counters.match;
- stats->drops = counters.not_pass_gate + counters.not_pass_sdu +
- counters.red;
+ memset(s, 0, sizeof(*s));
+
+ mutex_unlock(&ocelot->stat_view_lock);
return 0;
}
@@ -2810,6 +2466,7 @@ static void vsc9959_psfp_init(struct ocelot *ocelot)
INIT_LIST_HEAD(&psfp->stream_list);
INIT_LIST_HEAD(&psfp->sfi_list);
INIT_LIST_HEAD(&psfp->sgi_list);
+ mutex_init(&psfp->lock);
}
/* When using cut-through forwarding and the egress port runs at a higher data
@@ -2908,12 +2565,13 @@ static const struct ocelot_ops vsc9959_ops = {
.psfp_stats_get = vsc9959_psfp_stats_get,
.cut_through_fwd = vsc9959_cut_through_fwd,
.tas_clock_adjust = vsc9959_tas_clock_adjust,
+ .update_stats = vsc9959_update_stats,
};
static const struct felix_info felix_info_vsc9959 = {
- .target_io_res = vsc9959_target_io_res,
- .port_io_res = vsc9959_port_io_res,
- .imdio_res = &vsc9959_imdio_res,
+ .resources = vsc9959_resources,
+ .num_resources = ARRAY_SIZE(vsc9959_resources),
+ .resource_names = vsc9959_resource_names,
.regfields = vsc9959_regfields,
.map = vsc9959_regmap,
.ops = &vsc9959_ops,
@@ -2935,7 +2593,6 @@ static const struct felix_info felix_info_vsc9959 = {
.port_setup_tc = vsc9959_port_setup_tc,
.port_sched_speed_set = vsc9959_sched_speed_set,
.tas_guard_bands_update = vsc9959_tas_guard_bands_update,
- .init_regmap = ocelot_regmap_init,
};
static irqreturn_t felix_irq_handler(int irq, void *data)
@@ -2987,7 +2644,6 @@ static int felix_pci_probe(struct pci_dev *pdev,
ocelot->num_flooding_pgids = OCELOT_NUM_TC;
felix->info = &felix_info_vsc9959;
felix->switch_base = pci_resource_start(pdev, VSC9959_SWITCH_PCI_BAR);
- felix->imdio_base = pci_resource_start(pdev, VSC9959_IMDIO_PCI_BAR);
pci_set_master(pdev);
@@ -3048,8 +2704,6 @@ static void felix_pci_remove(struct pci_dev *pdev)
kfree(felix);
pci_disable_device(pdev);
-
- pci_set_drvdata(pdev, NULL);
}
static void felix_pci_shutdown(struct pci_dev *pdev)