diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c index 9d8e0dd9eb6..9b5478a51c3 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -221,95 +220,6 @@ static int rtldsa_ports_probe(struct rtl838x_switch_priv *priv) // return idx; // } -/* - * Packet counters share hardware memory with octet counters (2 packet counters - * per 1 octet block). Allocation relies on two complementary bitmaps: - * - * octet_cntr_use_bm: 0 = free block, 1 = used (or split into packet counters) - * packet_cntr_use_bm: 1 = free standalone counter, 0 = unavailable - * - * Allocation strategy: - * 1. Look for a free standalone counter from an already split block (bit = 1). - * 2. If none are free, claim a new octet block 'j', use counter index (2 * j), - * and mark counter (2 * j + 1) as available for future allocations. - */ - -/** - * rtldsa_packet_cntr_alloc - Allocate a hardware packet counter. - * @priv: Switch driver private structure. - * - * Return: Counter index (>= 0) on success, or -1 if full. - */ -int rtldsa_packet_cntr_alloc(struct rtl838x_switch_priv *priv) -{ - int idx, j, base = 0; - - /* On SoCs where a PIE rule implicitly logs into the LOG table entry - * with its own rule ID (RTL930x), the tc cls_flower offload consumes - * one LOG counter per PIE rule and does not pass through this - * allocator. Keep that range reserved so a route counter handed out - * here cannot alias a flow's LOG entry. - * - * The offload is ingress-only, so PIE rule IDs currently populate - * only the lower half of that range, and a route counter's LOG entry - * (idx / 2) never dips below the upper half either. If egress PIE - * rules are ever wired up, this reservation needs to grow so their - * LOG entries stay clear of route counters too. - */ - if (priv->r->pie_rule_id_is_log_counter) - base = priv->r->n_pie_blocks * PIE_BLOCK_SIZE; - - scoped_guard(mutex, &priv->reg_mutex) { - idx = find_next_bit(priv->packet_cntr_use_bm, priv->r->n_counters * 2, base); - if (idx >= priv->r->n_counters * 2) { - j = find_next_zero_bit(priv->octet_cntr_use_bm, priv->r->n_counters, - base / 2); - if (j >= priv->r->n_counters) - return -1; - - __set_bit(j, priv->octet_cntr_use_bm); - idx = j * 2; - __set_bit(j * 2 + 1, priv->packet_cntr_use_bm); - } else { - __clear_bit(idx, priv->packet_cntr_use_bm); - } - } - - return idx; -} - -/** - * rtldsa_packet_cntr_free - Release a packet counter from rtldsa_packet_cntr_alloc(). - * @priv: Switch driver private structure. - * @idx: Packet counter index to free; a negative id is ignored. - * - * Marks the counter free again and, once both halves of its octet block are - * free, returns the whole block to the octet counter pool. - */ -void rtldsa_packet_cntr_free(struct rtl838x_switch_priv *priv, int idx) -{ - int j; - - if (idx < 0 || idx >= priv->r->n_counters * 2) - return; - - scoped_guard(mutex, &priv->reg_mutex) { - /* already free - guard against a double release */ - if (test_bit(idx, priv->packet_cntr_use_bm)) - return; - - __set_bit(idx, priv->packet_cntr_use_bm); - - j = idx / 2; - if (test_bit(j, priv->octet_cntr_use_bm) && - test_bit(idx ^ 1, priv->packet_cntr_use_bm)) { - __clear_bit(idx, priv->packet_cntr_use_bm); - __clear_bit(idx ^ 1, priv->packet_cntr_use_bm); - __clear_bit(j, priv->octet_cntr_use_bm); - } - } -} - int rtl83xx_port_is_under(const struct net_device *dev, struct rtl838x_switch_priv *priv) { /* Is the lower network device a DSA user network device of our RTL930X-switch? diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c index 4f12c05a4ac..a871e582259 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c @@ -156,8 +156,8 @@ static int rtldsa_83xx_setup(struct dsa_switch *ds) } priv->r->print_matrix(); - rtldsa_stats_init(priv); - rtldsa_stats_init_counters(priv); + otto_stats_init(priv); + otto_stats_init_counters(priv); rtldsa_83xx_mc_pmasks_setup(priv); otto_vlan_setup(priv); @@ -206,8 +206,8 @@ static int rtldsa_93xx_setup(struct dsa_switch *ds) priv->r->traffic_set(priv->r->cpu_port, BIT_ULL(priv->r->cpu_port)); priv->r->print_matrix(); - rtldsa_stats_init(priv); - rtldsa_stats_init_counters(priv); + otto_stats_init(priv); + otto_stats_init_counters(priv); otto_vlan_setup(priv); @@ -1249,15 +1249,15 @@ const struct dsa_switch_ops rtldsa_83xx_switch_ops = { .phylink_get_caps = rtldsa_phylink_get_caps, - .get_strings = rtldsa_get_strings, - .get_ethtool_stats = rtldsa_get_ethtool_stats, - .get_sset_count = rtldsa_get_sset_count, - .get_eth_phy_stats = rtldsa_get_eth_phy_stats, - .get_eth_mac_stats = rtldsa_get_eth_mac_stats, - .get_eth_ctrl_stats = rtldsa_get_eth_ctrl_stats, - .get_rmon_stats = rtldsa_get_rmon_stats, - .get_stats64 = rtldsa_get_stats64, - .get_pause_stats = rtldsa_get_pause_stats, + .get_strings = otto_stats_get_strings, + .get_ethtool_stats = otto_stats_get_ethtool, + .get_sset_count = otto_stats_get_sset_count, + .get_eth_phy_stats = otto_stats_get_eth_phy, + .get_eth_mac_stats = otto_stats_get_eth_mac, + .get_eth_ctrl_stats = otto_stats_get_eth_ctrl, + .get_rmon_stats = otto_stats_get_rmon, + .get_stats64 = otto_stats_get64, + .get_pause_stats = otto_stats_get_pause, .port_enable = rtldsa_port_enable, .port_disable = rtldsa_port_disable, @@ -1311,15 +1311,15 @@ const struct dsa_switch_ops rtldsa_93xx_switch_ops = { .phylink_get_caps = rtldsa_phylink_get_caps, - .get_strings = rtldsa_get_strings, - .get_ethtool_stats = rtldsa_get_ethtool_stats, - .get_sset_count = rtldsa_get_sset_count, - .get_eth_phy_stats = rtldsa_get_eth_phy_stats, - .get_eth_mac_stats = rtldsa_get_eth_mac_stats, - .get_eth_ctrl_stats = rtldsa_get_eth_ctrl_stats, - .get_rmon_stats = rtldsa_get_rmon_stats, - .get_stats64 = rtldsa_get_stats64, - .get_pause_stats = rtldsa_get_pause_stats, + .get_strings = otto_stats_get_strings, + .get_ethtool_stats = otto_stats_get_ethtool, + .get_sset_count = otto_stats_get_sset_count, + .get_eth_phy_stats = otto_stats_get_eth_phy, + .get_eth_mac_stats = otto_stats_get_eth_mac, + .get_eth_ctrl_stats = otto_stats_get_eth_ctrl, + .get_rmon_stats = otto_stats_get_rmon, + .get_stats64 = otto_stats_get64, + .get_pause_stats = otto_stats_get_pause, .port_enable = rtldsa_port_enable, .port_disable = rtldsa_port_disable, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 7ec5cd2ced1..e9af3c9e43c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -80,6 +80,7 @@ #include "l3.h" #include "pie.h" #include "rtl-otto.h" +#include "stats.h" /* Route entry types */ #define ROUTE_TYPE_IP4UC 0 @@ -1745,7 +1746,7 @@ static void otto_l3_route_update_hw(struct otto_l3_ctrl *ctrl, struct otto_l3_ro return; if (r->pr.id < 0) { - r->pr.packet_cntr = rtldsa_packet_cntr_alloc(priv); + r->pr.packet_cntr = otto_stats_packet_cntr_alloc(priv); if (r->pr.packet_cntr >= 0) { dev_info(ctrl->dev, "Using packet counter %d\n", r->pr.packet_cntr); @@ -2174,7 +2175,7 @@ static void otto_l3_route_teardown(struct otto_l3_ctrl *ctrl, struct otto_l3_rou otto_l2_nexthop_del(priv, &r->nh); dev_dbg(ctrl->dev, "releasing packet counter %d\n", r->pr.packet_cntr); - rtldsa_packet_cntr_free(priv, r->pr.packet_cntr); + otto_stats_packet_cntr_free(priv, r->pr.packet_cntr); /* Once the rows are not where the list says, after a failed move or a * lookup that timed out, the row of a prefix route may still be in diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index a25f72c0629..76ad086ffff 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -337,7 +337,7 @@ struct rtldsa_config { * code. * * Any SoC family which requires stat_port_table_read must use the table - * rtldsa_counters_(un)lock_table helpers. They are using a mutex for locking. The counters + * otto_stats_counters_(un)lock_table helpers. They are using a mutex for locking. The counters * update is therefore not atomic. */ void (*stat_update_counters_atomically)(struct rtl838x_switch_priv *priv, int port); @@ -554,8 +554,6 @@ struct fdb_update_work { }; void rtldsa_port_fast_age(struct dsa_switch *ds, int port); -int rtldsa_packet_cntr_alloc(struct rtl838x_switch_priv *priv); -void rtldsa_packet_cntr_free(struct rtl838x_switch_priv *priv, int idx); int rtl83xx_port_is_under(const struct net_device *dev, struct rtl838x_switch_priv *priv); /* Port register accessor functions for the RTL839x and RTL931X SoCs */ void rtl839x_mask_port_reg_be(u64 clear, u64 set, int reg); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c index 4331f8e7b74..0eff30e5ad7 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c @@ -157,46 +157,6 @@ static void rtl838x_init_eee(struct rtl838x_switch_priv *priv, bool enable) priv->eee_enabled = enable; } -static u32 rtl838x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter) -{ - u32 buf[2]; - u32 v; - - dev_dbg(priv->dev, "reading LOG packet counter %d\n", counter); - otto_table_read(RTL8380_TBL_LOG, counter / 2, &buf); - - dev_dbg(priv->dev, "LOG entry: %08x %08x\n", buf[0], buf[1]); - if (counter % 2) - v = buf[0]; - else - v = buf[1]; - - return v; -} - -static void rtl838x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter) -{ - int tbl = otto_table_acquire(RTL8380_TBL_LOG); - u32 buf[2]; - - dev_dbg(priv->dev, "clearing LOG packet counter %d\n", counter); - - /* - * Two counters share one LOG table entry. Read the current entry - * first so clearing one half preserves the adjacent counter. - */ - __otto_table_read(tbl, counter / 2, &buf); - - if (counter % 2) - buf[0] = 0; - else - buf[1] = 0; - - __otto_table_write(tbl, counter / 2, &buf); - - otto_table_release(tbl); -} - static void rtl838x_set_igr_filter(int port, enum igr_filter state) { sw_w32_mask(0x3 << ((port & 0xf) << 1), state << ((port & 0xf) << 1), @@ -229,12 +189,6 @@ static void rtl838x_set_receive_management_action(int port, rma_ctrl_t type, act } } -static void rtldsa_838x_stat_init(struct rtl838x_switch_priv *priv) -{ - /* Enable statistics module: all counters plus debug */ - sw_w32_mask(0, 3, RTL838X_STAT_CTRL); -} - const struct rtldsa_config rtldsa_838x_cfg = { .switch_ops = &rtldsa_83xx_switch_ops, .phylink_mac_ops = &rtldsa_83xx_phylink_mac_ops, @@ -254,12 +208,12 @@ const struct rtldsa_config rtldsa_838x_cfg = { .get_port_reg_le = rtl838x_get_port_reg, .stat_port_rst = RTL838X_STAT_PORT_RST, .stat_rst = RTL838X_STAT_RST, - .stat_init = rtldsa_838x_stat_init, + .stat_init = otto_stats_838x_init, .stat_port_std_mib = RTL838X_STAT_PORT_STD_MIB, .mib_desc = &rtldsa_838x_mib_desc, - .stat_counters_lock = rtldsa_counters_lock_register, - .stat_counters_unlock = rtldsa_counters_unlock_register, - .stat_update_counters_atomically = rtldsa_update_counters_atomically, + .stat_counters_lock = otto_stats_counters_lock_register, + .stat_counters_unlock = otto_stats_counters_unlock_register, + .stat_update_counters_atomically = otto_stats_update_counters_atomically, .stat_counter_poll_interval = RTLDSA_COUNTERS_POLL_INTERVAL, .port_iso_ctrl = rtl838x_port_iso_ctrl, .traffic_enable = rtl838x_traffic_enable, @@ -330,8 +284,8 @@ const struct rtldsa_config rtldsa_838x_cfg = { .pie_rule_add = rtl838x_pie_rule_add, .pie_rule_rm = rtl838x_pie_rule_rm, .l2_learning_setup = otto_l2_838x_learning_setup, - .packet_cntr_read = rtl838x_packet_cntr_read, - .packet_cntr_clear = rtl838x_packet_cntr_clear, + .packet_cntr_read = otto_stats_838x_packet_cntr_read, + .packet_cntr_clear = otto_stats_838x_packet_cntr_clear, .set_receive_management_action = rtl838x_set_receive_management_action, .get_egress_rate = rtldsa_838x_get_egress_rate, .set_egress_rate = rtldsa_838x_set_egress_rate, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c index 73a356b8d49..0cabdb1b28b 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c @@ -157,45 +157,6 @@ static void rtl839x_init_eee(struct rtl838x_switch_priv *priv, bool enable) priv->eee_enabled = enable; } -static u32 rtl839x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter) -{ - u32 buf[2]; - u32 v; - - dev_dbg(priv->dev, "reading LOG packet counter %d\n", counter); - otto_table_read(RTL8390_TBL_LOG, counter / 2, &buf); - - if (counter % 2) - v = buf[0]; - else - v = buf[1]; - - return v; -} - -static void rtl839x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter) -{ - int tbl = otto_table_acquire(RTL8390_TBL_LOG); - u32 buf[2]; - - dev_dbg(priv->dev, "clearing LOG packet counter %d\n", counter); - - /* - * Two counters share one LOG table entry. Read the current entry - * first so clearing one half preserves the adjacent counter. - */ - __otto_table_read(tbl, counter / 2, &buf); - - if (counter % 2) - buf[0] = 0; - else - buf[1] = 0; - - __otto_table_write(tbl, counter / 2, &buf); - - otto_table_release(tbl); -} - static void rtl839x_set_igr_filter(int port, enum igr_filter state) { sw_w32_mask(0x3 << ((port & 0xf) << 1), state << ((port & 0xf) << 1), @@ -249,9 +210,9 @@ const struct rtldsa_config rtldsa_839x_cfg = { .stat_rst = RTL839X_STAT_RST, .stat_port_std_mib = RTL839X_STAT_PORT_STD_MIB, .mib_desc = &rtldsa_839x_mib_desc, - .stat_counters_lock = rtldsa_counters_lock_register, - .stat_counters_unlock = rtldsa_counters_unlock_register, - .stat_update_counters_atomically = rtldsa_update_counters_atomically, + .stat_counters_lock = otto_stats_counters_lock_register, + .stat_counters_unlock = otto_stats_counters_unlock_register, + .stat_update_counters_atomically = otto_stats_update_counters_atomically, .stat_counter_poll_interval = RTLDSA_COUNTERS_POLL_INTERVAL, .traffic_enable = rtl839x_traffic_enable, .traffic_disable = rtl839x_traffic_disable, @@ -320,8 +281,8 @@ const struct rtldsa_config rtldsa_839x_cfg = { .pie_rule_add = rtl839x_pie_rule_add, .pie_rule_rm = rtl839x_pie_rule_rm, .l2_learning_setup = otto_l2_839x_learning_setup, - .packet_cntr_read = rtl839x_packet_cntr_read, - .packet_cntr_clear = rtl839x_packet_cntr_clear, + .packet_cntr_read = otto_stats_839x_packet_cntr_read, + .packet_cntr_clear = otto_stats_839x_packet_cntr_clear, .set_receive_management_action = rtl839x_set_receive_management_action, .get_egress_rate = rtldsa_839x_get_egress_rate, .set_egress_rate = rtldsa_839x_set_egress_rate, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index f79bcf453c8..9d367e960fb 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -383,61 +383,6 @@ static void rtl930x_init_eee(struct rtl838x_switch_priv *priv, bool enable) // return mtu_id; // } -/* A PIE rule logs its matched packets into the LOG table entry that carries - * its own rule ID, in data word 1 - one entry per rule. Counters handed out - * by rtldsa_packet_cntr_alloc() for L3 route statistics start above the PIE - * rule ID range and pack two 32-bit counters into one 64-bit LOG entry. - */ -#define RTL930X_PIE_RULE_IDS (rtldsa_930x_cfg.n_pie_blocks * PIE_BLOCK_SIZE) - -static u32 rtl930x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter) -{ - u32 buf[2]; - u32 v; - - dev_dbg(priv->dev, "reading LOG packet counter %d\n", counter); - - if (counter < RTL930X_PIE_RULE_IDS) { - otto_table_read(RTL9300_TBL_LOG, counter, &buf); - v = buf[1]; - } else { - /* Two counters share one entry, so the parity of counter picks - * which half of it to return. - */ - otto_table_read(RTL9300_TBL_LOG, counter / 2, &buf); - v = counter % 2 ? buf[0] : buf[1]; - } - - dev_dbg(priv->dev, "LOG entry: %08x %08x\n", buf[0], buf[1]); - - return v; -} - -static void rtl930x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter) -{ - int tbl = otto_table_acquire(RTL9300_TBL_LOG); - - u32 v[2]; - - dev_dbg(priv->dev, "clearing LOG packet counter %d\n", counter); - - /* Read-modify-write: for a route counter the other 32-bit counter in - * the same 64-bit entry must be preserved; for a PIE rule ID the entry - * is ours alone but the RMW is harmless. - */ - if (counter < RTL930X_PIE_RULE_IDS) { - __otto_table_read(tbl, counter, &v); - v[1] = 0; - __otto_table_write(tbl, counter, &v); - } else { - __otto_table_read(tbl, counter / 2, &v); - v[counter % 2 ? 0 : 1] = 0; - __otto_table_write(tbl, counter / 2, &v); - } - - otto_table_release(tbl); -} - static void rtl930x_set_igr_filter(int port, enum igr_filter state) { sw_w32_mask(0x3 << ((port & 0xf) << 1), state << ((port & 0xf) << 1), @@ -620,9 +565,9 @@ const struct rtldsa_config rtldsa_930x_cfg = { .stat_port_std_mib = RTL930X_STAT_PORT_MIB_CNTR, .stat_port_prv_mib = RTL930X_STAT_PORT_PRVTE_CNTR, .mib_desc = &rtldsa_930x_mib_desc, - .stat_counters_lock = rtldsa_counters_lock_register, - .stat_counters_unlock = rtldsa_counters_unlock_register, - .stat_update_counters_atomically = rtldsa_update_counters_atomically, + .stat_counters_lock = otto_stats_counters_lock_register, + .stat_counters_unlock = otto_stats_counters_unlock_register, + .stat_update_counters_atomically = otto_stats_update_counters_atomically, .stat_counter_poll_interval = RTLDSA_COUNTERS_POLL_INTERVAL, .traffic_enable = rtl930x_traffic_enable, .traffic_disable = rtl930x_traffic_disable, @@ -686,8 +631,8 @@ const struct rtldsa_config rtldsa_930x_cfg = { .pie_rule_add = rtl930x_pie_rule_add, .pie_rule_rm = rtl930x_pie_rule_rm, .l2_learning_setup = otto_l2_930x_learning_setup, - .packet_cntr_read = rtl930x_packet_cntr_read, - .packet_cntr_clear = rtl930x_packet_cntr_clear, + .packet_cntr_read = otto_stats_930x_packet_cntr_read, + .packet_cntr_clear = otto_stats_930x_packet_cntr_clear, .led_init = rtl930x_led_init, .enable_learning = otto_l2_930x_enable_learning, .enable_l2_new_sa_fwd = otto_l2_930x_set_port_new_sa_fwd, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c index 61de425a795..14d985f052b 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c @@ -385,36 +385,6 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv) dev_dbg(dev, "%08x: %08x\n", 0xbb000600 + i * 4, sw_r32(0x0600 + i * 4)); } -static u64 rtldsa_931x_stat_port_table_read(int port, unsigned int mib_size, - unsigned int mib_offset, bool is_pvt) -{ - enum otto_table_id id; - int field_offset; - u32 val[2]; - - if (is_pvt) { - id = RTL9310_TBL_STAT_PORT_PRVTE_CNTR; - field_offset = 27; - } else { - id = RTL9310_TBL_STAT_PORT_MIB_CNTR; - field_offset = 52; - } - - /* Counter fields are numbered down from the last data word of the - * entry, so the high half of a 64 bit counter sits at the lower word - * index. - */ - if (mib_size == 2) { - otto_table_offset_read(id, port, &val, field_offset - (mib_offset + 1)); - - return (u64)val[0] << 32 | val[1]; - } - - otto_table_offset_read(id, port, &val[0], field_offset - mib_offset); - - return val[0]; -} - const struct rtldsa_config rtldsa_931x_cfg = { .switch_ops = &rtldsa_93xx_switch_ops, .phylink_mac_ops = &rtldsa_93xx_phylink_mac_ops, @@ -436,9 +406,9 @@ const struct rtldsa_config rtldsa_931x_cfg = { .stat_rst = RTL931X_STAT_RST, .stat_port_std_mib = 0, /* Not defined */ .mib_desc = &rtldsa_931x_mib_desc, - .stat_port_table_read = rtldsa_931x_stat_port_table_read, - .stat_counters_lock = rtldsa_counters_lock_table, - .stat_counters_unlock = rtldsa_counters_unlock_table, + .stat_port_table_read = otto_stats_931x_port_table_read, + .stat_counters_lock = otto_stats_counters_lock_table, + .stat_counters_unlock = otto_stats_counters_unlock_table, .stat_counter_poll_interval = RTLDSA_COUNTERS_FAST_POLL_INTERVAL, .traffic_enable = rtl931x_traffic_enable, .traffic_disable = rtl931x_traffic_disable, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.c index 0ca24d3c09d..4a45a71ac9d 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.c @@ -1,7 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include #include +#include "pie.h" #include "rtl-otto.h" #include "stats.h" @@ -368,7 +374,43 @@ const struct rtldsa_mib_desc rtldsa_931x_mib_desc = { .list = rtldsa_931x_mib_list }; -void rtldsa_stats_init(struct rtl838x_switch_priv *priv) +void otto_stats_838x_init(struct rtl838x_switch_priv *priv) +{ + /* Enable statistics module: all counters plus debug */ + sw_w32_mask(0, 3, RTL838X_STAT_CTRL); +} + +u64 otto_stats_931x_port_table_read(int port, unsigned int mib_size, + unsigned int mib_offset, bool is_pvt) +{ + enum otto_table_id id; + int field_offset; + u32 val[2]; + + if (is_pvt) { + id = RTL9310_TBL_STAT_PORT_PRVTE_CNTR; + field_offset = 27; + } else { + id = RTL9310_TBL_STAT_PORT_MIB_CNTR; + field_offset = 52; + } + + /* Counter fields are numbered down from the last data word of the + * entry, so the high half of a 64 bit counter sits at the lower word + * index. + */ + if (mib_size == 2) { + otto_table_offset_read(id, port, &val, field_offset - (mib_offset + 1)); + + return (u64)val[0] << 32 | val[1]; + } + + otto_table_offset_read(id, port, &val[0], field_offset - mib_offset); + + return val[0]; +} + +void otto_stats_init(struct rtl838x_switch_priv *priv) { mutex_lock(&priv->reg_mutex); @@ -381,9 +423,9 @@ void rtldsa_stats_init(struct rtl838x_switch_priv *priv) mutex_unlock(&priv->reg_mutex); } -static bool rtldsa_read_mib_item(struct rtl838x_switch_priv *priv, int port, - const struct rtldsa_mib_item *mib_item, - u64 *data) +static bool otto_stats_read_mib_item(struct rtl838x_switch_priv *priv, int port, + const struct rtldsa_mib_item *mib_item, + u64 *data) { u32 high1, high2; int reg, reg_offset, addr_low; @@ -428,14 +470,14 @@ static bool rtldsa_read_mib_item(struct rtl838x_switch_priv *priv, int port, return true; } -static void rtldsa_update_counter(struct rtl838x_switch_priv *priv, int port, - struct rtldsa_counter *counter, - const struct rtldsa_mib_item *mib_item) +static void otto_stats_update_counter(struct rtl838x_switch_priv *priv, int port, + struct rtldsa_counter *counter, + const struct rtldsa_mib_item *mib_item) { u64 val; u32 val32, diff; - if (!rtldsa_read_mib_item(priv, port, mib_item, &val)) + if (!otto_stats_read_mib_item(priv, port, mib_item, &val)) return; if (mib_item->size == 2) { @@ -448,8 +490,8 @@ static void rtldsa_update_counter(struct rtl838x_switch_priv *priv, int port, } } -static void rtldsa_update_link_stat(struct rtnl_link_stats64 *s, - const struct rtldsa_counter_state *counters) +static void otto_stats_update_link(struct rtnl_link_stats64 *s, + const struct rtldsa_counter_state *counters) { s->rx_packets = counters->if_in_ucast_pkts.val + counters->if_in_mcast_pkts.val + @@ -483,7 +525,7 @@ static void rtldsa_update_link_stat(struct rtnl_link_stats64 *s, s->tx_errors = s->tx_aborted_errors + s->tx_window_errors; } -static void rtldsa_update_port_counters(struct rtl838x_switch_priv *priv, int port) +static void otto_stats_update_port_counters(struct rtl838x_switch_priv *priv, int port) { struct rtldsa_counter_state *counters = &priv->ports[port].counters; const struct rtldsa_mib_desc *mib_desc; @@ -500,120 +542,120 @@ static void rtldsa_update_port_counters(struct rtl838x_switch_priv *priv, int po return; counters->last_update = now; - rtldsa_update_counter(priv, port, &counters->symbol_errors, - &mib_desc->symbol_errors); + otto_stats_update_counter(priv, port, &counters->symbol_errors, + &mib_desc->symbol_errors); - rtldsa_update_counter(priv, port, &counters->if_in_octets, - &mib_desc->if_in_octets); - rtldsa_update_counter(priv, port, &counters->if_out_octets, - &mib_desc->if_out_octets); - rtldsa_update_counter(priv, port, &counters->if_in_ucast_pkts, - &mib_desc->if_in_ucast_pkts); - rtldsa_update_counter(priv, port, &counters->if_in_mcast_pkts, - &mib_desc->if_in_mcast_pkts); - rtldsa_update_counter(priv, port, &counters->if_in_bcast_pkts, - &mib_desc->if_in_bcast_pkts); - rtldsa_update_counter(priv, port, &counters->if_out_ucast_pkts, - &mib_desc->if_out_ucast_pkts); - rtldsa_update_counter(priv, port, &counters->if_out_mcast_pkts, - &mib_desc->if_out_mcast_pkts); - rtldsa_update_counter(priv, port, &counters->if_out_bcast_pkts, - &mib_desc->if_out_bcast_pkts); - rtldsa_update_counter(priv, port, &counters->if_out_discards, - &mib_desc->if_out_discards); - rtldsa_update_counter(priv, port, &counters->single_collisions, - &mib_desc->single_collisions); - rtldsa_update_counter(priv, port, &counters->multiple_collisions, - &mib_desc->multiple_collisions); - rtldsa_update_counter(priv, port, &counters->deferred_transmissions, - &mib_desc->deferred_transmissions); - rtldsa_update_counter(priv, port, &counters->late_collisions, - &mib_desc->late_collisions); - rtldsa_update_counter(priv, port, &counters->excessive_collisions, - &mib_desc->excessive_collisions); - rtldsa_update_counter(priv, port, &counters->crc_align_errors, - &mib_desc->crc_align_errors); - rtldsa_update_counter(priv, port, &counters->rx_pkts_over_max_octets, - &mib_desc->rx_pkts_over_max_octets); + otto_stats_update_counter(priv, port, &counters->if_in_octets, + &mib_desc->if_in_octets); + otto_stats_update_counter(priv, port, &counters->if_out_octets, + &mib_desc->if_out_octets); + otto_stats_update_counter(priv, port, &counters->if_in_ucast_pkts, + &mib_desc->if_in_ucast_pkts); + otto_stats_update_counter(priv, port, &counters->if_in_mcast_pkts, + &mib_desc->if_in_mcast_pkts); + otto_stats_update_counter(priv, port, &counters->if_in_bcast_pkts, + &mib_desc->if_in_bcast_pkts); + otto_stats_update_counter(priv, port, &counters->if_out_ucast_pkts, + &mib_desc->if_out_ucast_pkts); + otto_stats_update_counter(priv, port, &counters->if_out_mcast_pkts, + &mib_desc->if_out_mcast_pkts); + otto_stats_update_counter(priv, port, &counters->if_out_bcast_pkts, + &mib_desc->if_out_bcast_pkts); + otto_stats_update_counter(priv, port, &counters->if_out_discards, + &mib_desc->if_out_discards); + otto_stats_update_counter(priv, port, &counters->single_collisions, + &mib_desc->single_collisions); + otto_stats_update_counter(priv, port, &counters->multiple_collisions, + &mib_desc->multiple_collisions); + otto_stats_update_counter(priv, port, &counters->deferred_transmissions, + &mib_desc->deferred_transmissions); + otto_stats_update_counter(priv, port, &counters->late_collisions, + &mib_desc->late_collisions); + otto_stats_update_counter(priv, port, &counters->excessive_collisions, + &mib_desc->excessive_collisions); + otto_stats_update_counter(priv, port, &counters->crc_align_errors, + &mib_desc->crc_align_errors); + otto_stats_update_counter(priv, port, &counters->rx_pkts_over_max_octets, + &mib_desc->rx_pkts_over_max_octets); - rtldsa_update_counter(priv, port, &counters->unsupported_opcodes, - &mib_desc->unsupported_opcodes); + otto_stats_update_counter(priv, port, &counters->unsupported_opcodes, + &mib_desc->unsupported_opcodes); - rtldsa_update_counter(priv, port, &counters->rx_undersize_pkts, - &mib_desc->rx_undersize_pkts); - rtldsa_update_counter(priv, port, &counters->rx_oversize_pkts, - &mib_desc->rx_oversize_pkts); - rtldsa_update_counter(priv, port, &counters->rx_fragments, - &mib_desc->rx_fragments); - rtldsa_update_counter(priv, port, &counters->rx_jabbers, - &mib_desc->rx_jabbers); + otto_stats_update_counter(priv, port, &counters->rx_undersize_pkts, + &mib_desc->rx_undersize_pkts); + otto_stats_update_counter(priv, port, &counters->rx_oversize_pkts, + &mib_desc->rx_oversize_pkts); + otto_stats_update_counter(priv, port, &counters->rx_fragments, + &mib_desc->rx_fragments); + otto_stats_update_counter(priv, port, &counters->rx_jabbers, + &mib_desc->rx_jabbers); for (int i = 0; i < ARRAY_SIZE(mib_desc->tx_pkts); i++) { if (mib_desc->tx_pkts[i].reg == MIB_REG_INVALID) break; - rtldsa_update_counter(priv, port, &counters->tx_pkts[i], - &mib_desc->tx_pkts[i]); + otto_stats_update_counter(priv, port, &counters->tx_pkts[i], + &mib_desc->tx_pkts[i]); } for (int i = 0; i < ARRAY_SIZE(mib_desc->rx_pkts); i++) { if (mib_desc->rx_pkts[i].reg == MIB_REG_INVALID) break; - rtldsa_update_counter(priv, port, &counters->rx_pkts[i], - &mib_desc->rx_pkts[i]); + otto_stats_update_counter(priv, port, &counters->rx_pkts[i], + &mib_desc->rx_pkts[i]); } - rtldsa_update_counter(priv, port, &counters->drop_events, - &mib_desc->drop_events); - rtldsa_update_counter(priv, port, &counters->collisions, - &mib_desc->collisions); + otto_stats_update_counter(priv, port, &counters->drop_events, + &mib_desc->drop_events); + otto_stats_update_counter(priv, port, &counters->collisions, + &mib_desc->collisions); - rtldsa_update_counter(priv, port, &counters->rx_pause_frames, - &mib_desc->rx_pause_frames); - rtldsa_update_counter(priv, port, &counters->tx_pause_frames, - &mib_desc->tx_pause_frames); + otto_stats_update_counter(priv, port, &counters->rx_pause_frames, + &mib_desc->rx_pause_frames); + otto_stats_update_counter(priv, port, &counters->tx_pause_frames, + &mib_desc->tx_pause_frames); /* prepare get_stats64 reply without requiring caller waiting for mutex */ spin_lock(&counters->link_stat_lock); - rtldsa_update_link_stat(&counters->link_stat, counters); + otto_stats_update_link(&counters->link_stat, counters); spin_unlock(&counters->link_stat_lock); } -void rtldsa_counters_lock_register(struct rtl838x_switch_priv *priv, int port) +void otto_stats_counters_lock_register(struct rtl838x_switch_priv *priv, int port) __acquires(&priv->ports[port].counters.lock) { spin_lock(&priv->ports[port].counters.lock); } -void rtldsa_counters_unlock_register(struct rtl838x_switch_priv *priv, int port) +void otto_stats_counters_unlock_register(struct rtl838x_switch_priv *priv, int port) __releases(&priv->ports[port].counters.lock) { spin_unlock(&priv->ports[port].counters.lock); } -void rtldsa_counters_lock_table(struct rtl838x_switch_priv *priv, int port __maybe_unused) +void otto_stats_counters_lock_table(struct rtl838x_switch_priv *priv, int port __maybe_unused) __acquires(&priv->counters_lock) { mutex_lock(&priv->counters_lock); } -void rtldsa_counters_unlock_table(struct rtl838x_switch_priv *priv, int port __maybe_unused) +void otto_stats_counters_unlock_table(struct rtl838x_switch_priv *priv, int port __maybe_unused) __releases(&priv->ports[port].counters.lock) { mutex_unlock(&priv->counters_lock); } -static void rtldsa_counters_lock(struct rtl838x_switch_priv *priv, int port) +static void otto_stats_counters_lock(struct rtl838x_switch_priv *priv, int port) { priv->r->stat_counters_lock(priv, port); } -static void rtldsa_counters_unlock(struct rtl838x_switch_priv *priv, int port) +static void otto_stats_counters_unlock(struct rtl838x_switch_priv *priv, int port) { priv->r->stat_counters_unlock(priv, port); } -static void rtldsa_poll_counters(struct work_struct *work) +static void otto_stats_poll_counters(struct work_struct *work) { struct rtl838x_switch_priv *priv = container_of(to_delayed_work(work), struct rtl838x_switch_priv, @@ -623,16 +665,16 @@ static void rtldsa_poll_counters(struct work_struct *work) if (!priv->ports[port].phy && !priv->ports[port].has_pcs) continue; - rtldsa_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); - rtldsa_counters_unlock(priv, port); + otto_stats_counters_lock(priv, port); + otto_stats_update_port_counters(priv, port); + otto_stats_counters_unlock(priv, port); } queue_delayed_work(priv->wq, &priv->counters_work, priv->r->stat_counter_poll_interval); } -void rtldsa_stats_init_counters(struct rtl838x_switch_priv *priv) +void otto_stats_init_counters(struct rtl838x_switch_priv *priv) { struct rtldsa_counter_state *counters; @@ -647,12 +689,12 @@ void rtldsa_stats_init_counters(struct rtl838x_switch_priv *priv) spin_lock_init(&counters->link_stat_lock); } - INIT_DELAYED_WORK(&priv->counters_work, rtldsa_poll_counters); + INIT_DELAYED_WORK(&priv->counters_work, otto_stats_poll_counters); queue_delayed_work(priv->wq, &priv->counters_work, priv->r->stat_counter_poll_interval); } -void rtldsa_get_strings(struct dsa_switch *ds, int port, u32 stringset, u8 *data) +void otto_stats_get_strings(struct dsa_switch *ds, int port, u32 stringset, u8 *data) { struct rtl838x_switch_priv *priv = ds->priv; const struct rtldsa_mib_desc *mib_desc; @@ -669,8 +711,8 @@ void rtldsa_get_strings(struct dsa_switch *ds, int port, u32 stringset, u8 *data ethtool_puts(&data, mib_desc->list[i].name); } -void rtldsa_get_ethtool_stats(struct dsa_switch *ds, int port, - u64 *data) +void otto_stats_get_ethtool(struct dsa_switch *ds, int port, + u64 *data) { struct rtl838x_switch_priv *priv = ds->priv; const struct rtldsa_mib_desc *mib_desc; @@ -682,11 +724,11 @@ void rtldsa_get_ethtool_stats(struct dsa_switch *ds, int port, mib_desc = priv->r->mib_desc; for (int i = 0; i < mib_desc->list_count; i++) { mib_item = &mib_desc->list[i].item; - rtldsa_read_mib_item(priv, port, mib_item, &data[i]); + otto_stats_read_mib_item(priv, port, mib_item, &data[i]); } } -int rtldsa_get_sset_count(struct dsa_switch *ds, int port, int sset) +int otto_stats_get_sset_count(struct dsa_switch *ds, int port, int sset) { struct rtl838x_switch_priv *priv = ds->priv; @@ -699,8 +741,8 @@ int rtldsa_get_sset_count(struct dsa_switch *ds, int port, int sset) return priv->r->mib_desc->list_count; } -void rtldsa_get_eth_phy_stats(struct dsa_switch *ds, int port, - struct ethtool_eth_phy_stats *phy_stats) +void otto_stats_get_eth_phy(struct dsa_switch *ds, int port, + struct ethtool_eth_phy_stats *phy_stats) { struct rtl838x_switch_priv *priv = ds->priv; struct rtldsa_counter_state *counters = &priv->ports[port].counters; @@ -708,17 +750,17 @@ void rtldsa_get_eth_phy_stats(struct dsa_switch *ds, int port, if (port < 0 || port >= priv->r->cpu_port) return; - rtldsa_counters_lock(priv, port); + otto_stats_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); + otto_stats_update_port_counters(priv, port); phy_stats->SymbolErrorDuringCarrier = counters->symbol_errors.val; - rtldsa_counters_unlock(priv, port); + otto_stats_counters_unlock(priv, port); } -void rtldsa_get_eth_mac_stats(struct dsa_switch *ds, int port, - struct ethtool_eth_mac_stats *mac_stats) +void otto_stats_get_eth_mac(struct dsa_switch *ds, int port, + struct ethtool_eth_mac_stats *mac_stats) { struct rtl838x_switch_priv *priv = ds->priv; struct rtldsa_counter_state *counters = &priv->ports[port].counters; @@ -726,9 +768,9 @@ void rtldsa_get_eth_mac_stats(struct dsa_switch *ds, int port, if (port < 0 || port >= priv->r->cpu_port) return; - rtldsa_counters_lock(priv, port); + otto_stats_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); + otto_stats_update_port_counters(priv, port); /* Frame and octet counters are calculated based on RFC3635, while also * taking into account that the behaviour of the hardware counters differs @@ -765,11 +807,11 @@ void rtldsa_get_eth_mac_stats(struct dsa_switch *ds, int port, mac_stats->FrameCheckSequenceErrors = counters->crc_align_errors.val; - rtldsa_counters_unlock(priv, port); + otto_stats_counters_unlock(priv, port); } -void rtldsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port, - struct ethtool_eth_ctrl_stats *ctrl_stats) +void otto_stats_get_eth_ctrl(struct dsa_switch *ds, int port, + struct ethtool_eth_ctrl_stats *ctrl_stats) { struct rtl838x_switch_priv *priv = ds->priv; struct rtldsa_counter_state *counters = &priv->ports[port].counters; @@ -777,18 +819,18 @@ void rtldsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port, if (port < 0 || port >= priv->r->cpu_port) return; - rtldsa_counters_lock(priv, port); + otto_stats_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); + otto_stats_update_port_counters(priv, port); ctrl_stats->UnsupportedOpcodesReceived = counters->unsupported_opcodes.val; - rtldsa_counters_unlock(priv, port); + otto_stats_counters_unlock(priv, port); } -void rtldsa_get_rmon_stats(struct dsa_switch *ds, int port, - struct ethtool_rmon_stats *rmon_stats, - const struct ethtool_rmon_hist_range **ranges) +void otto_stats_get_rmon(struct dsa_switch *ds, int port, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) { struct rtl838x_switch_priv *priv = ds->priv; const struct rtldsa_mib_desc *mib_desc; @@ -799,9 +841,9 @@ void rtldsa_get_rmon_stats(struct dsa_switch *ds, int port, mib_desc = priv->r->mib_desc; - rtldsa_counters_lock(priv, port); + otto_stats_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); + otto_stats_update_port_counters(priv, port); rmon_stats->undersize_pkts = counters->rx_undersize_pkts.val; rmon_stats->oversize_pkts = counters->rx_oversize_pkts.val; @@ -824,18 +866,18 @@ void rtldsa_get_rmon_stats(struct dsa_switch *ds, int port, *ranges = mib_desc->rmon_ranges; - rtldsa_counters_unlock(priv, port); + otto_stats_counters_unlock(priv, port); } -void rtldsa_update_counters_atomically(struct rtl838x_switch_priv *priv, int port) +void otto_stats_update_counters_atomically(struct rtl838x_switch_priv *priv, int port) { - rtldsa_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); - rtldsa_counters_unlock(priv, port); + otto_stats_counters_lock(priv, port); + otto_stats_update_port_counters(priv, port); + otto_stats_counters_unlock(priv, port); } -void rtldsa_get_stats64(struct dsa_switch *ds, int port, - struct rtnl_link_stats64 *s) +void otto_stats_get64(struct dsa_switch *ds, int port, + struct rtnl_link_stats64 *s) { struct rtl838x_switch_priv *priv = ds->priv; struct rtldsa_counter_state *counters = &priv->ports[port].counters; @@ -852,8 +894,8 @@ void rtldsa_get_stats64(struct dsa_switch *ds, int port, spin_unlock(&counters->link_stat_lock); } -void rtldsa_get_pause_stats(struct dsa_switch *ds, int port, - struct ethtool_pause_stats *pause_stats) +void otto_stats_get_pause(struct dsa_switch *ds, int port, + struct ethtool_pause_stats *pause_stats) { struct rtl838x_switch_priv *priv = ds->priv; struct rtldsa_counter_state *counters = &priv->ports[port].counters; @@ -861,12 +903,235 @@ void rtldsa_get_pause_stats(struct dsa_switch *ds, int port, if (port < 0 || port >= priv->r->cpu_port) return; - rtldsa_counters_lock(priv, port); + otto_stats_counters_lock(priv, port); - rtldsa_update_port_counters(priv, port); + otto_stats_update_port_counters(priv, port); pause_stats->tx_pause_frames = counters->tx_pause_frames.val; pause_stats->rx_pause_frames = counters->rx_pause_frames.val; - rtldsa_counters_unlock(priv, port); + otto_stats_counters_unlock(priv, port); +} + +/* + * Packet counters share hardware memory with octet counters (2 packet counters + * per 1 octet block). Allocation relies on two complementary bitmaps: + * + * octet_cntr_use_bm: 0 = free block, 1 = used (or split into packet counters) + * packet_cntr_use_bm: 1 = free standalone counter, 0 = unavailable + * + * Allocation strategy: + * 1. Look for a free standalone counter from an already split block (bit = 1). + * 2. If none are free, claim a new octet block 'j', use counter index (2 * j), + * and mark counter (2 * j + 1) as available for future allocations. + */ + +/** + * otto_stats_packet_cntr_alloc - Allocate a hardware packet counter. + * @priv: Switch driver private structure. + * + * Return: Counter index (>= 0) on success, or -1 if full. + */ +int otto_stats_packet_cntr_alloc(struct rtl838x_switch_priv *priv) +{ + int idx, j, base = 0; + + /* On SoCs where a PIE rule implicitly logs into the LOG table entry + * with its own rule ID (RTL930x), the tc cls_flower offload consumes + * one LOG counter per PIE rule and does not pass through this + * allocator. Keep that range reserved so a route counter handed out + * here cannot alias a flow's LOG entry. + * + * The offload is ingress-only, so PIE rule IDs currently populate + * only the lower half of that range, and a route counter's LOG entry + * (idx / 2) never dips below the upper half either. If egress PIE + * rules are ever wired up, this reservation needs to grow so their + * LOG entries stay clear of route counters too. + */ + if (priv->r->pie_rule_id_is_log_counter) + base = priv->r->n_pie_blocks * PIE_BLOCK_SIZE; + + scoped_guard(mutex, &priv->reg_mutex) { + idx = find_next_bit(priv->packet_cntr_use_bm, priv->r->n_counters * 2, base); + if (idx >= priv->r->n_counters * 2) { + j = find_next_zero_bit(priv->octet_cntr_use_bm, priv->r->n_counters, + base / 2); + if (j >= priv->r->n_counters) + return -1; + + __set_bit(j, priv->octet_cntr_use_bm); + idx = j * 2; + __set_bit(j * 2 + 1, priv->packet_cntr_use_bm); + } else { + __clear_bit(idx, priv->packet_cntr_use_bm); + } + } + + return idx; +} + +/** + * otto_stats_packet_cntr_free - Release a packet counter from otto_stats_packet_cntr_alloc(). + * @priv: Switch driver private structure. + * @idx: Packet counter index to free; a negative id is ignored. + * + * Marks the counter free again and, once both halves of its octet block are + * free, returns the whole block to the octet counter pool. + */ +void otto_stats_packet_cntr_free(struct rtl838x_switch_priv *priv, int idx) +{ + int j; + + if (idx < 0 || idx >= priv->r->n_counters * 2) + return; + + scoped_guard(mutex, &priv->reg_mutex) { + /* already free - guard against a double release */ + if (test_bit(idx, priv->packet_cntr_use_bm)) + return; + + __set_bit(idx, priv->packet_cntr_use_bm); + + j = idx / 2; + if (test_bit(j, priv->octet_cntr_use_bm) && + test_bit(idx ^ 1, priv->packet_cntr_use_bm)) { + __clear_bit(idx, priv->packet_cntr_use_bm); + __clear_bit(idx ^ 1, priv->packet_cntr_use_bm); + __clear_bit(j, priv->octet_cntr_use_bm); + } + } +} + +u32 otto_stats_838x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter) +{ + u32 buf[2]; + u32 v; + + dev_dbg(priv->dev, "reading LOG packet counter %d\n", counter); + otto_table_read(RTL8380_TBL_LOG, counter / 2, &buf); + + dev_dbg(priv->dev, "LOG entry: %08x %08x\n", buf[0], buf[1]); + if (counter % 2) + v = buf[0]; + else + v = buf[1]; + + return v; +} + +void otto_stats_838x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter) +{ + int tbl = otto_table_acquire(RTL8380_TBL_LOG); + u32 buf[2]; + + dev_dbg(priv->dev, "clearing LOG packet counter %d\n", counter); + + /* + * Two counters share one LOG table entry. Read the current entry + * first so clearing one half preserves the adjacent counter. + */ + __otto_table_read(tbl, counter / 2, &buf); + + if (counter % 2) + buf[0] = 0; + else + buf[1] = 0; + + __otto_table_write(tbl, counter / 2, &buf); + + otto_table_release(tbl); +} + +u32 otto_stats_839x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter) +{ + u32 buf[2]; + u32 v; + + dev_dbg(priv->dev, "reading LOG packet counter %d\n", counter); + otto_table_read(RTL8390_TBL_LOG, counter / 2, &buf); + + if (counter % 2) + v = buf[0]; + else + v = buf[1]; + + return v; +} + +void otto_stats_839x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter) +{ + int tbl = otto_table_acquire(RTL8390_TBL_LOG); + u32 buf[2]; + + dev_dbg(priv->dev, "clearing LOG packet counter %d\n", counter); + + /* + * Two counters share one LOG table entry. Read the current entry + * first so clearing one half preserves the adjacent counter. + */ + __otto_table_read(tbl, counter / 2, &buf); + + if (counter % 2) + buf[0] = 0; + else + buf[1] = 0; + + __otto_table_write(tbl, counter / 2, &buf); + + otto_table_release(tbl); +} + +/* A PIE rule logs its matched packets into the LOG table entry that carries + * its own rule ID, in data word 1 - one entry per rule. Counters handed out + * by otto_stats_packet_cntr_alloc() for L3 route statistics start above the PIE + * rule ID range and pack two 32-bit counters into one 64-bit LOG entry. + */ +#define RTL930X_PIE_RULE_IDS (rtldsa_930x_cfg.n_pie_blocks * PIE_BLOCK_SIZE) + +u32 otto_stats_930x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter) +{ + u32 buf[2]; + u32 v; + + dev_dbg(priv->dev, "reading LOG packet counter %d\n", counter); + + if (counter < RTL930X_PIE_RULE_IDS) { + otto_table_read(RTL9300_TBL_LOG, counter, &buf); + v = buf[1]; + } else { + /* Two counters share one entry, so the parity of counter picks + * which half of it to return. + */ + otto_table_read(RTL9300_TBL_LOG, counter / 2, &buf); + v = counter % 2 ? buf[0] : buf[1]; + } + + dev_dbg(priv->dev, "LOG entry: %08x %08x\n", buf[0], buf[1]); + + return v; +} + +void otto_stats_930x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter) +{ + int tbl = otto_table_acquire(RTL9300_TBL_LOG); + + u32 v[2]; + + dev_dbg(priv->dev, "clearing LOG packet counter %d\n", counter); + + /* Read-modify-write: for a route counter the other 32-bit counter in + * the same 64-bit entry must be preserved; for a PIE rule ID the entry + * is ours alone but the RMW is harmless. + */ + if (counter < RTL930X_PIE_RULE_IDS) { + __otto_table_read(tbl, counter, &v); + v[1] = 0; + __otto_table_write(tbl, counter, &v); + } else { + __otto_table_read(tbl, counter / 2, &v); + v[counter % 2 ? 0 : 1] = 0; + __otto_table_write(tbl, counter / 2, &v); + } + + otto_table_release(tbl); } diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.h index fe98f161e33..4401949b28e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/stats.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef __RTL_OTTO_STATS_H -#define __RTL_OTTO_STATS_H +#ifndef _OTTO_STATS_H +#define _OTTO_STATS_H #include #include @@ -177,36 +177,48 @@ struct ethtool_rmon_stats; struct rtl838x_switch_priv; struct rtnl_link_stats64; -void rtldsa_stats_init(struct rtl838x_switch_priv *priv); -void rtldsa_stats_init_counters(struct rtl838x_switch_priv *priv); +void otto_stats_init(struct rtl838x_switch_priv *priv); +void otto_stats_init_counters(struct rtl838x_switch_priv *priv); +void otto_stats_838x_init(struct rtl838x_switch_priv *priv); +u64 otto_stats_931x_port_table_read(int port, unsigned int mib_size, + unsigned int mib_offset, bool is_pvt); -void rtldsa_get_strings(struct dsa_switch *ds, int port, u32 stringset, - u8 *data); -void rtldsa_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data); -int rtldsa_get_sset_count(struct dsa_switch *ds, int port, int sset); -void rtldsa_get_eth_phy_stats(struct dsa_switch *ds, int port, - struct ethtool_eth_phy_stats *phy_stats); -void rtldsa_get_eth_mac_stats(struct dsa_switch *ds, int port, - struct ethtool_eth_mac_stats *mac_stats); -void rtldsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port, - struct ethtool_eth_ctrl_stats *ctrl_stats); -void rtldsa_get_rmon_stats(struct dsa_switch *ds, int port, - struct ethtool_rmon_stats *rmon_stats, - const struct ethtool_rmon_hist_range **ranges); -void rtldsa_get_stats64(struct dsa_switch *ds, int port, - struct rtnl_link_stats64 *s); -void rtldsa_get_pause_stats(struct dsa_switch *ds, int port, - struct ethtool_pause_stats *pause_stats); +int otto_stats_packet_cntr_alloc(struct rtl838x_switch_priv *priv); +void otto_stats_packet_cntr_free(struct rtl838x_switch_priv *priv, int idx); +u32 otto_stats_838x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter); +void otto_stats_838x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter); +u32 otto_stats_839x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter); +void otto_stats_839x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter); +u32 otto_stats_930x_packet_cntr_read(struct rtl838x_switch_priv *priv, int counter); +void otto_stats_930x_packet_cntr_clear(struct rtl838x_switch_priv *priv, int counter); -void rtldsa_counters_lock_register(struct rtl838x_switch_priv *priv, int port) +void otto_stats_get_strings(struct dsa_switch *ds, int port, u32 stringset, + u8 *data); +void otto_stats_get_ethtool(struct dsa_switch *ds, int port, u64 *data); +int otto_stats_get_sset_count(struct dsa_switch *ds, int port, int sset); +void otto_stats_get_eth_phy(struct dsa_switch *ds, int port, + struct ethtool_eth_phy_stats *phy_stats); +void otto_stats_get_eth_mac(struct dsa_switch *ds, int port, + struct ethtool_eth_mac_stats *mac_stats); +void otto_stats_get_eth_ctrl(struct dsa_switch *ds, int port, + struct ethtool_eth_ctrl_stats *ctrl_stats); +void otto_stats_get_rmon(struct dsa_switch *ds, int port, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges); +void otto_stats_get64(struct dsa_switch *ds, int port, + struct rtnl_link_stats64 *s); +void otto_stats_get_pause(struct dsa_switch *ds, int port, + struct ethtool_pause_stats *pause_stats); + +void otto_stats_counters_lock_register(struct rtl838x_switch_priv *priv, int port) __acquires(&priv->ports[port].counters.lock); -void rtldsa_counters_unlock_register(struct rtl838x_switch_priv *priv, int port) +void otto_stats_counters_unlock_register(struct rtl838x_switch_priv *priv, int port) __releases(&priv->ports[port].counters.lock); -void rtldsa_counters_lock_table(struct rtl838x_switch_priv *priv, int port) +void otto_stats_counters_lock_table(struct rtl838x_switch_priv *priv, int port) __acquires(&priv->counters_lock); -void rtldsa_counters_unlock_table(struct rtl838x_switch_priv *priv, int port) +void otto_stats_counters_unlock_table(struct rtl838x_switch_priv *priv, int port) __releases(&priv->ports[port].counters.lock); -void rtldsa_update_counters_atomically(struct rtl838x_switch_priv *priv, - int port); +void otto_stats_update_counters_atomically(struct rtl838x_switch_priv *priv, + int port); -#endif /* __RTL_OTTO_STATS_H */ +#endif /* _OTTO_STATS_H */ diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/tc.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/tc.c index d5109d2a0f2..44caad74a3d 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/tc.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/tc.c @@ -481,7 +481,7 @@ static int otto_tc_configure_flower(struct rtl838x_switch_priv *priv, /* The only caller, otto_tc_pie_cls_flower_add(), is RTL930x-only, where * the PIE rule ID is also the LOG table counter ID: the counter is * implied by the rule and only known once pie_rule_add() has assigned - * the ID. That range is kept out of rtldsa_packet_cntr_alloc(), so the + * the ID. That range is kept out of otto_stats_packet_cntr_alloc(), so the * implied LOG entry cannot alias an L3 route PIE rule's counter. */ flow->rule.log_sel = true;