diff --git a/configs/aarch64_classic_defconfig b/configs/aarch64_classic_defconfig index 002b4672..c6aee739 100644 --- a/configs/aarch64_classic_defconfig +++ b/configs/aarch64_classic_defconfig @@ -21,6 +21,8 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/classic/post-build.sh" BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.6" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig" BR2_LINUX_KERNEL_DTS_SUPPORT=y diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 845225a5..d22d6415 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -22,6 +22,8 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/post-build.sh" BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.6" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig" BR2_LINUX_KERNEL_DTS_SUPPORT=y diff --git a/configs/x86_64_classic_defconfig b/configs/x86_64_classic_defconfig index aaccc074..0674900d 100644 --- a/configs/x86_64_classic_defconfig +++ b/configs/x86_64_classic_defconfig @@ -20,6 +20,8 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/classic/post-build.sh" BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.6" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig" BR2_LINUX_KERNEL_INSTALL_TARGET=y diff --git a/configs/x86_64_defconfig b/configs/x86_64_defconfig index a10c0009..7e563d41 100644 --- a/configs/x86_64_defconfig +++ b/configs/x86_64_defconfig @@ -21,6 +21,8 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/post-build.sh" BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.6" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig" BR2_LINUX_KERNEL_INSTALL_TARGET=y diff --git a/configs/x86_64_minimal_defconfig b/configs/x86_64_minimal_defconfig index d6cbed29..4582254e 100644 --- a/configs/x86_64_minimal_defconfig +++ b/configs/x86_64_minimal_defconfig @@ -21,6 +21,8 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/post-build.sh" BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh" BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.6" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig" BR2_LINUX_KERNEL_INSTALL_TARGET=y diff --git a/patches/linux/0001-eth-fwnode-Fall-back-to-NVMEM-provided-MAC-address-f.patch b/patches/linux/0001-eth-fwnode-Fall-back-to-NVMEM-provided-MAC-address-f.patch new file mode 100644 index 00000000..7a353682 --- /dev/null +++ b/patches/linux/0001-eth-fwnode-Fall-back-to-NVMEM-provided-MAC-address-f.patch @@ -0,0 +1,40 @@ +From 99e3fc4a7c6d31f5d0fdc7bb5c409c776c19012c Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 5 Oct 2023 16:09:25 +0200 +Subject: [PATCH 1/9] eth: fwnode: Fall back to NVMEM provided MAC address from + OF + +In the cases where the fwnode is an OF node, make use of any NVMEM +source of the interface's MAC address that might have been specified +in the device tree. + +Signed-off-by: Tobias Waldekranz +--- + net/ethernet/eth.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c +index 2edc8b796a4e..04900a41fab3 100644 +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -609,11 +609,17 @@ static int fwnode_get_mac_addr(struct fwnode_handle *fwnode, + */ + int fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr) + { ++ struct device_node *np; ++ + if (!fwnode_get_mac_addr(fwnode, "mac-address", addr) || + !fwnode_get_mac_addr(fwnode, "local-mac-address", addr) || + !fwnode_get_mac_addr(fwnode, "address", addr)) + return 0; + ++ np = to_of_node(fwnode); ++ if (np) ++ return of_get_mac_address_nvmem(np, addr); ++ + return -ENOENT; + } + EXPORT_SYMBOL(fwnode_get_mac_address); +-- +2.34.1 + diff --git a/patches/linux/0002-net-dsa-mv88e6xxx-Create-API-to-read-a-single-stat-c.patch b/patches/linux/0002-net-dsa-mv88e6xxx-Create-API-to-read-a-single-stat-c.patch new file mode 100644 index 00000000..acf20b52 --- /dev/null +++ b/patches/linux/0002-net-dsa-mv88e6xxx-Create-API-to-read-a-single-stat-c.patch @@ -0,0 +1,472 @@ +From 5ddc784a4c8803aff2c3fa3c6595e9d32933d4aa Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 5 Sep 2023 13:08:29 +0200 +Subject: [PATCH 2/9] net: dsa: mv88e6xxx: Create API to read a single stat + counter + +This change contains no functional change. We simply push the hardware +specific stats logic to a function reading a single counter, rather +than the whole set. + +This is a preparatory change for the upcoming standard ethtool +statistics support (i.e. "eth-mac", "eth-ctrl" etc.). + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 160 ++++++++++++++++++------------- + drivers/net/dsa/mv88e6xxx/chip.h | 27 +++--- + 2 files changed, 105 insertions(+), 82 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 7af2f08a62f1..1e944cf08233 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1082,7 +1082,7 @@ static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = { + }; + + static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, +- struct mv88e6xxx_hw_stat *s, ++ const struct mv88e6xxx_hw_stat *s, + int port, u16 bank1_select, + u16 histogram) + { +@@ -1265,59 +1265,82 @@ static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset) + return count; + } + +-static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port, +- uint64_t *data, int types, +- u16 bank1_select, u16 histogram) ++static int mv88e6095_stats_get_stat(struct mv88e6xxx_chip *chip, int port, ++ const struct mv88e6xxx_hw_stat *stat, ++ uint64_t *data) + { +- struct mv88e6xxx_hw_stat *stat; +- int i, j; ++ if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_PORT))) ++ return 0; + +- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { +- stat = &mv88e6xxx_hw_stats[i]; +- if (stat->type & types) { +- mv88e6xxx_reg_lock(chip); +- data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port, +- bank1_select, +- histogram); +- mv88e6xxx_reg_unlock(chip); ++ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0, ++ MV88E6XXX_G1_STATS_OP_HIST_RX_TX); ++ return 1; ++} + +- j++; +- } +- } +- return j; ++static int mv88e6250_stats_get_stat(struct mv88e6xxx_chip *chip, int port, ++ const struct mv88e6xxx_hw_stat *stat, ++ uint64_t *data) ++{ ++ if (!(stat->type & STATS_TYPE_BANK0)) ++ return 0; ++ ++ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0, ++ MV88E6XXX_G1_STATS_OP_HIST_RX_TX); ++ return 1; + } + +-static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port, +- uint64_t *data) ++static int mv88e6320_stats_get_stat(struct mv88e6xxx_chip *chip, int port, ++ const struct mv88e6xxx_hw_stat *stat, ++ uint64_t *data) + { +- return mv88e6xxx_stats_get_stats(chip, port, data, +- STATS_TYPE_BANK0 | STATS_TYPE_PORT, +- 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); ++ if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1))) ++ return 0; ++ ++ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, ++ MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9, ++ MV88E6XXX_G1_STATS_OP_HIST_RX_TX); ++ return 1; + } + +-static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port, +- uint64_t *data) ++static int mv88e6390_stats_get_stat(struct mv88e6xxx_chip *chip, int port, ++ const struct mv88e6xxx_hw_stat *stat, ++ uint64_t *data) + { +- return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0, +- 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); ++ if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1))) ++ return 0; ++ ++ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, ++ MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10, ++ 0); ++ return 1; + } + +-static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, +- uint64_t *data) ++static int mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port, ++ const struct mv88e6xxx_hw_stat *stat, ++ uint64_t *data) + { +- return mv88e6xxx_stats_get_stats(chip, port, data, +- STATS_TYPE_BANK0 | STATS_TYPE_BANK1, +- MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9, +- MV88E6XXX_G1_STATS_OP_HIST_RX_TX); ++ int ret = 0; ++ ++ if (chip->info->ops->stats_get_stat) { ++ mv88e6xxx_reg_lock(chip); ++ ret = chip->info->ops->stats_get_stat(chip, port, stat, data); ++ mv88e6xxx_reg_unlock(chip); ++ } ++ ++ return ret; + } + +-static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port, ++static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port, + uint64_t *data) + { +- return mv88e6xxx_stats_get_stats(chip, port, data, +- STATS_TYPE_BANK0 | STATS_TYPE_BANK1, +- MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10, +- 0); ++ struct mv88e6xxx_hw_stat *stat; ++ int i, j; ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { ++ stat = &mv88e6xxx_hw_stats[i]; ++ j += mv88e6xxx_stats_get_stat(chip, port, stat, &data[j]); ++ } ++ return j; + } + + static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port, +@@ -1333,10 +1356,9 @@ static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port, + static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, + uint64_t *data) + { +- int count = 0; ++ int count; + +- if (chip->info->ops->stats_get_stats) +- count = chip->info->ops->stats_get_stats(chip, port, data); ++ count = mv88e6xxx_stats_get_stats(chip, port, data); + + mv88e6xxx_reg_lock(chip); + if (chip->info->ops->serdes_get_stats) { +@@ -4196,7 +4218,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4234,7 +4256,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, + .serdes_power = mv88e6185_serdes_power, + .serdes_get_lane = mv88e6185_serdes_get_lane, +@@ -4277,7 +4299,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4323,7 +4345,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4366,7 +4388,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4415,7 +4437,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -4477,7 +4499,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4515,7 +4537,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4563,7 +4585,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4612,7 +4634,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4668,7 +4690,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4717,7 +4739,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4769,7 +4791,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -4820,7 +4842,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -4885,7 +4907,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -4948,7 +4970,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5014,7 +5036,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -5074,7 +5096,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6250_stats_get_sset_count, + .stats_get_strings = mv88e6250_stats_get_strings, +- .stats_get_stats = mv88e6250_stats_get_stats, ++ .stats_get_stat = mv88e6250_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6250_watchdog_ops, +@@ -5121,7 +5143,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5187,7 +5209,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6320_stats_get_stats, ++ .stats_get_stat = mv88e6320_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5234,7 +5256,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6320_stats_get_stats, ++ .stats_get_stat = mv88e6320_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5283,7 +5305,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5348,7 +5370,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -5394,7 +5416,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -5445,7 +5467,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6095_stats_get_sset_count, + .stats_get_strings = mv88e6095_stats_get_strings, +- .stats_get_stats = mv88e6095_stats_get_stats, ++ .stats_get_stat = mv88e6095_stats_get_stat, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6097_watchdog_ops, +@@ -5514,7 +5536,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5583,7 +5605,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + .set_cpu_port = mv88e6390_g1_set_cpu_port, + .set_egress_port = mv88e6390_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, +@@ -5652,7 +5674,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { + .stats_set_histogram = mv88e6390_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6320_stats_get_sset_count, + .stats_get_strings = mv88e6320_stats_get_strings, +- .stats_get_stats = mv88e6390_stats_get_stats, ++ .stats_get_stat = mv88e6390_stats_get_stat, + /* .set_cpu_port is missing because this family does not support a global + * CPU port, only per port CPU port which is set via + * .port_set_upstream_port method. +diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h +index 0ad34b2d8913..268c97cde8d8 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -318,6 +318,17 @@ struct mv88e6xxx_mst { + struct mv88e6xxx_stu_entry stu; + }; + ++#define STATS_TYPE_PORT BIT(0) ++#define STATS_TYPE_BANK0 BIT(1) ++#define STATS_TYPE_BANK1 BIT(2) ++ ++struct mv88e6xxx_hw_stat { ++ char string[ETH_GSTRING_LEN]; ++ size_t size; ++ int reg; ++ int type; ++}; ++ + struct mv88e6xxx_chip { + const struct mv88e6xxx_info *info; + +@@ -574,8 +585,9 @@ struct mv88e6xxx_ops { + /* Return the number of strings describing statistics */ + int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip); + int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data); +- int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, +- uint64_t *data); ++ int (*stats_get_stat)(struct mv88e6xxx_chip *chip, int port, ++ const struct mv88e6xxx_hw_stat *stat, ++ uint64_t *data); + int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); + int (*set_egress_port)(struct mv88e6xxx_chip *chip, + enum mv88e6xxx_egress_direction direction, +@@ -736,17 +748,6 @@ struct mv88e6xxx_ptp_ops { + u32 cc_mult_dem; + }; + +-#define STATS_TYPE_PORT BIT(0) +-#define STATS_TYPE_BANK0 BIT(1) +-#define STATS_TYPE_BANK1 BIT(2) +- +-struct mv88e6xxx_hw_stat { +- char string[ETH_GSTRING_LEN]; +- size_t size; +- int reg; +- int type; +-}; +- + static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip) + { + return chip->info->max_sid > 0 && +-- +2.34.1 + diff --git a/patches/linux/0003-net-dsa-mv88e6xxx-Give-each-hw-stat-an-ID.patch b/patches/linux/0003-net-dsa-mv88e6xxx-Give-each-hw-stat-an-ID.patch new file mode 100644 index 00000000..dc30e3c2 --- /dev/null +++ b/patches/linux/0003-net-dsa-mv88e6xxx-Give-each-hw-stat-an-ID.patch @@ -0,0 +1,196 @@ +From 63c14938bdaa1891386989aa46bee4571c1c0777 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 5 Sep 2023 21:10:15 +0200 +Subject: [PATCH 3/9] net: dsa: mv88e6xxx: Give each hw stat an ID + +With the upcoming standard counter group support, we are no longer +reading out the whole set of counters, but rather mapping a subset to +the requested group. + +Therefore, create an enum with an ID for each stat, such that +mv88e6xxx_hw_stats[] can be subscripted with a human-readable ID +corresponding to the counters name. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 141 +++++++++++++++++-------------- + 1 file changed, 78 insertions(+), 63 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 1e944cf08233..ea4fb0d3e628 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1019,68 +1019,83 @@ static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port) + return chip->info->ops->stats_snapshot(chip, port); + } + +-static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = { +- { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, }, +- { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, }, +- { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, }, +- { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, }, +- { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, }, +- { "in_pause", 4, 0x16, STATS_TYPE_BANK0, }, +- { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, }, +- { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, }, +- { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, }, +- { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, }, +- { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, }, +- { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, }, +- { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, }, +- { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, }, +- { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, }, +- { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, }, +- { "out_pause", 4, 0x15, STATS_TYPE_BANK0, }, +- { "excessive", 4, 0x11, STATS_TYPE_BANK0, }, +- { "collisions", 4, 0x1e, STATS_TYPE_BANK0, }, +- { "deferred", 4, 0x05, STATS_TYPE_BANK0, }, +- { "single", 4, 0x14, STATS_TYPE_BANK0, }, +- { "multiple", 4, 0x17, STATS_TYPE_BANK0, }, +- { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, }, +- { "late", 4, 0x1f, STATS_TYPE_BANK0, }, +- { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, }, +- { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, }, +- { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, }, +- { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, }, +- { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, }, +- { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, }, +- { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, }, +- { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, }, +- { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, }, +- { "in_discards", 4, 0x00, STATS_TYPE_BANK1, }, +- { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, }, +- { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, }, +- { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, }, +- { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, }, +- { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, }, +- { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, }, +- { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, }, +- { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, }, +- { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, }, +- { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, }, +- { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, }, +- { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, }, +- { "in_management", 4, 0x0f, STATS_TYPE_BANK1, }, +- { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, }, +- { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, }, +- { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, }, +- { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, }, +- { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, }, +- { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, }, +- { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, }, +- { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, }, +- { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, }, +- { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, }, +- { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, }, +- { "out_management", 4, 0x1f, STATS_TYPE_BANK1, }, ++#define MV88E6XXX_HW_STAT_MAPPER(_fn) \ ++ _fn(in_good_octets, 8, 0x00, STATS_TYPE_BANK0) \ ++ _fn(in_bad_octets, 4, 0x02, STATS_TYPE_BANK0) \ ++ _fn(in_unicast, 4, 0x04, STATS_TYPE_BANK0) \ ++ _fn(in_broadcasts, 4, 0x06, STATS_TYPE_BANK0) \ ++ _fn(in_multicasts, 4, 0x07, STATS_TYPE_BANK0) \ ++ _fn(in_pause, 4, 0x16, STATS_TYPE_BANK0) \ ++ _fn(in_undersize, 4, 0x18, STATS_TYPE_BANK0) \ ++ _fn(in_fragments, 4, 0x19, STATS_TYPE_BANK0) \ ++ _fn(in_oversize, 4, 0x1a, STATS_TYPE_BANK0) \ ++ _fn(in_jabber, 4, 0x1b, STATS_TYPE_BANK0) \ ++ _fn(in_rx_error, 4, 0x1c, STATS_TYPE_BANK0) \ ++ _fn(in_fcs_error, 4, 0x1d, STATS_TYPE_BANK0) \ ++ _fn(out_octets, 8, 0x0e, STATS_TYPE_BANK0) \ ++ _fn(out_unicast, 4, 0x10, STATS_TYPE_BANK0) \ ++ _fn(out_broadcasts, 4, 0x13, STATS_TYPE_BANK0) \ ++ _fn(out_multicasts, 4, 0x12, STATS_TYPE_BANK0) \ ++ _fn(out_pause, 4, 0x15, STATS_TYPE_BANK0) \ ++ _fn(excessive, 4, 0x11, STATS_TYPE_BANK0) \ ++ _fn(collisions, 4, 0x1e, STATS_TYPE_BANK0) \ ++ _fn(deferred, 4, 0x05, STATS_TYPE_BANK0) \ ++ _fn(single, 4, 0x14, STATS_TYPE_BANK0) \ ++ _fn(multiple, 4, 0x17, STATS_TYPE_BANK0) \ ++ _fn(out_fcs_error, 4, 0x03, STATS_TYPE_BANK0) \ ++ _fn(late, 4, 0x1f, STATS_TYPE_BANK0) \ ++ _fn(hist_64bytes, 4, 0x08, STATS_TYPE_BANK0) \ ++ _fn(hist_65_127bytes, 4, 0x09, STATS_TYPE_BANK0) \ ++ _fn(hist_128_255bytes, 4, 0x0a, STATS_TYPE_BANK0) \ ++ _fn(hist_256_511bytes, 4, 0x0b, STATS_TYPE_BANK0) \ ++ _fn(hist_512_1023bytes, 4, 0x0c, STATS_TYPE_BANK0) \ ++ _fn(hist_1024_max_bytes, 4, 0x0d, STATS_TYPE_BANK0) \ ++ _fn(sw_in_discards, 4, 0x10, STATS_TYPE_PORT) \ ++ _fn(sw_in_filtered, 2, 0x12, STATS_TYPE_PORT) \ ++ _fn(sw_out_filtered, 2, 0x13, STATS_TYPE_PORT) \ ++ _fn(in_discards, 4, 0x00, STATS_TYPE_BANK1) \ ++ _fn(in_filtered, 4, 0x01, STATS_TYPE_BANK1) \ ++ _fn(in_accepted, 4, 0x02, STATS_TYPE_BANK1) \ ++ _fn(in_bad_accepted, 4, 0x03, STATS_TYPE_BANK1) \ ++ _fn(in_good_avb_class_a, 4, 0x04, STATS_TYPE_BANK1) \ ++ _fn(in_good_avb_class_b, 4, 0x05, STATS_TYPE_BANK1) \ ++ _fn(in_bad_avb_class_a, 4, 0x06, STATS_TYPE_BANK1) \ ++ _fn(in_bad_avb_class_b, 4, 0x07, STATS_TYPE_BANK1) \ ++ _fn(tcam_counter_0, 4, 0x08, STATS_TYPE_BANK1) \ ++ _fn(tcam_counter_1, 4, 0x09, STATS_TYPE_BANK1) \ ++ _fn(tcam_counter_2, 4, 0x0a, STATS_TYPE_BANK1) \ ++ _fn(tcam_counter_3, 4, 0x0b, STATS_TYPE_BANK1) \ ++ _fn(in_da_unknown, 4, 0x0e, STATS_TYPE_BANK1) \ ++ _fn(in_management, 4, 0x0f, STATS_TYPE_BANK1) \ ++ _fn(out_queue_0, 4, 0x10, STATS_TYPE_BANK1) \ ++ _fn(out_queue_1, 4, 0x11, STATS_TYPE_BANK1) \ ++ _fn(out_queue_2, 4, 0x12, STATS_TYPE_BANK1) \ ++ _fn(out_queue_3, 4, 0x13, STATS_TYPE_BANK1) \ ++ _fn(out_queue_4, 4, 0x14, STATS_TYPE_BANK1) \ ++ _fn(out_queue_5, 4, 0x15, STATS_TYPE_BANK1) \ ++ _fn(out_queue_6, 4, 0x16, STATS_TYPE_BANK1) \ ++ _fn(out_queue_7, 4, 0x17, STATS_TYPE_BANK1) \ ++ _fn(out_cut_through, 4, 0x18, STATS_TYPE_BANK1) \ ++ _fn(out_octets_a, 4, 0x1a, STATS_TYPE_BANK1) \ ++ _fn(out_octets_b, 4, 0x1b, STATS_TYPE_BANK1) \ ++ _fn(out_management, 4, 0x1f, STATS_TYPE_BANK1) \ ++ /* */ ++ ++#define MV88E6XXX_HW_STAT_ENTRY(_string, _size, _reg, _type) \ ++ { #_string, _size, _reg, _type }, ++static const struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = { ++ MV88E6XXX_HW_STAT_MAPPER(MV88E6XXX_HW_STAT_ENTRY) + }; + ++#define MV88E6XXX_HW_STAT_ENUM(_string, _size, _reg, _type) \ ++ MV88E6XXX_HW_STAT_ID_ ## _string, ++enum mv88e6xxx_hw_stat_id { ++ MV88E6XXX_HW_STAT_MAPPER(MV88E6XXX_HW_STAT_ENUM) ++ ++ MV88E6XXX_HW_STAT_ID_MAX ++}; ++ ++ + static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, + const struct mv88e6xxx_hw_stat *s, + int port, u16 bank1_select, +@@ -1125,7 +1140,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, + static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip, + uint8_t *data, int types) + { +- struct mv88e6xxx_hw_stat *stat; ++ const struct mv88e6xxx_hw_stat *stat; + int i, j; + + for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { +@@ -1206,7 +1221,7 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, + static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip, + int types) + { +- struct mv88e6xxx_hw_stat *stat; ++ const struct mv88e6xxx_hw_stat *stat; + int i, j; + + for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { +@@ -1333,7 +1348,7 @@ static int mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port, + static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port, + uint64_t *data) + { +- struct mv88e6xxx_hw_stat *stat; ++ const struct mv88e6xxx_hw_stat *stat; + int i, j; + + for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { +-- +2.34.1 + diff --git a/patches/linux/0004-net-dsa-mv88e6xxx-Add-eth-mac-counter-group-support.patch b/patches/linux/0004-net-dsa-mv88e6xxx-Add-eth-mac-counter-group-support.patch new file mode 100644 index 00000000..5344c771 --- /dev/null +++ b/patches/linux/0004-net-dsa-mv88e6xxx-Add-eth-mac-counter-group-support.patch @@ -0,0 +1,86 @@ +From ffd5442fcbadcbd8733b9ac870d83d7561cca9fc Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 5 Sep 2023 21:15:52 +0200 +Subject: [PATCH 4/9] net: dsa: mv88e6xxx: Add "eth-mac" counter group support + +After this change, mv88e6xxx ports can report the applicable subset of +their counters using ethtool's standardized "eth-mac" counter group. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 52 ++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index ea4fb0d3e628..ec3a4717bc44 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1403,6 +1403,57 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, + + } + ++static void mv88e6xxx_get_eth_mac_stats(struct dsa_switch *ds, int port, ++ struct ethtool_eth_mac_stats *mac_stats) ++{ ++#define MV88E6XXX_ETH_MAC_STAT_MAPPING(_id, _member) \ ++ [MV88E6XXX_HW_STAT_ID_ ## _id] = \ ++ offsetof(struct ethtool_eth_mac_stats, stats._member) \ ++ ++ static const size_t stat_map[MV88E6XXX_HW_STAT_ID_MAX] = { ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(out_unicast, FramesTransmittedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(single, SingleCollisionFrames), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(multiple, MultipleCollisionFrames), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(in_unicast, FramesReceivedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(in_fcs_error, FrameCheckSequenceErrors), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(out_octets, OctetsTransmittedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(deferred, FramesWithDeferredXmissions), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(late, LateCollisions), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(in_good_octets, OctetsReceivedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(out_multicasts, MulticastFramesXmittedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(out_broadcasts, BroadcastFramesXmittedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(excessive, FramesWithExcessiveDeferral), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(in_multicasts, MulticastFramesReceivedOK), ++ MV88E6XXX_ETH_MAC_STAT_MAPPING(in_broadcasts, BroadcastFramesReceivedOK), ++ }; ++ struct mv88e6xxx_chip *chip = ds->priv; ++ const struct mv88e6xxx_hw_stat *stat; ++ enum mv88e6xxx_hw_stat_id id; ++ u64 *member; ++ int ret; ++ ++ mv88e6xxx_reg_lock(chip); ++ ret = mv88e6xxx_stats_snapshot(chip, port); ++ mv88e6xxx_reg_unlock(chip); ++ ++ if (ret < 0) ++ return; ++ ++ stat = mv88e6xxx_hw_stats; ++ for (id = 0; id < MV88E6XXX_HW_STAT_ID_MAX; id++, stat++) { ++ if (!stat_map[id]) ++ continue; ++ ++ member = (u64 *)(((char *)mac_stats) + stat_map[id]); ++ mv88e6xxx_stats_get_stat(chip, port, stat, member); ++ } ++ ++ mac_stats->stats.FramesTransmittedOK += mac_stats->stats.MulticastFramesXmittedOK; ++ mac_stats->stats.FramesTransmittedOK += mac_stats->stats.BroadcastFramesXmittedOK; ++ mac_stats->stats.FramesReceivedOK += mac_stats->stats.MulticastFramesReceivedOK; ++ mac_stats->stats.FramesReceivedOK += mac_stats->stats.BroadcastFramesReceivedOK; ++} ++ + static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port) + { + struct mv88e6xxx_chip *chip = ds->priv; +@@ -7160,6 +7211,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { + .phylink_mac_link_up = mv88e6xxx_mac_link_up, + .get_strings = mv88e6xxx_get_strings, + .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, ++ .get_eth_mac_stats = mv88e6xxx_get_eth_mac_stats, + .get_sset_count = mv88e6xxx_get_sset_count, + .port_enable = mv88e6xxx_port_enable, + .port_disable = mv88e6xxx_port_disable, +-- +2.34.1 + diff --git a/patches/linux/0005-net-dsa-mv88e6xxx-Add-rmon-counter-group-support.patch b/patches/linux/0005-net-dsa-mv88e6xxx-Add-rmon-counter-group-support.patch new file mode 100644 index 00000000..85842b70 --- /dev/null +++ b/patches/linux/0005-net-dsa-mv88e6xxx-Add-rmon-counter-group-support.patch @@ -0,0 +1,90 @@ +From 2cfafa598282efc980baf00b312a61032b9f5aa9 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 6 Sep 2023 10:55:53 +0200 +Subject: [PATCH 5/9] net: dsa: mv88e6xxx: Add "rmon" counter group support + +After this change, mv88e6xxx ports can report the applicable subset of +their counters using ethtool's standardized "rmon" counter group. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 56 ++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index ec3a4717bc44..eb5990cfc7d4 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1454,6 +1454,61 @@ static void mv88e6xxx_get_eth_mac_stats(struct dsa_switch *ds, int port, + mac_stats->stats.FramesReceivedOK += mac_stats->stats.BroadcastFramesReceivedOK; + } + ++static void mv88e6xxx_get_rmon_stats(struct dsa_switch *ds, int port, ++ struct ethtool_rmon_stats *rmon_stats, ++ const struct ethtool_rmon_hist_range **ranges) ++{ ++#define MV88E6XXX_RMON_STAT_MAPPING(_id, _member) \ ++ [MV88E6XXX_HW_STAT_ID_ ## _id] = \ ++ offsetof(struct ethtool_rmon_stats, stats._member) \ ++ ++ static const size_t stat_map[MV88E6XXX_HW_STAT_ID_MAX] = { ++ MV88E6XXX_RMON_STAT_MAPPING(in_undersize, undersize_pkts), ++ MV88E6XXX_RMON_STAT_MAPPING(in_oversize, oversize_pkts), ++ MV88E6XXX_RMON_STAT_MAPPING(in_fragments, fragments), ++ MV88E6XXX_RMON_STAT_MAPPING(in_jabber, jabbers), ++ MV88E6XXX_RMON_STAT_MAPPING(hist_64bytes, hist[0]), ++ MV88E6XXX_RMON_STAT_MAPPING(hist_65_127bytes, hist[1]), ++ MV88E6XXX_RMON_STAT_MAPPING(hist_128_255bytes, hist[2]), ++ MV88E6XXX_RMON_STAT_MAPPING(hist_256_511bytes, hist[3]), ++ MV88E6XXX_RMON_STAT_MAPPING(hist_512_1023bytes, hist[4]), ++ MV88E6XXX_RMON_STAT_MAPPING(hist_1024_max_bytes, hist[5]), ++ }; ++ static const struct ethtool_rmon_hist_range rmon_ranges[] = { ++ { 64, 64 }, ++ { 65, 127 }, ++ { 128, 255 }, ++ { 256, 511 }, ++ { 512, 1023 }, ++ { 1024, 65535 }, ++ {} ++ }; ++ struct mv88e6xxx_chip *chip = ds->priv; ++ const struct mv88e6xxx_hw_stat *stat; ++ enum mv88e6xxx_hw_stat_id id; ++ u64 *member; ++ int ret; ++ ++ mv88e6xxx_reg_lock(chip); ++ ret = mv88e6xxx_stats_snapshot(chip, port); ++ mv88e6xxx_reg_unlock(chip); ++ ++ if (ret < 0) ++ return; ++ ++ stat = mv88e6xxx_hw_stats; ++ for (id = 0; id < MV88E6XXX_HW_STAT_ID_MAX; id++, stat++) { ++ if (!stat_map[id]) ++ continue; ++ ++ member = (u64 *)(((char *)rmon_stats) + stat_map[id]); ++ mv88e6xxx_stats_get_stat(chip, port, stat, member); ++ } ++ ++ *ranges = rmon_ranges; ++} ++ ++ + static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port) + { + struct mv88e6xxx_chip *chip = ds->priv; +@@ -7212,6 +7267,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { + .get_strings = mv88e6xxx_get_strings, + .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, + .get_eth_mac_stats = mv88e6xxx_get_eth_mac_stats, ++ .get_rmon_stats = mv88e6xxx_get_rmon_stats, + .get_sset_count = mv88e6xxx_get_sset_count, + .port_enable = mv88e6xxx_port_enable, + .port_disable = mv88e6xxx_port_disable, +-- +2.34.1 + diff --git a/patches/linux/0006-arm64-dts-marvell-cp11x-Provide-clock-names-for-MDIO.patch b/patches/linux/0006-arm64-dts-marvell-cp11x-Provide-clock-names-for-MDIO.patch new file mode 100644 index 00000000..8918714a --- /dev/null +++ b/patches/linux/0006-arm64-dts-marvell-cp11x-Provide-clock-names-for-MDIO.patch @@ -0,0 +1,39 @@ +From 7abdce276172fe74e24fd30d204a75e388bbab6c Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 21 Sep 2023 11:10:26 +0200 +Subject: [PATCH 6/9] arm64: dts: marvell: cp11x: Provide clock names for MDIO + controllers + +This will let the driver figure out the rate of the core clk, such +that custom MDC frequencies can be supported. + +Signed-off-by: Tobias Waldekranz +--- + arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi +index 4ec1aae0a3a9..f268017498a9 100644 +--- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi +@@ -180,6 +180,8 @@ CP11X_LABEL(mdio): mdio@12a200 { + reg = <0x12a200 0x10>; + clocks = <&CP11X_LABEL(clk) 1 9>, <&CP11X_LABEL(clk) 1 5>, + <&CP11X_LABEL(clk) 1 6>, <&CP11X_LABEL(clk) 1 18>; ++ clock-names = "gop_clk", "mg_clk", ++ "mg_core_clk", "axi_clk"; + status = "disabled"; + }; + +@@ -190,6 +192,8 @@ CP11X_LABEL(xmdio): mdio@12a600 { + reg = <0x12a600 0x10>; + clocks = <&CP11X_LABEL(clk) 1 5>, + <&CP11X_LABEL(clk) 1 6>, <&CP11X_LABEL(clk) 1 18>; ++ clock-names = "mg_clk", ++ "mg_core_clk", "axi_clk"; + status = "disabled"; + }; + +-- +2.34.1 + diff --git a/patches/linux/0007-net-mvmdio-Avoid-excessive-sleeps-in-polled-mode.patch b/patches/linux/0007-net-mvmdio-Avoid-excessive-sleeps-in-polled-mode.patch new file mode 100644 index 00000000..faf0d31f --- /dev/null +++ b/patches/linux/0007-net-mvmdio-Avoid-excessive-sleeps-in-polled-mode.patch @@ -0,0 +1,119 @@ +From 8dc464b6506fbc038ccdae0a88936989fdf32117 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 19 Sep 2023 18:19:40 +0200 +Subject: [PATCH 7/9] net: mvmdio: Avoid excessive sleeps in polled mode + +Before this change, when operating in polled mode, i.e. no IRQ is +available, every individual C45 access would be hit with a 150us sleep +after the bus access. + +For example, on a board with a CN9130 SoC connected to an MV88X3310 +PHY, a single C45 read would take around 165us: + + root@infix:~$ mdio f212a600.mdio-mii mmd 4:1 bench 0xc003 + Performed 1000 reads in 165ms + +By replacing the long sleep with a tighter poll loop, we observe a 10x +increase in bus throughput: + + root@infix:~$ mdio f212a600.mdio-mii mmd 4:1 bench 0xc003 + Performed 1000 reads in 15ms + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/ethernet/marvell/mvmdio.c | 41 +++++++++++---------------- + 1 file changed, 16 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c +index 8662543ca5c8..37e20c2702b5 100644 +--- a/drivers/net/ethernet/marvell/mvmdio.c ++++ b/drivers/net/ethernet/marvell/mvmdio.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -58,11 +59,6 @@ + * - Armada 370 (Globalscale Mirabox): 41us to 43us (Polled) + */ + #define MVMDIO_SMI_TIMEOUT 1000 /* 1000us = 1ms */ +-#define MVMDIO_SMI_POLL_INTERVAL_MIN 45 +-#define MVMDIO_SMI_POLL_INTERVAL_MAX 55 +- +-#define MVMDIO_XSMI_POLL_INTERVAL_MIN 150 +-#define MVMDIO_XSMI_POLL_INTERVAL_MAX 160 + + struct orion_mdio_dev { + void __iomem *regs; +@@ -84,8 +80,6 @@ enum orion_mdio_bus_type { + + struct orion_mdio_ops { + int (*is_done)(struct orion_mdio_dev *); +- unsigned int poll_interval_min; +- unsigned int poll_interval_max; + }; + + /* Wait for the SMI unit to be ready for another operation +@@ -94,23 +88,24 @@ static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops, + struct mii_bus *bus) + { + struct orion_mdio_dev *dev = bus->priv; +- unsigned long timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT); +- unsigned long end = jiffies + timeout; +- int timedout = 0; ++ unsigned long end, timeout; ++ int done, timedout; + +- while (1) { +- if (ops->is_done(dev)) ++ if (dev->err_interrupt <= 0) { ++ if (!read_poll_timeout_atomic(ops->is_done, done, done, 2, ++ MVMDIO_SMI_TIMEOUT, false, dev)) + return 0; +- else if (timedout) +- break; +- +- if (dev->err_interrupt <= 0) { +- usleep_range(ops->poll_interval_min, +- ops->poll_interval_max); ++ } else { ++ timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT); ++ end = jiffies + timeout; ++ timedout = 0; ++ ++ while (1) { ++ if (ops->is_done(dev)) ++ return 0; ++ else if (timedout) ++ break; + +- if (time_is_before_jiffies(end)) +- ++timedout; +- } else { + /* wait_event_timeout does not guarantee a delay of at + * least one whole jiffie, so timeout must be no less + * than two. +@@ -135,8 +130,6 @@ static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev) + + static const struct orion_mdio_ops orion_mdio_smi_ops = { + .is_done = orion_mdio_smi_is_done, +- .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN, +- .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX, + }; + + static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id, +@@ -194,8 +187,6 @@ static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev) + + static const struct orion_mdio_ops orion_mdio_xsmi_ops = { + .is_done = orion_mdio_xsmi_is_done, +- .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN, +- .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX, + }; + + static int orion_mdio_xsmi_read_c45(struct mii_bus *bus, int mii_id, +-- +2.34.1 + diff --git a/patches/linux/0008-net-mvmdio-Support-setting-the-MDC-frequency-on-XSMI.patch b/patches/linux/0008-net-mvmdio-Support-setting-the-MDC-frequency-on-XSMI.patch new file mode 100644 index 00000000..7d6606e2 --- /dev/null +++ b/patches/linux/0008-net-mvmdio-Support-setting-the-MDC-frequency-on-XSMI.patch @@ -0,0 +1,88 @@ +From 1956176490d4eec3a889a38626326b375782a55a Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Thu, 21 Sep 2023 11:12:55 +0200 +Subject: [PATCH 8/9] net: mvmdio: Support setting the MDC frequency on XSMI + controllers + +Support the standard "clock-frequency" attribute to set the generated +MDC frequency. If not specified, the driver will leave the divisor +untouched. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/ethernet/marvell/mvmdio.c | 45 +++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c +index 37e20c2702b5..a33f63b7f773 100644 +--- a/drivers/net/ethernet/marvell/mvmdio.c ++++ b/drivers/net/ethernet/marvell/mvmdio.c +@@ -53,6 +53,13 @@ + #define MVMDIO_XSMI_BUSY BIT(30) + #define MVMDIO_XSMI_ADDR_REG 0x8 + ++#define MVMDIO_XSMI_CFG_REG 0xc ++#define MVMDIO_XSMI_CLKDIV_MASK 0x3 ++#define MVMDIO_XSMI_CLKDIV_256 0x0 ++#define MVMDIO_XSMI_CLKDIV_64 0x1 ++#define MVMDIO_XSMI_CLKDIV_32 0x2 ++#define MVMDIO_XSMI_CLKDIV_8 0x3 ++ + /* + * SMI Timeout measurements: + * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt) +@@ -237,6 +244,41 @@ static int orion_mdio_xsmi_write_c45(struct mii_bus *bus, int mii_id, + return 0; + } + ++static void orion_mdio_xsmi_set_mdc_freq(struct mii_bus *bus) ++{ ++ struct orion_mdio_dev *dev = bus->priv; ++ struct clk *mg_core; ++ u32 div, freq, cfg; ++ ++ if (device_property_read_u32(bus->parent, "clock-frequency", &freq)) ++ return; ++ ++ mg_core = of_clk_get_by_name(bus->parent->of_node, "mg_core_clk"); ++ if (IS_ERR(mg_core)) { ++ dev_err(bus->parent, ++ "MG core clock unknown, not changing MDC frequency"); ++ return; ++ } ++ ++ div = clk_get_rate(mg_core) / (freq + 1) + 1; ++ clk_put(mg_core); ++ ++ if (div <= 8) ++ div = MVMDIO_XSMI_CLKDIV_8; ++ else if (div <= 32) ++ div = MVMDIO_XSMI_CLKDIV_32; ++ else if (div <= 64) ++ div = MVMDIO_XSMI_CLKDIV_64; ++ else ++ div = MVMDIO_XSMI_CLKDIV_256; ++ ++ cfg = readl(dev->regs + MVMDIO_XSMI_CFG_REG); ++ cfg &= ~MVMDIO_XSMI_CLKDIV_MASK; ++ cfg |= div; ++ writel(cfg, dev->regs + MVMDIO_XSMI_CFG_REG); ++} ++ ++ + static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id) + { + struct orion_mdio_dev *dev = dev_id; +@@ -315,6 +357,9 @@ static int orion_mdio_probe(struct platform_device *pdev) + dev_warn(&pdev->dev, + "unsupported number of clocks, limiting to the first " + __stringify(ARRAY_SIZE(dev->clk)) "\n"); ++ ++ if (type == BUS_TYPE_XSMI) ++ orion_mdio_xsmi_set_mdc_freq(bus); + } else { + dev->clk[0] = clk_get(&pdev->dev, NULL); + if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) { +-- +2.34.1 + diff --git a/patches/linux/0009-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch b/patches/linux/0009-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch new file mode 100644 index 00000000..eef51999 --- /dev/null +++ b/patches/linux/0009-net-phy-marvell10g-Support-firmware-loading-on-88X33.patch @@ -0,0 +1,198 @@ +From 0de9c5dfc6395eb2e3066488638ac86de58b8068 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 19 Sep 2023 18:38:10 +0200 +Subject: [PATCH 9/9] net: phy: marvell10g: Support firmware loading on 88X3310 + +If a device is found waiting for firmware to be loaded into its RAM, +ask userspace for the binary and load it over XMDIO. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/phy/marvell10g.c | 143 +++++++++++++++++++++++++++++++++++ + 1 file changed, 143 insertions(+) + +diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c +index d4bb90d76881..155f439d9c1c 100644 +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -50,6 +51,13 @@ enum { + MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6, + MV_PMA_BOOT = 0xc050, + MV_PMA_BOOT_FATAL = BIT(0), ++ MV_PMA_BOOT_PRGS_MASK = 0x0006, ++ MV_PMA_BOOT_PRGS_INIT = 0x0000, ++ MV_PMA_BOOT_PRGS_WAIT = 0x0002, ++ MV_PMA_BOOT_PRGS_CSUM = 0x0004, ++ MV_PMA_BOOT_PRGS_JRAM = 0x0006, ++ MV_PMA_BOOT_APP_STARTED = BIT(4), ++ MV_PMA_BOOT_APP_LOADED = BIT(6), + + MV_PCS_BASE_T = 0x0000, + MV_PCS_BASE_R = 0x1000, +@@ -96,6 +104,12 @@ enum { + MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380, + MV_PCS_PORT_INFO_NPORTS_SHIFT = 7, + ++ /* Firmware downloading */ ++ MV_PCS_FW_ADDR_LOW = 0xd0f0, ++ MV_PCS_FW_ADDR_HIGH = 0xd0f1, ++ MV_PCS_FW_DATA = 0xd0f2, ++ MV_PCS_FW_CSUM = 0xd0f3, ++ + /* SerDes reinitialization 88E21X0 */ + MV_AN_21X0_SERDES_CTRL2 = 0x800f, + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13), +@@ -499,6 +513,129 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = { + .module_insert = mv3310_sfp_insert, + }; + ++struct mv3310_fw_hdr { ++ struct { ++ u32 size; ++ u32 addr; ++ u16 csum; ++ } __packed data; ++ ++ u8 flags; ++#define MV3310_FW_HDR_DATA_ONLY BIT(6) ++ ++ u8 port_skip; ++ u32 next_hdr; ++ u16 csum; ++ ++ u8 pad[14]; ++} __packed; ++ ++static int mv3310_load_fw_sect(struct phy_device *phydev, ++ const struct mv3310_fw_hdr *hdr, const u8 *data) ++{ ++ int err = 0; ++ size_t i; ++ u16 csum; ++ ++ dev_dbg(&phydev->mdio.dev, "Loading %u byte %s section at 0x%08x\n", ++ hdr->data.size, ++ (hdr->flags & MV3310_FW_HDR_DATA_ONLY) ? "data" : "executable", ++ hdr->data.addr); ++ ++ for (i = 0, csum = 0; i < hdr->data.size; i++) ++ csum += data[i]; ++ ++ if ((u16)~csum != hdr->data.csum) { ++ dev_err(&phydev->mdio.dev, "Corrupt section data\n"); ++ return -EINVAL; ++ } ++ ++ phy_lock_mdio_bus(phydev); ++ ++ /* Any existing checksum is cleared by a read */ ++ __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); ++ ++ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_LOW, hdr->data.addr & 0xffff); ++ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_HIGH, hdr->data.addr >> 16); ++ ++ for (i = 0; i < hdr->data.size; i += 2) { ++ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_DATA, ++ (data[i + 1] << 8) | data[i]); ++ } ++ ++ csum = __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); ++ if ((u16)~csum != hdr->data.csum) { ++ dev_err(&phydev->mdio.dev, "Download failed\n"); ++ err = -EIO; ++ goto unlock; ++ } ++ ++ if (hdr->flags & MV3310_FW_HDR_DATA_ONLY) ++ goto unlock; ++ ++ __phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT, 0, MV_PMA_BOOT_APP_LOADED); ++ mdelay(200); ++ if (!(__phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT) & MV_PMA_BOOT_APP_STARTED)) { ++ dev_err(&phydev->mdio.dev, "Application did not startup\n"); ++ err = -ENOSYS; ++ } ++ ++unlock: ++ phy_unlock_mdio_bus(phydev); ++ return err; ++} ++ ++static int mv3310_load_fw(struct phy_device *phydev) ++{ ++ const struct firmware *fw; ++ struct mv3310_fw_hdr hdr; ++ const u8 *sect; ++ size_t i; ++ u16 csum; ++ int err; ++ ++ /* dev_info(&phydev->mdio.dev, "Requ */ ++ err = request_firmware(&fw, "x33x0fw.hdr", &phydev->mdio.dev); ++ if (err) ++ return err; ++ ++ if (fw->size & 1) { ++ err = -EINVAL; ++ goto release; ++ } ++ ++ for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { ++ memcpy(&hdr, sect, sizeof(hdr)); ++ hdr.data.size = cpu_to_le32(hdr.data.size); ++ hdr.data.addr = cpu_to_le32(hdr.data.addr); ++ hdr.data.csum = cpu_to_le16(hdr.data.csum); ++ hdr.next_hdr = cpu_to_le32(hdr.next_hdr); ++ hdr.csum = cpu_to_le16(hdr.csum); ++ ++ for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++) ++ csum += sect[i]; ++ ++ if ((u16)~csum != hdr.csum) { ++ dev_err(&phydev->mdio.dev, "Corrupt section header\n"); ++ err = -EINVAL; ++ break; ++ } ++ ++ err = mv3310_load_fw_sect(phydev, &hdr, sect + sizeof(hdr)); ++ if (err) ++ break; ++ ++ if (!hdr.next_hdr) ++ break; ++ ++ sect = fw->data + hdr.next_hdr; ++ } ++ ++release: ++ release_firmware(fw); ++ return err; ++} ++ + static int mv3310_probe(struct phy_device *phydev) + { + const struct mv3310_chip *chip = to_mv3310_chip(phydev); +@@ -520,6 +657,12 @@ static int mv3310_probe(struct phy_device *phydev) + return -ENODEV; + } + ++ if ((ret & MV_PMA_BOOT_PRGS_MASK) == MV_PMA_BOOT_PRGS_WAIT) { ++ ret = mv3310_load_fw(phydev); ++ if (ret) ++ return ret; ++ } ++ + priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; +-- +2.34.1 + diff --git a/patches/linux/marvell-cn9130-crb-dts-fix.patch b/patches/linux/marvell-cn9130-crb-dts-fix.patch deleted file mode 100644 index c506312d..00000000 --- a/patches/linux/marvell-cn9130-crb-dts-fix.patch +++ /dev/null @@ -1,16 +0,0 @@ -Index: linux-6.1.32/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi -=================================================================== ---- linux-6.1.32.orig/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi -+++ linux-6.1.32/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi -@@ -284,6 +284,11 @@ - reg = <10>; - label = "cpu"; - ethernet = <&cp0_eth0>; -+ phy-mode = "10gbase-r"; -+ fixed-link { -+ speed = <10000>; -+ full-duplex; -+ }; - }; - - };