diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json index 1e23d6c8b2..f93e421270 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json @@ -1,80 +1,12 @@ -{ +{ "thermal_control_algorithm": { "run_at_boot_up": "true", "fan_speed_when_suspend": "60" }, "info_types": [ - { - "type": "fan_info" - }, - { - "type": "psu_info" - }, - { - "type": "chassis_info" - } + ], "policies": [ - { - "name": "any fan absence", - "conditions": [ - { - "type": "fan.any.absence" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "any psu absence", - "conditions": [ - { - "type": "psu.any.absence" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "any fan broken", - "conditions": [ - { - "type": "fan.any.fault" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "all fan and psu presence", - "conditions": [ - { - "type": "fan.all.presence" - }, - { - "type": "psu.all.presence" - }, - { - "type": "fan.all.good" - } - ], - "actions": [ - { - "type": "thermal.recover" - } - ] - } + ] -} \ No newline at end of file +} diff --git a/platform/mellanox/hw-management.mk b/platform/mellanox/hw-management.mk index e8484dc611..8c57fb6399 100644 --- a/platform/mellanox/hw-management.mk +++ b/platform/mellanox/hw-management.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2022 NVIDIA CORPORATION & AFFILIATES. +# Copyright (c) 2016-2023 NVIDIA CORPORATION & AFFILIATES. # Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ # # Mellanox HW Management -MLNX_HW_MANAGEMENT_VERSION = 7.0020.4301 +MLNX_HW_MANAGEMENT_VERSION = 7.0030.1011 export MLNX_HW_MANAGEMENT_VERSION diff --git a/platform/mellanox/hw-management/0002-Disable-hw-mgmt-on-SimX-platforms.patch b/platform/mellanox/hw-management/0002-Disable-hw-mgmt-on-SimX-platforms.patch index 61aab18090..a35a7e15ee 100644 --- a/platform/mellanox/hw-management/0002-Disable-hw-mgmt-on-SimX-platforms.patch +++ b/platform/mellanox/hw-management/0002-Disable-hw-mgmt-on-SimX-platforms.patch @@ -1,69 +1,103 @@ -From 422b64397f2f33b394d037820f0ceb4c09e3a725 Mon Sep 17 00:00:00 2001 -From: Alexander Allen -Date: Fri, 21 Jan 2022 16:47:19 +0000 -Subject: [PATCH 2/4] Disable hw-mgmt on SimX platforms +From eb3a76d7fbd0cbf2c370ecadd912960b094403d6 Mon Sep 17 00:00:00 2001 +From: Junchao-Mellanox +Date: Wed, 23 Aug 2023 14:33:44 +0800 +Subject: [PATCH] [PATCH 2/4] Disable hw-mgmt on SimX platforms --- - usr/usr/bin/hw-management-ready.sh | 11 +++++++---- - usr/usr/bin/hw-management.sh | 9 +++++++++ - 2 files changed, 16 insertions(+), 4 deletions(-) + usr/usr/bin/hw-management-ready.sh | 3 --- + usr/usr/bin/hw-management.sh | 21 +++++++++------------ + 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/usr/usr/bin/hw-management-ready.sh b/usr/usr/bin/hw-management-ready.sh -index 88672a8..7558c68 100755 +index 840bb0b..2f8547f 100755 --- a/usr/usr/bin/hw-management-ready.sh +++ b/usr/usr/bin/hw-management-ready.sh -@@ -51,17 +51,20 @@ if [ -d /var/run/hw-management ]; then - rm -fr /var/run/hw-management - fi - --case $board_type in --VMOD0014) -+if [ -z "$(lspci -vvv | grep SimX)" ]; then -+ case $board_type in -+ VMOD0014) - if [ ! -d /sys/devices/pci0000:00/0000:00:1f.0/NVSN2201:00/mlxreg-hotplug/hwmon ]; then - timeout 180 bash -c 'until [ -d /sys/devices/pci0000:00/0000:00:1f.0/NVSN2201:00/mlxreg-hotplug/hwmon ]; do sleep 0.2; done' - fi - ;; --*) -+ *) - if [ ! -d /sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon ]; then - timeout 180 bash -c 'until [ -d /sys/devices/platform/mlxplat/mlxreg-hotplug/hwmon ]; do sleep 0.2; done' - fi - ;; --esac -+ esac -+fi -+ - echo "Start Chassis HW management service." - logger -t hw-management -p daemon.notice "Start Chassis HW management service." +@@ -56,9 +56,6 @@ fi + # environment, TC need to be stopped. + if [ -n "$(lspci -vvv | grep SimX)" ]; then + case $product_sku in +- HI130|HI122) +- # Let the TC continue to run +- ;; + *) + if systemctl is-enabled --quiet hw-management-tc; then + echo "Stopping and disabling hw-management-tc on SimX" diff --git a/usr/usr/bin/hw-management.sh b/usr/usr/bin/hw-management.sh -index 1ee05b5..50d922b 100755 +index d3914d1..a60dba9 100755 --- a/usr/usr/bin/hw-management.sh +++ b/usr/usr/bin/hw-management.sh -@@ -2310,6 +2310,13 @@ do_chip_down() - /usr/bin/hw-management-thermal-events.sh change hotplug_asic down %S %p - } +@@ -545,7 +545,7 @@ function restore_i2c_bus_frequency_default() + function find_regio_sysfs_path_helper() + { + # Find hwmon{n} sysfs path for regio device +- case $board_type in ++ case $board_type in + VMOD0014) + for path in /sys/devices/pci0000:00/*/NVSN2201:*/mlxreg-io/hwmon/hwmon*; do + if [ -d "$path" ]; then +@@ -732,10 +732,10 @@ set_jtag_gpio() + gpio_tdi=$((gpiobase+jtag_tdi)) + echo $gpio_tdi > /sys/class/gpio/"$export_unexport" -+check_simx() -+{ -+ if [ -n "$(lspci -vvv | grep SimX)" ]; then -+ exit 0 +- # In SN2201 system. ++ # In SN2201 system. + # GPIO0 for CPU request to reset the Main Board I2C Mux. +- # GPIO1 for CPU control the CPU Board MUX when doing the ISP programming. +- # GPIO13 for CPU request Main Board JTAG control signal. ++ # GPIO1 for CPU control the CPU Board MUX when doing the ISP programming. ++ # GPIO13 for CPU request Main Board JTAG control signal. + if [ "$board_type" == "VMOD0014" ]; then + mux_reset=27 + jtag_mux_en=33 +@@ -1294,7 +1294,7 @@ connect_msn4700_msn4600_A1() + # msn4600C with removed A2D + connect_table+=(${msn4600C_A1_base_connect_table[@]}) + else +- # msn4700/msn4600 respin ++ # msn4700/msn4600 respin + connect_table+=(${msn4700_msn4600_A1_base_connect_table[@]}) + fi + add_cpu_board_to_connection_table +@@ -2144,7 +2144,7 @@ create_symbolic_links() + fi + if [ ! -d $thermal_path ]; then + mkdir $thermal_path +- fi + fi -+} -+ - __usage=" - Usage: $(basename "$0") [Options] + if [ ! -d $config_path ]; then + mkdir $config_path + fi +@@ -2341,7 +2341,7 @@ do_start() + check_system + set_asic_pci_id -@@ -2335,6 +2342,8 @@ Options: - force-reload Performs hw-management 'stop' and the 'start. - " - -+check_simx -+ - case $ACTION in - start) - if [ -d /var/run/hw-management ]; then +- asic_control=$(< $config_path/asic_control) ++ asic_control=$(< $config_path/asic_control) + if [[ $asic_control -ne 0 ]]; then + get_asic_bus + get_asic2_bus +@@ -2379,9 +2379,9 @@ do_start() + else + ln -sf /etc/sensors3.conf $config_path/lm_sensors_config + fi +- if [ -v "lm_sensors_labels" ] && [ -f $lm_sensors_labels ]; then ++ if [ -v "lm_sensors_labels" ] && [ -f $lm_sensors_labels ]; then + ln -sf $lm_sensors_labels $config_path/lm_sensors_labels +- fi ++ fi + if [ -v "thermal_control_config" ] && [ -f $thermal_control_config ]; then + ln -sf $thermal_control_config $config_path/tc_config.json + else +@@ -2528,9 +2528,6 @@ do_chip_up_down() + check_simx() + { + case $sku in +- HI130|HI122) +- # Let the initialization go through +- ;; + *) + if [ -n "$(lspci -vvv | grep SimX)" ]; then + exit 0 -- -2.20.1 +1.9.1 diff --git a/platform/mellanox/hw-management/hw-mgmt b/platform/mellanox/hw-management/hw-mgmt index c036e38b39..c7d4c31a21 160000 --- a/platform/mellanox/hw-management/hw-mgmt +++ b/platform/mellanox/hw-management/hw-mgmt @@ -1 +1 @@ -Subproject commit c036e38b3969e1b0eebbf36ef367bb14cd52bcfb +Subproject commit c7d4c31a212eec6a5543f554ffb2c63c5cb621e3 diff --git a/platform/mellanox/hw-management/hwmgmt_nonup_patches b/platform/mellanox/hw-management/hwmgmt_nonup_patches index 98c6161769..36d1d3bd8b 100644 --- a/platform/mellanox/hw-management/hwmgmt_nonup_patches +++ b/platform/mellanox/hw-management/hwmgmt_nonup_patches @@ -1,4 +1,10 @@ # Current non-upstream patch list, should be updated by hwmgmt_kernel_patches.py script +0049-leds-mlxreg-Provide-conversion-for-hardware-LED-colo.patch +0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch +0051-leds-mlxreg-Allow-multi-instantiation-of-same-name-L.patch +0098-1-Revert-mlxsw-Use-u16-for-local_port-field.patch +0098-2-Revert-mlxsw-i2c-Fix-chunk-size-setting.patch +0098-3-Revert-mlxsw-core_hwmon-Adjust-module-label-names.patch 0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch 0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch 0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch @@ -57,7 +63,107 @@ 0154-mlxsw-core-Export-line-card-API.patch 0155-mlxsw-minimal-Add-system-event-handler.patch 0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch -0163-platform-mellanox-Introduce-support-for-rack-manager.patch -0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch -0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch -0178-platform-mellanox-Introduce-support-for-next-generat.patch +0167-DS-lan743x-Add-support-for-fixed-phy.patch +0168-TMP-mlxsw-minimal-Ignore-error-reading-SPAD-register.patch +0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch +0172-DS-platform-mlx-platform-Add-SPI-path-for-rack-switc.patch +0174-DS-mlxsw-core_linecards-Skip-devlink-and-provisionin.patch +0181-Revert-Fix-out-of-bounds-memory-accesses-in-thermal.patch +0182-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch +0183-platform-mellanox-Split-initialization-procedure.patch +0184-platform-mellanox-Split-logic-in-init-and-exit-flow.patch +0185-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch +0187-platform_data-mlxreg-Add-field-with-mapped-resource-.patch +0188-i2c-mux-Add-register-map-based-mux-driver.patch +0189-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch +0190-i2c-mlxcpld-Modify-base-address-type.patch +0191-i2c-mlxcpld-Allow-to-configure-base-address-of-regis.patch +0192-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch +0193-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch +0194-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch +0195-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch +0196-platform-mellanox-Relocate-mlx-platform-driver.patch +0197-platform-mellanox-Add-initial-support-for-PCIe-based.patch +0198-platform-mellanox-Introduce-support-for-switches-bas.patch +0199-platform-mellanox-mlx-platform-Add-reset-and-extend-.patch +0200-dt-bindings-i2c-mellanox-i2c-mlxbf-convert-txt-to-YA.patch +0203-i2c-mlxbf-remove-IRQF_ONESHOT.patch +0206-i2c-mlxbf-add-multi-slave-functionality.patch +0207-i2c-mlxbf-support-BlueField-3-SoC.patch +0208-i2c-mlxbf-remove-device-tree-support.patch +0209-UBUNTU-SAUCE-i2c-mlxbf.c-Add-driver-version.patch +0210-platform-mellanox-Typo-fix-in-the-file-mlxbf-bootctl.patch +0211-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-boot.patch +0212-platform-mellanox-mlxbf-pmc-Add-Mellanox-BlueField-P.patch +0213-platform-mellanox-mlxbf-pmc-fix-kernel-doc-notation.patch +0214-platform-mellanox-mlxbf-pmc-Fix-an-IS_ERR-vs-NULL-bu.patch +0215-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-pmc.patch +0216-UBUNTU-SAUCE-mlxbf_pmc-Fix-references-to-sprintf.patch +0217-UBUNTU-SAUCE-mlxbf-pmc-Fix-error-when-reading-unprog.patch +0218-UBUNTU-SAUCE-platform-mellanox-Add-mlx-trio-driver.patch +0219-UBUNTU-SAUCE-platform-mellanox-mlxbf-tmfifo-Add-Blue.patch +0220-UBUNTU-SAUCE-pka-Add-pka-driver.patch +0221-UBUNTU-SAUCE-platform-mellanox-Add-mlxbf-livefish-dr.patch +0222-workqueue-Add-resource-managed-version-of-delayed-wo.patch +0223-devm-helpers-Fix-devm_delayed_work_autocancel-kernel.patch +0224-devm-helpers-Add-resource-managed-version-of-work-in.patch +0225-UBUNTU-SAUCE-Add-support-to-pwr-mlxbf.c-driver.patch +0226-Add-Mellanox-BlueField-Gigabit-Ethernet-driver.patch +0227-mlxbf_gige-clear-valid_polarity-upon-open.patch +0228-net-mellanox-mlxbf_gige-Replace-non-standard-interru.patch +0229-mlxbf_gige-increase-MDIO-polling-rate-to-5us.patch +0230-mlxbf_gige-remove-driver-managed-interrupt-counts.patch +0231-mlxbf_gige-remove-own-module-name-define-and-use-KBU.patch +0232-UBUNTU-SAUCE-mlxbf_gige-add-ethtool-mlxbf_gige_set_r.patch +0233-UBUNTU-SAUCE-Fix-OOB-handling-RX-packets-in-heavy-tr.patch +0234-UBUNTU-SAUCE-mlxbf_gige-add-validation-of-ACPI-table.patch +0235-UBUNTU-SAUCE-mlxbf_gige-set-driver-version-to-1.27.patch +0236-UBUNTU-SAUCE-mlxbf_gige-clear-MDIO-gateway-lock-afte.patch +0237-mlxbf_gige-compute-MDIO-period-based-on-i1clk.patch +0238-net-mlxbf_gige-Fix-an-IS_ERR-vs-NULL-bug-in-mlxbf_gi.patch +0239-UBUNTU-SAUCE-mlxbf_gige-add-MDIO-support-for-BlueFie.patch +0240-UBUNTU-SAUCE-mlxbf_gige-support-10M-100M-1G-speeds-o.patch +0241-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-Serdes-confi.patch +0242-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-ethtool_ops.patch +0243-UBUNTU-SAUCE-bluefield_edac-Add-SMC-support.patch +0244-UBUNTU-SAUCE-bluefield_edac-Update-license-and-copyr.patch +0245-gpio-mlxbf2-Convert-to-device-PM-ops.patch +0246-gpio-mlxbf2-Drop-wrong-use-of-ACPI_PTR.patch +0247-gpio-mlxbf2-Use-devm_platform_ioremap_resource.patch +0248-gpio-mlxbf2-Use-DEFINE_RES_MEM_NAMED-helper-macro.patch +0249-gpio-mlxbf2-Introduce-IRQ-support.patch +0250-UBUNTU-SAUCE-gpio-mlxbf2.c-support-driver-version.patch +0251-mmc-sdhci-of-dwcmshc-add-rockchip-platform-support.patch +0252-mmc-sdhci-of-dwcmshc-add-ACPI-support-for-BlueField-.patch +0253-mmc-sdhci-of-dwcmshc-fix-error-return-code-in-dwcmsh.patch +0254-mmc-sdhci-of-dwcmshc-set-MMC_CAP_WAIT_WHILE_BUSY.patch +0255-mmc-sdhci-of-dwcmshc-Re-enable-support-for-the-BlueF.patch +0256-UBUNTU-SAUCE-Support-BlueField-3-GPIO-driver.patch +0257-regmap-debugfs-Enable-writing-to-the-regmap-debugfs-.patch +0258-UBUNTU-SAUCE-mlx-bootctl-support-icm-carveout-eeprom.patch +0259-mmc-sdhci-of-dwcmshc-Enable-host-V4-support-for-Blue.patch +0260-UBUNTU-SAUCE-mlxbf-pka-Fix-kernel-crash-with-pka-TRN.patch +0261-mlxbf-ptm-power-and-thermal-management-debugfs-drive.patch +0262-UBUNTU-SAUCE-mlxbf-pmc-Fix-event-string-typo.patch +0263-UBUNTU-SAUCE-mlxbf-pmc-Support-for-BlueField-3-perfo.patch +0264-UBUNTU-SAUCE-platform-mellanox-Add-ctrl-message-and-.patch +0266-UBUNTU-SAUCE-mlxbf-pmc-Bug-fix-for-BlueField-3-count.patch +0267-UBUNTU-SAUCE-mmc-sdhci-of-dwcmshc-add-the-missing-de.patch +0268-DS-mlxsw-core_linecards-Disable-firmware-bundling-ma.patch +0269-platform-mellanox-Cosmetic-changes.patch +0270-platform-mellanox-Fix-order-in-exit-flow.patch +0271-platform-mellanox-Add-new-attributes.patch +0272-platform-mellanox-Change-register-offset-addresses.patch +0273-platform-mellanox-Add-field-upgrade-capability-regis.patch +0274-platform-mellanox-Modify-reset-causes-description.patch +0275-mlxsw-Use-u16-for-local_port-field-instead-of-u8.patch +0276-mlxsw-minimal-Change-type-for-local-port.patch +0277-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch +0278-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch +0279-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch +0280-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch +0281-platform-mellanox-mlx-platform-Modify-health-and-pow.patch +0282-platform-mellanox-mlx-platform-add-support-of-5th-CP.patch +0283-mlxsw-core_hwmon-Align-modules-label-name-assignment.patch +0284-platform-mellanox-mlx-platform-fix-CPLD4-PN-report.patch +9002-TMP-fix-for-fan-minimum-speed.patch diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py b/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py index 4b4eed5bbb..37da8d3a86 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. +# Copyright (c) 2020-2023 NVIDIA CORPORATION & AFFILIATES. # Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,10 +23,6 @@ from . import utils DEVICE_DATA = { 'x86_64-mlnx_msn2700-r0': { 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:30":13, "31:40":14 , "41:120":15}, - "unk_untrust": {"-127:25":13, "26:30":14 , "31:35":15, "36:120":16} - }, "capability": { "comex_amb": False } @@ -34,10 +30,6 @@ DEVICE_DATA = { }, 'x86_64-mlnx_msn2740-r0': { 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:120":13}, - "unk_untrust": {"-127:15":13, "16:25":14 , "26:30":15, "31:120":17}, - }, "capability": { "cpu_pack": False, "comex_amb": False @@ -46,10 +38,6 @@ DEVICE_DATA = { }, 'x86_64-mlnx_msn2100-r0': { 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:40":12, "41:120":13}, - "unk_untrust": {"-127:15":12, "16:25":13, "26:30":14, "31:35":15, "36:120":16} - }, "capability": { "cpu_pack": False, "comex_amb": False @@ -58,10 +46,6 @@ DEVICE_DATA = { }, 'x86_64-mlnx_msn2410-r0': { 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:30":13, "31:40":14 , "41:120":15}, - "unk_untrust": {"-127:25":13, "26:30":14 , "31:35":15, "36:120":16} - }, "capability": { "comex_amb": False } @@ -69,10 +53,6 @@ DEVICE_DATA = { }, 'x86_64-mlnx_msn2010-r0': { 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:120":12}, - "unk_untrust": {"-127:15":12, "16:20":13 , "21:30":14, "31:35":15, "36:120":16} - }, "capability": { "cpu_pack": False, "comex_amb": False @@ -80,75 +60,26 @@ DEVICE_DATA = { } }, 'x86_64-mlnx_msn3700-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:25":12, "26:40":13 , "41:120":14}, - "unk_untrust": {"-127:15":12, "16:30":13 , "31:35":14, "36:40":15, "41:120":16}, - } - } }, 'x86_64-mlnx_msn3700c-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:40":12, "41:120":13}, - "unk_untrust": {"-127:10":12, "11:20":13 , "21:30":14, "31:35":15, "36:120":16}, - } - } }, 'x86_64-mlnx_msn3800-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:30":12, "31:40":13 , "41:120":14}, - "unk_untrust": {"-127:0":12, "1:10":13 , "11:15":14, "16:20":15, "21:35":16, "36:120":17}, - } - } }, 'x86_64-mlnx_msn4700-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:35":14, "36:120":15}, - "unk_untrust": {"-127:35":14, "36:120":15}, - } - } }, 'x86_64-mlnx_msn4410-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:40":12, "41:120":13}, - "unk_untrust": {"-127:10":12, "11:20":13, "21:30":14, "31:35":15, "36:120":16}, - } - } }, 'x86_64-mlnx_msn3420-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:120":12}, - "unk_untrust": {"-127:25":12, "26:35":13, "36:40":14, "41:120":16}, - } - } }, 'x86_64-mlnx_msn4600c-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:40":12, "41:120":13}, - "unk_untrust": {"-127:5":12, "6:20":13, "21:30":14, "31:35":15, "36:40":16, "41:120":17}, - } - } }, 'x86_64-mlnx_msn4600-r0': { - 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:40": 12, "41:120": 13}, - "unk_untrust": {"-127:5": 12, "6:20": 13, "21:30": 14, "31:35": 15, "36:40": 16, "41:120": 17}, - } - } }, 'x86_64-nvidia_sn4800-r0': { 'thermal': { "capability": { "comex_amb": False - }, - 'cpu_threshold': (80, 95) # min=80, max=95 + } }, 'sfp': { 'max_port_per_line_card': 16 @@ -156,10 +87,6 @@ DEVICE_DATA = { }, 'x86_64-nvidia_sn2201-r0': { 'thermal': { - 'minimum_table': { - "unk_trust": {"-127:30": 13, "31:35": 14, "36:40": 15, "41:120": 16}, - "unk_untrust": {"-127:15": 13, "16:20": 14, "21:25": 15, "26:30": 16, "31:35": 17, "36:40": 18, "41:120": 19}, - }, "capability": { "comex_amb": False, "cpu_amb": True @@ -242,19 +169,6 @@ class DeviceDataManager: def get_sodimm_thermal_count(cls): return len(glob.glob('/run/hw-management/thermal/sodimm*_temp_input')) - @classmethod - @utils.read_only_cache() - def get_minimum_table(cls): - platform_data = DEVICE_DATA.get(cls.get_platform_name(), None) - if not platform_data: - return None - - thermal_data = platform_data.get('thermal', None) - if not thermal_data: - return None - - return thermal_data.get('minimum_table', None) - @classmethod @utils.read_only_cache() def get_thermal_capability(cls): @@ -285,23 +199,6 @@ class DeviceDataManager: return 0 return sfp_data.get('max_port_per_line_card', 0) - @classmethod - def is_cpu_thermal_control_supported(cls): - return cls.get_cpu_thermal_threshold() != (None, None) - - @classmethod - @utils.read_only_cache() - def get_cpu_thermal_threshold(cls): - platform_data = DEVICE_DATA.get(cls.get_platform_name(), None) - if not platform_data: - return None, None - - thermal_data = platform_data.get('thermal', None) - if not thermal_data: - return None, None - - return thermal_data.get('cpu_threshold', (None, None)) - @classmethod def get_bios_component(cls): from .component import ComponentBIOS, ComponentBIOSSN2201 diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py index c53abf6af9..9567c65ce6 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. +# Copyright (c) 2019-2023 NVIDIA CORPORATION & AFFILIATES. # Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -216,7 +216,7 @@ class PsuFan(MlnxFan): """ try: # Get PSU fan target speed according to current system cooling level - cooling_level = Thermal.get_cooling_level() + cooling_level = utils.read_int_from_file('/run/hw-management/thermal/cooling_cur_state', log_func=None) return int(self.PSU_FAN_SPEED[cooling_level], 16) except Exception: return self.get_speed() @@ -250,6 +250,7 @@ class PsuFan(MlnxFan): logger.log_error('Failed to set PSU FAN speed - {}'.format(e)) return False + class Fan(MlnxFan): """Platform-specific Fan class""" def __init__(self, fan_index, fan_drawer, position): diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py index 1a603e1831..4786b1f740 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. +# Copyright (c) 2019-2023 NVIDIA CORPORATION & AFFILIATES. # Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,12 +27,11 @@ try: from sonic_py_common.logger import Logger import copy import os - import glob from .device_data import DeviceDataManager from . import utils except ImportError as e: - raise ImportError (str(e) + "- required module not found") + raise ImportError(str(e) + "- required module not found") # Global logger class instance logger = Logger() @@ -143,23 +142,6 @@ THERMAL_NAMING_RULE = { } CHASSIS_THERMAL_SYSFS_FOLDER = '/run/hw-management/thermal' -COOLING_STATE_PATH = "/var/run/hw-management/thermal/cooling_cur_state" -THERMAL_ZONE_ASIC_PATH = '/var/run/hw-management/thermal/mlxsw/' -THERMAL_ZONE_FOLDER_WILDCARD = '/run/hw-management/thermal/mlxsw*' -THERMAL_ZONE_HIGH_THRESHOLD = 'temp_trip_high' -THERMAL_ZONE_HOT_THRESHOLD = 'temp_trip_hot' -THERMAL_ZONE_NORMAL_THRESHOLD = 'temp_trip_norm' -THERMAL_ZONE_MODE_FILE = 'thermal_zone_mode' -THERMAL_ZONE_POLICY_FILE = 'thermal_zone_policy' -THERMAL_ZONE_TEMP_FILE = 'thermal_zone_temp' -THERMAL_ZONE_HYSTERESIS = 5000 -MODULE_TEMP_FAULT_WILDCARRD = '/run/hw-management/thermal/module*_temp_fault' -MAX_AMBIENT_TEMP = 120 -# Min allowed cooling level when all thermal zones are in normal state -MIN_COOLING_LEVEL_FOR_NORMAL = 2 -# Min allowed cooling level when any thermal zone is in high state but no thermal zone is in emergency state -MIN_COOLING_LEVEL_FOR_HIGH = 4 -MAX_COOLING_LEVEL = 10 def initialize_chassis_thermals(): @@ -369,175 +351,6 @@ class Thermal(ThermalBase): """ return False - @classmethod - def set_thermal_algorithm_status(cls, status, force=True): - """ - Enable/disable kernel thermal algorithm. - When enable kernel thermal algorithm, kernel will adjust fan speed - according to thermal zones temperature. Please note that kernel will - only adjust fan speed when temperature across some "edge", e.g temperature - changes to exceed high threshold. - When disable kernel thermal algorithm, kernel no longer adjust fan speed. - We usually disable the algorithm when we want to set a fix speed. E.g, when - a fan unit is removed from system, we will set fan speed to 100% and disable - the algorithm to avoid it adjust the speed. - - Returns: - True if thermal algorithm status changed. - """ - if not force and cls.thermal_algorithm_status == status: - return False - - cls.thermal_algorithm_status = status - mode = "enabled" if status else "disabled" - policy = "step_wise" if status else "user_space" - for thermal_zone_folder in glob.iglob(THERMAL_ZONE_FOLDER_WILDCARD): - policy_file = os.path.join(thermal_zone_folder, THERMAL_ZONE_POLICY_FILE) - utils.write_file(policy_file, policy) - mode_file = os.path.join(thermal_zone_folder, THERMAL_ZONE_MODE_FILE) - utils.write_file(mode_file, mode) - - return True - - @classmethod - def get_min_allowed_cooling_level_by_thermal_zone(cls): - """Get min allowed cooling level according to thermal zone status: - 1. If temperature of all thermal zones is less than normal threshold, min allowed cooling level is - $MIN_COOLING_LEVEL_FOR_NORMAL = 2 - 2. If temperature of any thermal zone is greater than normal threshold, but no thermal zone temperature - is greater than high threshold, min allowed cooling level is $MIN_COOLING_LEVEL_FOR_HIGH = 4 - 3. Otherwise, there is no minimum allowed value and policy should not adjust cooling level - Returns: - int: minimum allowed cooling level - """ - min_allowed = MIN_COOLING_LEVEL_FOR_NORMAL - thermal_zone_present = False - try: - for thermal_zone_folder in glob.iglob(THERMAL_ZONE_FOLDER_WILDCARD): - current = utils.read_int_from_file(os.path.join(thermal_zone_folder, THERMAL_ZONE_TEMP_FILE)) - if current == 0: - # Temperature value 0 means that this thermal zone has no - # sensor and it should be ignored in this loop - continue - - thermal_zone_present = True - normal_thresh = utils.read_int_from_file(os.path.join(thermal_zone_folder, THERMAL_ZONE_NORMAL_THRESHOLD)) - if current < normal_thresh - THERMAL_ZONE_HYSTERESIS: - continue - - hot_thresh = utils.read_int_from_file(os.path.join(thermal_zone_folder, THERMAL_ZONE_HIGH_THRESHOLD)) - if current < hot_thresh - THERMAL_ZONE_HYSTERESIS: - min_allowed = MIN_COOLING_LEVEL_FOR_HIGH - else: - min_allowed = None - break - except Exception as e: - logger.log_error('Failed to get thermal zone status for {} - {}'.format(thermal_zone_folder, repr(e))) - return None - - return min_allowed if thermal_zone_present else None - - @classmethod - def check_module_temperature_trustable(cls): - for file_path in glob.iglob(MODULE_TEMP_FAULT_WILDCARRD): - fault = utils.read_int_from_file(file_path) - if fault != 0: - return 'untrust' - return 'trust' - - @classmethod - def get_min_amb_temperature(cls): - fan_ambient_path = os.path.join(CHASSIS_THERMAL_SYSFS_FOLDER, 'fan_amb') - port_ambient_path = os.path.join(CHASSIS_THERMAL_SYSFS_FOLDER, 'port_amb') - - try: - fan_ambient_temp = utils.read_int_from_file(fan_ambient_path, raise_exception=True) - port_ambient_temp = utils.read_int_from_file(port_ambient_path, raise_exception=True) - return fan_ambient_temp if fan_ambient_temp < port_ambient_temp else port_ambient_temp - except Exception as e: - # Can't get ambient temperature, return maximum - logger.log_error('Failed to get minimum ambient temperature, use pessimistic instead') - return MAX_AMBIENT_TEMP - - @classmethod - def set_cooling_level(cls, level): - """ - Change cooling level. The input level should be an integer value [1, 10]. - 1 means 10%, 2 means 20%, 10 means 100%. - """ - if cls.last_set_cooling_level != level: - utils.write_file(COOLING_STATE_PATH, level + 10, raise_exception=True) - cls.last_set_cooling_level = level - - @classmethod - def set_cooling_state(cls, state): - """Change cooling state. - Args: - state (int): cooling state - """ - if cls.last_set_cooling_state != state: - utils.write_file(COOLING_STATE_PATH, state, raise_exception=True) - cls.last_set_cooling_state = state - - @classmethod - def get_cooling_level(cls): - try: - return utils.read_int_from_file(COOLING_STATE_PATH, raise_exception=True) - except (ValueError, IOError) as e: - raise RuntimeError("Failed to get cooling level - {}".format(e)) - - @classmethod - def set_expect_cooling_level(cls, expect_value): - """During thermal policy running, cache the expect cooling level generated by policies. The max expect - cooling level will be committed to hardware. - Args: - expect_value (int): Expected cooling level value - """ - if cls.expect_cooling_level is None or cls.expect_cooling_level < expect_value: - cls.expect_cooling_level = int(expect_value) - - @classmethod - def commit_cooling_level(cls, thermal_info_dict): - """Commit cooling level to hardware. This will affect system fan and PSU fan speed. - Args: - thermal_info_dict (dict): Thermal information dictionary - """ - if cls.expect_cooling_level is not None: - cls.set_cooling_level(cls.expect_cooling_level) - - if cls.expect_cooling_state is not None: - cls.set_cooling_state(cls.expect_cooling_state) - elif cls.expect_cooling_level is not None: - cls.set_cooling_state(cls.expect_cooling_level) - - cls.expect_cooling_level = None - # We need to set system fan speed here because kernel will automaticlly adjust fan speed according to cooling level and cooling state - - # Commit PSU fan speed with current state - from .thermal_infos import ChassisInfo - if ChassisInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ChassisInfo.INFO_NAME], ChassisInfo): - cooling_level = cls.get_cooling_level() - if cls.last_set_psu_cooling_level == cooling_level: - return - speed = cooling_level * 10 - chassis = thermal_info_dict[ChassisInfo.INFO_NAME].get_chassis() - for psu in chassis.get_all_psus(): - for psu_fan in psu.get_all_fans(): - psu_fan.set_speed(speed) - cls.last_set_psu_cooling_level = cooling_level - - @classmethod - def monitor_asic_themal_zone(cls): - """This is a protection for asic thermal zone, if asic temperature is greater than hot threshold + THERMAL_ZONE_HYSTERESIS, - and if cooling state is not MAX, we need enforce the cooling state to MAX - """ - asic_temp = utils.read_int_from_file(os.path.join(THERMAL_ZONE_ASIC_PATH, THERMAL_ZONE_TEMP_FILE), raise_exception=True) - hot_thresh = utils.read_int_from_file(os.path.join(THERMAL_ZONE_ASIC_PATH, THERMAL_ZONE_HOT_THRESHOLD), raise_exception=True) - if asic_temp >= hot_thresh + THERMAL_ZONE_HYSTERESIS: - cls.expect_cooling_state = MAX_COOLING_LEVEL - else: - cls.expect_cooling_state = None - class RemovableThermal(Thermal): def __init__(self, name, temp_file, high_th_file, high_crit_th_file, position, presence_cb): diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py deleted file mode 100644 index bada4476d4..0000000000 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py +++ /dev/null @@ -1,111 +0,0 @@ -# -# Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. -# Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase -from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object -from .thermal import Thermal - - -class SetFanSpeedAction(ThermalPolicyActionBase): - """ - Base thermal action class to set speed for fans - """ - # JSON field definition - JSON_FIELD_SPEED = 'speed' - - def __init__(self): - """ - Constructor of SetFanSpeedAction which actually do nothing. - """ - self.speed = None - - def load_from_json(self, json_obj): - """ - Construct SetFanSpeedAction via JSON. JSON example: - { - "type": "fan.all.set_speed" - "speed": "100" - } - :param json_obj: A JSON object representing a SetFanSpeedAction action. - :return: - """ - if SetFanSpeedAction.JSON_FIELD_SPEED in json_obj: - speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) - if speed < 0 or speed > 100: - raise ValueError('SetFanSpeedAction invalid speed value {} in JSON policy file, valid value should be [0, 100]'. - format(speed)) - self.speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) - else: - raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. - format(SetFanSpeedAction.JSON_FIELD_SPEED)) - - -@thermal_json_object('fan.all.set_speed') -class SetAllFanSpeedAction(SetFanSpeedAction): - """ - Action to set speed for all fans - """ - def execute(self, thermal_info_dict): - """ - Set speed for all fans - :param thermal_info_dict: A dictionary stores all thermal information. - :return: - """ - Thermal.set_expect_cooling_level(self.speed / 10) - - -@thermal_json_object('thermal.recover') -class ThermalRecoverAction(ThermalPolicyActionBase): - UNKNOWN_SKU_COOLING_LEVEL = 6 - - def execute(self, thermal_info_dict): - from .device_data import DeviceDataManager - from .thermal import MAX_COOLING_LEVEL, MIN_COOLING_LEVEL_FOR_HIGH, logger - Thermal.monitor_asic_themal_zone() - - # Calculate dynamic minimum cooling level - dynamic_min_cooling_level = None - minimum_table = DeviceDataManager.get_minimum_table() - if not minimum_table: - # If there is no minimum_table defined, set dynamic_min_cooling_level to default value - dynamic_min_cooling_level = ThermalRecoverAction.UNKNOWN_SKU_COOLING_LEVEL - else: - trust_state = Thermal.check_module_temperature_trustable() - temperature = Thermal.get_min_amb_temperature() - temperature = int(temperature / 1000) - minimum_table = minimum_table['unk_{}'.format(trust_state)] - - for key, cooling_level in minimum_table.items(): - temp_range = key.split(':') - temp_min = int(temp_range[0].strip()) - temp_max = int(temp_range[1].strip()) - if temp_min <= temperature <= temp_max: - dynamic_min_cooling_level = cooling_level - 10 - break - - if not dynamic_min_cooling_level: - # Should not go to this branch, just in case - logger.log_error('Failed to get dynamic minimum cooling level') - dynamic_min_cooling_level = MAX_COOLING_LEVEL - - if Thermal.last_set_cooling_level is not None and dynamic_min_cooling_level > Thermal.last_set_cooling_level and dynamic_min_cooling_level >= MIN_COOLING_LEVEL_FOR_HIGH: - # No need to check thermal zone as dynamic_min_cooling_level is greater than previous value and MIN_COOLING_LEVEL_FOR_HIGH - Thermal.set_expect_cooling_level(dynamic_min_cooling_level) - else: - min_cooling_level_by_tz = Thermal.get_min_allowed_cooling_level_by_thermal_zone() - if min_cooling_level_by_tz is not None: - cooling_level = max(dynamic_min_cooling_level, min_cooling_level_by_tz) - Thermal.set_expect_cooling_level(cooling_level) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py deleted file mode 100644 index 24a22c4101..0000000000 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py +++ /dev/null @@ -1,92 +0,0 @@ -# -# Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. -# Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase -from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object - - -class FanCondition(ThermalPolicyConditionBase): - def get_fan_info(self, thermal_info_dict): - from .thermal_infos import FanInfo - if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): - return thermal_info_dict[FanInfo.INFO_NAME] - else: - return None - - -@thermal_json_object('fan.any.absence') -class AnyFanAbsenceCondition(FanCondition): - def is_match(self, thermal_info_dict): - fan_info_obj = self.get_fan_info(thermal_info_dict) - return len(fan_info_obj.get_absence_fans()) > 0 if fan_info_obj else False - - -@thermal_json_object('fan.all.absence') -class AllFanAbsenceCondition(FanCondition): - def is_match(self, thermal_info_dict): - fan_info_obj = self.get_fan_info(thermal_info_dict) - return len(fan_info_obj.get_presence_fans()) == 0 if fan_info_obj else False - - -@thermal_json_object('fan.all.presence') -class AllFanPresenceCondition(FanCondition): - def is_match(self, thermal_info_dict): - fan_info_obj = self.get_fan_info(thermal_info_dict) - return len(fan_info_obj.get_absence_fans()) == 0 if fan_info_obj else False - - -@thermal_json_object('fan.any.fault') -class AnyFanFaultCondition(FanCondition): - def is_match(self, thermal_info_dict): - fan_info_obj = self.get_fan_info(thermal_info_dict) - return len(fan_info_obj.get_fault_fans()) > 0 if fan_info_obj else False - - -@thermal_json_object('fan.all.good') -class AllFanGoodCondition(FanCondition): - def is_match(self, thermal_info_dict): - fan_info_obj = self.get_fan_info(thermal_info_dict) - return len(fan_info_obj.get_fault_fans()) == 0 if fan_info_obj else False - - -class PsuCondition(ThermalPolicyConditionBase): - def get_psu_info(self, thermal_info_dict): - from .thermal_infos import PsuInfo - if PsuInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[PsuInfo.INFO_NAME], PsuInfo): - return thermal_info_dict[PsuInfo.INFO_NAME] - else: - return None - - -@thermal_json_object('psu.any.absence') -class AnyPsuAbsenceCondition(PsuCondition): - def is_match(self, thermal_info_dict): - psu_info_obj = self.get_psu_info(thermal_info_dict) - return len(psu_info_obj.get_absence_psus()) > 0 if psu_info_obj else False - - -@thermal_json_object('psu.all.absence') -class AllPsuAbsenceCondition(PsuCondition): - def is_match(self, thermal_info_dict): - psu_info_obj = self.get_psu_info(thermal_info_dict) - return len(psu_info_obj.get_presence_psus()) == 0 if psu_info_obj else False - - -@thermal_json_object('psu.all.presence') -class AllPsuPresenceCondition(PsuCondition): - def is_match(self, thermal_info_dict): - psu_info_obj = self.get_psu_info(thermal_info_dict) - return len(psu_info_obj.get_absence_psus()) == 0 if psu_info_obj else False diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py deleted file mode 100644 index f44afe735a..0000000000 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py +++ /dev/null @@ -1,171 +0,0 @@ -# -# Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES. -# Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase -from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object - - -@thermal_json_object('fan_info') -class FanInfo(ThermalPolicyInfoBase): - """ - Fan information needed by thermal policy - """ - - # Fan information name - INFO_NAME = 'fan_info' - - def __init__(self): - self._absence_fans = set() - self._presence_fans = set() - self._fault_fans = set() - self._status_changed = False - - def collect(self, chassis): - """ - Collect absence and presence fans. - :param chassis: The chassis object - :return: - """ - self._status_changed = False - for fan_drawer in chassis.get_all_fan_drawers(): - for fan in fan_drawer.get_all_fans(): - presence = fan.get_presence() - status = fan.get_status() - if presence and fan not in self._presence_fans: - self._presence_fans.add(fan) - self._status_changed = True - if fan in self._absence_fans: - self._absence_fans.remove(fan) - elif not presence and fan not in self._absence_fans: - self._absence_fans.add(fan) - self._status_changed = True - if fan in self._presence_fans: - self._presence_fans.remove(fan) - - if not status and fan not in self._fault_fans: - self._fault_fans.add(fan) - self._status_changed = True - elif status and fan in self._fault_fans: - self._fault_fans.remove(fan) - self._status_changed = True - - - def get_absence_fans(self): - """ - Retrieves absence fans - :return: A set of absence fans - """ - return self._absence_fans - - def get_presence_fans(self): - """ - Retrieves presence fans - :return: A set of presence fans - """ - return self._presence_fans - - def get_fault_fans(self): - """ - Retrieves fault fans - :return: A set of fault fans - """ - return self._fault_fans - - def is_status_changed(self): - """ - Retrieves if the status of fan information changed - :return: True if status changed else False - """ - return self._status_changed - - -@thermal_json_object('psu_info') -class PsuInfo(ThermalPolicyInfoBase): - """ - PSU information needed by thermal policy - """ - INFO_NAME = 'psu_info' - - def __init__(self): - self._absence_psus = set() - self._presence_psus = set() - self._status_changed = False - - def collect(self, chassis): - """ - Collect absence and presence PSUs. - :param chassis: The chassis object - :return: - """ - self._status_changed = False - for psu in chassis.get_all_psus(): - if psu.get_presence() and psu not in self._presence_psus: - self._presence_psus.add(psu) - self._status_changed = True - if psu in self._absence_psus: - self._absence_psus.remove(psu) - elif (not psu.get_presence()) and psu not in self._absence_psus: - self._absence_psus.add(psu) - self._status_changed = True - if psu in self._presence_psus: - self._presence_psus.remove(psu) - - def get_absence_psus(self): - """ - Retrieves presence PSUs - :return: A set of absence PSUs - """ - return self._absence_psus - - def get_presence_psus(self): - """ - Retrieves presence PSUs - :return: A set of presence fans - """ - return self._presence_psus - - def is_status_changed(self): - """ - Retrieves if the status of PSU information changed - :return: True if status changed else False - """ - return self._status_changed - - -@thermal_json_object('chassis_info') -class ChassisInfo(ThermalPolicyInfoBase): - """ - Chassis information needed by thermal policy - """ - INFO_NAME = 'chassis_info' - - def __init__(self): - self._chassis = None - - def collect(self, chassis): - """ - Collect platform chassis. - :param chassis: The chassis object - :return: - """ - self._chassis = chassis - - def get_chassis(self): - """ - Retrieves platform chassis object - :return: A platform chassis object. - """ - return self._chassis diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py index dcdd25e906..dd3d794d85 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. +# Copyright (c) 2020-2023 NVIDIA CORPORATION & AFFILIATES. # Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,81 +15,9 @@ # limitations under the License. # from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase -from .cpu_thermal_control import CPUThermalControl -from .device_data import DeviceDataManager -from .thermal_actions import * -from .thermal_conditions import * -from .thermal_infos import * -from .thermal import logger, MAX_COOLING_LEVEL, Thermal class ThermalManager(ThermalManagerBase): - cpu_thermal_control = None - - @classmethod - def start_thermal_control_algorithm(cls): - """ - Start thermal control algorithm - - Returns: - bool: True if set success, False if fail. - """ - Thermal.set_thermal_algorithm_status(True) - - @classmethod - def stop_thermal_control_algorithm(cls): - """ - Stop thermal control algorithm - - Returns: - bool: True if set success, False if fail. - """ - Thermal.set_thermal_algorithm_status(False) - - @classmethod - def start_cpu_thermal_control_algoritm(cls): - if cls.cpu_thermal_control: - return - - if not DeviceDataManager.is_cpu_thermal_control_supported(): - return - - cls.cpu_thermal_control = CPUThermalControl() - cls.cpu_thermal_control.task_run() - - @classmethod - def stop_cpu_thermal_control_algoritm(cls): - if cls.cpu_thermal_control: - cls.cpu_thermal_control.task_stop() - cls.cpu_thermal_control = None - @classmethod def run_policy(cls, chassis): - if cls._running: - cls.start_cpu_thermal_control_algoritm() - else: - cls.stop_cpu_thermal_control_algoritm() - - if not cls._policy_dict: - return - - try: - cls._collect_thermal_information(chassis) - except Exception as e: - logger.log_error('Failed to collect thermal information {}'.format(repr(e))) - Thermal.set_expect_cooling_level(MAX_COOLING_LEVEL) - Thermal.commit_cooling_level(cls._thermal_info_dict) - return - - for policy in cls._policy_dict.values(): - if not cls._running: - return - try: - if policy.is_match(cls._thermal_info_dict): - policy.do_action(cls._thermal_info_dict) - except Exception as e: - logger.log_error('Failed to run thermal policy {} - {}'.format(policy.name, repr(e))) - # In case there is an exception, we put cooling level to max value - Thermal.set_expect_cooling_level(MAX_COOLING_LEVEL) - - Thermal.commit_cooling_level(cls._thermal_info_dict) + pass diff --git a/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json b/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json deleted file mode 100644 index c19787aa26..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "any fan absence", - "conditions": [ - { - "type": "fan.any.absence" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - }, - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] -} diff --git a/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json b/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json deleted file mode 100644 index c25d84762e..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "any fan absence", - "conditions": [ - { - "type": "fan.any.absence" - }, - { - "type": "fan.any.absence" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] -} diff --git a/platform/mellanox/mlnx-platform-api/tests/empty_action.json b/platform/mellanox/mlnx-platform-api/tests/empty_action.json deleted file mode 100644 index b1051b5a6f..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/empty_action.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "any fan absence", - "conditions": [ - { - "type": "fan.any.absence" - } - ], - "actions": [ - ] -} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/empty_condition.json b/platform/mellanox/mlnx-platform-api/tests/empty_condition.json deleted file mode 100644 index e7a5884592..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/empty_condition.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "any fan absence", - "conditions": [ - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] -} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json b/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json deleted file mode 100644 index 9efe773a9b..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "thermal_control_algorithm": { - "run_at_boot_up": "false", - "fan_speed_when_suspend": "60" - }, - "info_types": [ - { - "type": "fan_info" - }, - { - "type": "psu_info" - }, - { - "type": "chassis_info" - } - ], - "policies": [ - { - "name": "all fan and psu presence", - "conditions": [ - { - "type": "fan.all.presence" - }, - { - "type": "psu.all.presence" - } - ], - "actions": [ - { - "type": "thermal.recover" - }, - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "any psu absence", - "conditions": [ - { - "type": "psu.any.absence" - } - ], - "actions": [ - { - "type": "thermal.recover" - }, - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "all fan and psu presence 1", - "conditions": [ - { - "type": "fan.all.presence" - }, - { - "type": "psu.all.presence" - } - ], - "actions": [ - { - "type": "thermal.recover" - } - ] - } - ] -} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/test_cpu_thermal_control.py b/platform/mellanox/mlnx-platform-api/tests/test_cpu_thermal_control.py deleted file mode 100644 index 8970e659c0..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/test_cpu_thermal_control.py +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. -# Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -############################################################################# -# Mellanox -# -# Module contains an implementation of SONiC Platform Base API and -# provides the Chassis information which are available in the platform -# -############################################################################# - -import glob -import os -import pytest -import sys -if sys.version_info.major == 3: - from unittest import mock -else: - import mock - -test_path = os.path.dirname(os.path.abspath(__file__)) -modules_path = os.path.dirname(test_path) -sys.path.insert(0, modules_path) - -from sonic_platform.cpu_thermal_control import CPUThermalControl - - -class TestCPUThermalControl: - @mock.patch('sonic_platform.device_data.DeviceDataManager.get_cpu_thermal_threshold', mock.MagicMock(return_value=(85, 95))) - @mock.patch('sonic_platform.utils.read_int_from_file') - @mock.patch('sonic_platform.utils.write_file') - def test_run(self, mock_write_file, mock_read_file): - instance = CPUThermalControl() - file_content = { - CPUThermalControl.CPU_COOLING_STATE: 5, - CPUThermalControl.CPU_TEMP_FILE: instance.temp_high + 1 - } - - def read_file(file_path, **kwargs): - return file_content[file_path] - - mock_read_file.side_effect = read_file - # Test current temp is higher than high threshold - instance.run(0) - mock_write_file.assert_called_with(CPUThermalControl.CPU_COOLING_STATE, CPUThermalControl.MAX_COOLING_STATE, log_func=None) - - # Test current temp is lower than low threshold - file_content[CPUThermalControl.CPU_TEMP_FILE] = instance.temp_low - 1 - instance.run(0) - mock_write_file.assert_called_with(CPUThermalControl.CPU_COOLING_STATE, CPUThermalControl.MIN_COOLING_STATE, log_func=None) - - # Test current temp increasing - file_content[CPUThermalControl.CPU_TEMP_FILE] = instance.temp_low - instance.run(0) - mock_write_file.assert_called_with(CPUThermalControl.CPU_COOLING_STATE, 6, log_func=None) - - # Test current temp decreasing - instance.run(instance.temp_low + 1) - mock_write_file.assert_called_with(CPUThermalControl.CPU_COOLING_STATE, 4, log_func=None) - - # Test current temp increasing and current cooling state is already the max - file_content[CPUThermalControl.CPU_TEMP_FILE] = 85 - file_content[CPUThermalControl.CPU_COOLING_STATE] = CPUThermalControl.MAX_COOLING_STATE - instance.run(84) - mock_write_file.assert_called_with(CPUThermalControl.CPU_COOLING_STATE, CPUThermalControl.MAX_COOLING_STATE, log_func=None) - - # Test current temp decreasing and current cooling state is already the max - file_content[CPUThermalControl.CPU_COOLING_STATE] = CPUThermalControl.MIN_COOLING_STATE - instance.run(86) - mock_write_file.assert_called_with(CPUThermalControl.CPU_COOLING_STATE, CPUThermalControl.MIN_COOLING_STATE, log_func=None) diff --git a/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py index 8f51ddb316..151b197e08 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. +# Copyright (c) 2020-2023 NVIDIA CORPORATION & AFFILIATES. # Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -108,11 +108,10 @@ class TestFan: mock_write_file.assert_called_with(fan.fan_speed_set_path, 153, raise_exception=True) @patch('sonic_platform.utils.read_int_from_file') - @patch('sonic_platform.thermal.Thermal.get_cooling_level') @patch('sonic_platform.psu.Psu.get_presence') @patch('sonic_platform.psu.Psu.get_powergood_status') @patch('os.path.exists') - def test_psu_fan_basic(self, mock_path_exists, mock_powergood, mock_presence, mock_cooling_level, mock_read_int): + def test_psu_fan_basic(self, mock_path_exists, mock_powergood, mock_presence, mock_read_int): mock_path_exists.return_value = False psu = Psu(0) fan = PsuFan(0, 1, psu) @@ -125,7 +124,7 @@ class TestFan: assert fan.get_presence() is False mock_path_exists.return_value = True assert fan.get_presence() is True - mock_cooling_level.return_value = 7 + mock_read_int.return_value = 7 assert fan.get_target_speed() == 70 mock_read_int.return_value = FAN_DIR_VALUE_INTAKE assert fan.get_direction() == Fan.FAN_DIRECTION_INTAKE diff --git a/platform/mellanox/mlnx-platform-api/tests/test_thermal.py b/platform/mellanox/mlnx-platform-api/tests/test_thermal.py index d906fdf4e0..db81f73096 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_thermal.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_thermal.py @@ -205,149 +205,3 @@ class TestThermal: mock_read.return_value = None assert thermal.get_high_critical_threshold() is None - - @mock.patch('glob.iglob', mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2'])) - @mock.patch('sonic_platform.utils.write_file') - def test_set_thermal_algorithm_status(self, mock_write): - from sonic_platform.thermal import Thermal, THERMAL_ZONE_FOLDER_WILDCARD, THERMAL_ZONE_POLICY_FILE, THERMAL_ZONE_MODE_FILE - assert Thermal.set_thermal_algorithm_status(True, False) - - for folder in glob.iglob(THERMAL_ZONE_FOLDER_WILDCARD): - mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_POLICY_FILE), 'step_wise') - mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_MODE_FILE), 'enabled') - - assert Thermal.set_thermal_algorithm_status(False, False) - for folder in glob.iglob(THERMAL_ZONE_FOLDER_WILDCARD): - mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_POLICY_FILE), 'user_space') - mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_MODE_FILE), 'disabled') - - assert not Thermal.set_thermal_algorithm_status(False, False) - - assert Thermal.set_thermal_algorithm_status(False) - - @mock.patch('glob.iglob', mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2'])) - @mock.patch('sonic_platform.utils.read_int_from_file') - def test_get_min_allowed_cooling_level_by_thermal_zone(self, mock_read_file): - from sonic_platform.thermal import Thermal, THERMAL_ZONE_TEMP_FILE, THERMAL_ZONE_HIGH_THRESHOLD, THERMAL_ZONE_NORMAL_THRESHOLD, MIN_COOLING_LEVEL_FOR_HIGH, MIN_COOLING_LEVEL_FOR_NORMAL - mock_read_file.side_effect = Exception('') - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() is None - - mock_file_content = {} - def mock_read_int_from_file(file_path, default=0, raise_exception=False): - return mock_file_content[file_path] - - mock_read_file.side_effect = mock_read_int_from_file - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_NORMAL_THRESHOLD)] = 75000 - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_HIGH_THRESHOLD)] = 85000 - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_TEMP_FILE)] = 69000 - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_NORMAL_THRESHOLD)] = 75000 - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_HIGH_THRESHOLD)] = 85000 - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_TEMP_FILE)] = 24000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() == MIN_COOLING_LEVEL_FOR_NORMAL - - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_TEMP_FILE)] = 71000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() == MIN_COOLING_LEVEL_FOR_HIGH - - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_TEMP_FILE)] = 79000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() == MIN_COOLING_LEVEL_FOR_HIGH - - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_TEMP_FILE)] = 81000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() is None - - @mock.patch('glob.iglob', mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2'])) - @mock.patch('sonic_platform.utils.read_int_from_file') - def test_no_sensor_thermal_zone(self, mock_read_file): - from sonic_platform.thermal import Thermal, THERMAL_ZONE_TEMP_FILE, THERMAL_ZONE_HIGH_THRESHOLD, THERMAL_ZONE_NORMAL_THRESHOLD, MIN_COOLING_LEVEL_FOR_HIGH, MIN_COOLING_LEVEL_FOR_NORMAL - - mock_file_content = {} - def mock_read_int_from_file(file_path, **kwargs): - return mock_file_content[file_path] - - mock_read_file.side_effect = mock_read_int_from_file - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_NORMAL_THRESHOLD)] = 0 - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_HIGH_THRESHOLD)] = 0 - mock_file_content[os.path.join('thermal_zone1', THERMAL_ZONE_TEMP_FILE)] = 0 - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_NORMAL_THRESHOLD)] = 75000 - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_HIGH_THRESHOLD)] = 85000 - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_TEMP_FILE)] = 24000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() == MIN_COOLING_LEVEL_FOR_NORMAL - - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_TEMP_FILE)] = 71000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() == MIN_COOLING_LEVEL_FOR_HIGH - - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_TEMP_FILE)] = 79000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() == MIN_COOLING_LEVEL_FOR_HIGH - - mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_TEMP_FILE)] = 81000 - assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() is None - - @mock.patch('glob.iglob', mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2'])) - def test_check_module_temperature_trustable(self): - from sonic_platform.thermal import Thermal - from sonic_platform import utils - - utils.read_int_from_file = mock.MagicMock(return_value=1) - assert Thermal.check_module_temperature_trustable() == 'untrust' - - utils.read_int_from_file = mock.MagicMock(return_value=0) - assert Thermal.check_module_temperature_trustable() == 'trust' - - def test_get_min_amb_temperature(self): - from sonic_platform.thermal import Thermal, MAX_AMBIENT_TEMP, CHASSIS_THERMAL_SYSFS_FOLDER - from sonic_platform import utils - - utils.read_int_from_file = mock.MagicMock(side_effect=Exception('')) - assert Thermal.get_min_amb_temperature() == MAX_AMBIENT_TEMP - - mock_file_content = {} - def mock_read_int_from_file(file_path, default=0, raise_exception=False): - return mock_file_content[file_path] - - utils.read_int_from_file = mock_read_int_from_file - mock_file_content[os.path.join(CHASSIS_THERMAL_SYSFS_FOLDER, 'fan_amb')] = 50 - mock_file_content[os.path.join(CHASSIS_THERMAL_SYSFS_FOLDER, 'port_amb')] = 40 - assert Thermal.get_min_amb_temperature() == 40 - - @mock.patch('sonic_platform.utils.write_file') - def test_set_cooling_level(self, mock_write_file): - from sonic_platform.thermal import Thermal, COOLING_STATE_PATH - Thermal.set_cooling_level(10) - calls = [mock.call(COOLING_STATE_PATH, 20, raise_exception=True)] - mock_write_file.assert_has_calls(calls) - - pre_call_count = mock_write_file.call_count - Thermal.set_cooling_level(10) - assert pre_call_count == mock_write_file.call_count - - Thermal.set_cooling_level(9) - calls = [mock.call(COOLING_STATE_PATH, 19, raise_exception=True)] - mock_write_file.assert_has_calls(calls) - - @mock.patch('sonic_platform.utils.write_file') - def test_set_cooling_state(self, mock_write_file): - from sonic_platform.thermal import Thermal, COOLING_STATE_PATH - Thermal.set_cooling_state(10) - calls = [mock.call(COOLING_STATE_PATH, 10, raise_exception=True)] - mock_write_file.assert_has_calls(calls) - - pre_call_count = mock_write_file.call_count - Thermal.set_cooling_state(10) - assert pre_call_count == mock_write_file.call_count - - Thermal.set_cooling_state(9) - calls = [mock.call(COOLING_STATE_PATH, 9, raise_exception=True)] - mock_write_file.assert_has_calls(calls) - - @mock.patch('sonic_platform.utils.read_int_from_file') - def test_get_cooling_level(self, mock_read_file): - from sonic_platform.thermal import Thermal, COOLING_STATE_PATH - Thermal.get_cooling_level() - mock_read_file.assert_called_with(COOLING_STATE_PATH, raise_exception=True) - - mock_read_file.side_effect = IOError('') - with pytest.raises(RuntimeError): - Thermal.get_cooling_level() - - mock_read_file.side_effect = ValueError('') - with pytest.raises(RuntimeError): - Thermal.get_cooling_level() diff --git a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py deleted file mode 100644 index ffdc6afbb0..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py +++ /dev/null @@ -1,510 +0,0 @@ -# -# Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. -# Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -import os -import sys -import pytest -import json -from mock import MagicMock, patch -from .mock_platform import MockChassis, MockFan, MockFanDrawer, MockPsu - -test_path = os.path.dirname(os.path.abspath(__file__)) -modules_path = os.path.dirname(test_path) -sys.path.insert(0, modules_path) - -from sonic_platform.thermal_manager import ThermalManager -from sonic_platform.thermal_infos import FanInfo, PsuInfo -from sonic_platform.thermal import Thermal, MAX_COOLING_LEVEL -from sonic_platform.device_data import DeviceDataManager - - -@pytest.fixture(scope='session', autouse=True) -def thermal_manager(): - policy_file = os.path.join(test_path, 'thermal_policy.json') - ThermalManager.load(policy_file) - return ThermalManager - - -def test_load_policy(thermal_manager): - assert 'psu_info' in thermal_manager._thermal_info_dict - assert 'fan_info' in thermal_manager._thermal_info_dict - assert 'chassis_info' in thermal_manager._thermal_info_dict - - assert 'any fan absence' in thermal_manager._policy_dict - assert 'any psu absence' in thermal_manager._policy_dict - assert 'any fan broken' in thermal_manager._policy_dict - assert 'all fan and psu presence' in thermal_manager._policy_dict - - assert thermal_manager._fan_speed_when_suspend == 60 - assert thermal_manager._run_thermal_algorithm_at_boot_up == False - - -def test_fan_info(): - chassis = MockChassis() - chassis.make_fan_absence() - fan_info = FanInfo() - fan_info.collect(chassis) - assert len(fan_info.get_absence_fans()) == 1 - assert len(fan_info.get_presence_fans()) == 0 - assert len(fan_info.get_fault_fans()) == 0 - assert fan_info.is_status_changed() - - chassis.get_all_fan_drawers()[0].get_all_fans()[0].presence = True - fan_info.collect(chassis) - assert len(fan_info.get_absence_fans()) == 0 - assert len(fan_info.get_presence_fans()) == 1 - assert len(fan_info.get_fault_fans()) == 0 - assert fan_info.is_status_changed() - - chassis.get_all_fan_drawers()[0].get_all_fans()[0].status = False - fan_info.collect(chassis) - assert len(fan_info.get_absence_fans()) == 0 - assert len(fan_info.get_presence_fans()) == 1 - assert len(fan_info.get_fault_fans()) == 1 - assert fan_info.is_status_changed() - -def test_psu_info(): - chassis = MockChassis() - chassis.make_psu_absence() - psu_info = PsuInfo() - psu_info.collect(chassis) - assert len(psu_info.get_absence_psus()) == 1 - assert len(psu_info.get_presence_psus()) == 0 - assert psu_info.is_status_changed() - - psu_list = chassis.get_all_psus() - psu_list[0].presence = True - psu_info.collect(chassis) - assert len(psu_info.get_absence_psus()) == 0 - assert len(psu_info.get_presence_psus()) == 1 - assert psu_info.is_status_changed() - - psu_list[0].powergood = False - psu_info.collect(chassis) - assert len(psu_info.get_absence_psus()) == 0 - assert len(psu_info.get_presence_psus()) == 1 - assert not psu_info.is_status_changed() - - -@patch('sonic_platform.thermal.Thermal.monitor_asic_themal_zone', MagicMock()) -@patch('sonic_platform.thermal.Thermal.get_cooling_level', MagicMock(return_value=6)) -@patch('sonic_platform.thermal.Thermal.get_min_allowed_cooling_level_by_thermal_zone', MagicMock(return_value=2)) -@patch('sonic_platform.thermal.Thermal.set_cooling_state') -@patch('sonic_platform.thermal.Thermal.set_cooling_level') -def test_fan_policy(mock_set_cooling_level, mock_set_cooling_state, thermal_manager): - print('In test_fan_policy') - from sonic_platform.thermal import MIN_COOLING_LEVEL_FOR_NORMAL - chassis = MockChassis() - chassis.make_fan_absence() - chassis.get_all_fan_drawers()[0].get_all_fans().append(MockFan()) - chassis.platform_name = 'some_platform' - thermal_manager.run_policy(chassis) - - mock_set_cooling_level.assert_called_with(MAX_COOLING_LEVEL) - mock_set_cooling_state.assert_called_with(MAX_COOLING_LEVEL) - - Thermal.expect_cooling_level = None - fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() - fan_list[0].presence = True - thermal_manager.run_policy(chassis) - mock_set_cooling_level.assert_called_with(6) - mock_set_cooling_state.assert_called_with(6) - - Thermal.expect_cooling_level = None - fan_list[0].status = False - thermal_manager.run_policy(chassis) - mock_set_cooling_level.assert_called_with(MAX_COOLING_LEVEL) - - Thermal.expect_cooling_level = None - fan_list[0].status = True - thermal_manager.run_policy(chassis) - mock_set_cooling_level.assert_called_with(6) - mock_set_cooling_state.assert_called_with(6) - - -@patch('sonic_platform.thermal.Thermal.monitor_asic_themal_zone', MagicMock()) -@patch('sonic_platform.thermal.Thermal.get_min_allowed_cooling_level_by_thermal_zone', MagicMock(return_value=2)) -@patch('sonic_platform.thermal.Thermal.get_cooling_level', MagicMock(return_value=6)) -@patch('sonic_platform.thermal.Thermal.set_cooling_state') -@patch('sonic_platform.thermal.Thermal.set_cooling_level') -def test_psu_policy(mock_set_cooling_level, mock_set_cooling_state, thermal_manager): - chassis = MockChassis() - chassis.make_psu_absence() - chassis.platform_name = 'some_platform' - thermal_manager.run_policy(chassis) - mock_set_cooling_level.assert_called_with(MAX_COOLING_LEVEL) - mock_set_cooling_state.assert_called_with(MAX_COOLING_LEVEL) - - psu_list = chassis.get_all_psus() - psu_list[0].presence = True - thermal_manager.run_policy(chassis) - mock_set_cooling_level.assert_called_with(6) - mock_set_cooling_state.assert_called_with(6) - - -def test_any_fan_absence_condition(): - chassis = MockChassis() - chassis.make_fan_absence() - fan_info = FanInfo() - fan_info.collect(chassis) - - from sonic_platform.thermal_conditions import AnyFanAbsenceCondition - condition = AnyFanAbsenceCondition() - assert condition.is_match({'fan_info': fan_info}) - - fan = chassis.get_all_fan_drawers()[0].get_all_fans()[0] - fan.presence = True - fan_info.collect(chassis) - assert not condition.is_match({'fan_info': fan_info}) - - -def test_all_fan_absence_condition(): - chassis = MockChassis() - chassis.make_fan_absence() - fan = MockFan() - fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() - fan_list.append(fan) - fan_info = FanInfo() - fan_info.collect(chassis) - - from sonic_platform.thermal_conditions import AllFanAbsenceCondition - condition = AllFanAbsenceCondition() - assert not condition.is_match({'fan_info': fan_info}) - - fan.presence = False - fan_info.collect(chassis) - assert condition.is_match({'fan_info': fan_info}) - - -def test_all_fan_presence_condition(): - chassis = MockChassis() - chassis.make_fan_absence() - fan = MockFan() - fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() - fan_list.append(fan) - fan_info = FanInfo() - fan_info.collect(chassis) - - from sonic_platform.thermal_conditions import AllFanPresenceCondition - condition = AllFanPresenceCondition() - assert not condition.is_match({'fan_info': fan_info}) - - fan_list[0].presence = True - fan_info.collect(chassis) - assert condition.is_match({'fan_info': fan_info}) - -def test_any_fan_fault_condition(): - chassis = MockChassis() - chassis.get_all_fan_drawers().append(MockFanDrawer()) - fan = MockFan() - fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() - fan_list.append(fan) - fault_fan = MockFan() - fault_fan.status = False - fan_list.append(fault_fan) - fan_info = FanInfo() - fan_info.collect(chassis) - - from sonic_platform.thermal_conditions import AnyFanFaultCondition - condition = AnyFanFaultCondition() - assert condition.is_match({'fan_info': fan_info}) - - fault_fan.status = True - fan_info.collect(chassis) - assert not condition.is_match({'fan_info': fan_info}) - -def test_all_fan_good_condition(): - chassis = MockChassis() - chassis.get_all_fan_drawers().append(MockFanDrawer()) - fan = MockFan() - fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() - fan_list.append(fan) - fault_fan = MockFan() - fault_fan.status = False - fan_list.append(fault_fan) - fan_info = FanInfo() - fan_info.collect(chassis) - - from sonic_platform.thermal_conditions import AllFanGoodCondition - condition = AllFanGoodCondition() - assert not condition.is_match({'fan_info': fan_info}) - - fault_fan.status = True - fan_info.collect(chassis) - assert condition.is_match({'fan_info': fan_info}) - - -def test_any_psu_absence_condition(): - chassis = MockChassis() - chassis.make_psu_absence() - psu_info = PsuInfo() - psu_info.collect(chassis) - - from sonic_platform.thermal_conditions import AnyPsuAbsenceCondition - condition = AnyPsuAbsenceCondition() - assert condition.is_match({'psu_info': psu_info}) - - psu = chassis.get_all_psus()[0] - psu.presence = True - psu_info.collect(chassis) - assert not condition.is_match({'psu_info': psu_info}) - - -def test_all_psu_absence_condition(): - chassis = MockChassis() - chassis.make_psu_absence() - psu = MockPsu() - psu_list = chassis.get_all_psus() - psu_list.append(psu) - psu_info = PsuInfo() - psu_info.collect(chassis) - - from sonic_platform.thermal_conditions import AllPsuAbsenceCondition - condition = AllPsuAbsenceCondition() - assert not condition.is_match({'psu_info': psu_info}) - - psu.presence = False - psu_info.collect(chassis) - assert condition.is_match({'psu_info': psu_info}) - - -def test_all_fan_presence_condition(): - chassis = MockChassis() - chassis.make_psu_absence() - psu = MockPsu() - psu_list = chassis.get_all_psus() - psu_list.append(psu) - psu_info = PsuInfo() - psu_info.collect(chassis) - - from sonic_platform.thermal_conditions import AllPsuPresenceCondition - condition = AllPsuPresenceCondition() - assert not condition.is_match({'psu_info': psu_info}) - - psu_list[0].presence = True - psu_info.collect(chassis) - assert condition.is_match({'psu_info': psu_info}) - - -def test_load_set_fan_speed_action(): - from sonic_platform.thermal_actions import SetAllFanSpeedAction - action = SetAllFanSpeedAction() - json_str = '{\"speed\": \"50\"}' - json_obj = json.loads(json_str) - action.load_from_json(json_obj) - assert action.speed == 50 - - json_str = '{\"speed\": \"-1\"}' - json_obj = json.loads(json_str) - with pytest.raises(ValueError): - action.load_from_json(json_obj) - - json_str = '{\"speed\": \"101\"}' - json_obj = json.loads(json_str) - with pytest.raises(ValueError): - action.load_from_json(json_obj) - - json_str = '{\"invalid\": \"101\"}' - json_obj = json.loads(json_str) - with pytest.raises(ValueError): - action.load_from_json(json_obj) - - -@patch('sonic_platform.thermal.Thermal.set_cooling_level', MagicMock()) -def test_execute_set_fan_speed_action(): - chassis = MockChassis() - chassis.get_all_fan_drawers().append(MockFanDrawer()) - fan_list = chassis.get_all_fan_drawers()[0].get_all_fans() - fan_list.append(MockFan()) - fan_list.append(MockFan()) - fan_info = FanInfo() - fan_info.collect(chassis) - - Thermal.expect_cooling_level = None - from sonic_platform.thermal_actions import SetAllFanSpeedAction - action = SetAllFanSpeedAction() - action.speed = 20 - action.execute({'fan_info': fan_info}) - assert Thermal.expect_cooling_level == 2 - - -def test_load_duplicate_condition(): - from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy - with open(os.path.join(test_path, 'duplicate_condition.json')) as f: - json_obj = json.load(f) - policy = ThermalPolicy() - with pytest.raises(Exception): - policy.load_from_json(json_obj) - -def test_load_duplicate_action(): - from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy - with open(os.path.join(test_path, 'duplicate_action.json')) as f: - json_obj = json.load(f) - policy = ThermalPolicy() - with pytest.raises(Exception): - policy.load_from_json(json_obj) - -def test_load_empty_condition(): - from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy - with open(os.path.join(test_path, 'empty_condition.json')) as f: - json_obj = json.load(f) - policy = ThermalPolicy() - with pytest.raises(Exception): - policy.load_from_json(json_obj) - -def test_load_empty_action(): - from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy - with open(os.path.join(test_path, 'empty_action.json')) as f: - json_obj = json.load(f) - policy = ThermalPolicy() - with pytest.raises(Exception): - policy.load_from_json(json_obj) - -def test_load_policy_with_same_conditions(): - from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase - class MockThermalManager(ThermalManagerBase): - pass - - with pytest.raises(Exception): - MockThermalManager.load(os.path.join(test_path, 'policy_with_same_conditions.json')) - -def test_dynamic_minimum_table_data(): - from sonic_platform.device_data import DEVICE_DATA - for platform, platform_data in DEVICE_DATA.items(): - if 'thermal' in platform_data and 'minimum_table' in platform_data['thermal']: - minimum_table = platform_data['thermal']['minimum_table'] - check_minimum_table_data(platform, minimum_table) - -def check_minimum_table_data(platform, minimum_table): - valid_dir = ['p2c', 'c2p', 'unk'] - valid_trust_state = ['trust', 'untrust'] - - for category, data in minimum_table.items(): - key_data = category.split('_') - assert key_data[0] in valid_dir - assert key_data[1] in valid_trust_state - - data_list = [(value, key) for key, value in data.items()] - data_list.sort(key=lambda x : x[0]) - - previous_edge = None - previous_cooling_level = None - for item in data_list: - cooling_level = item[0] - range_str = item[1] - - ranges = range_str.split(':') - low = int(ranges[0]) - high = int(ranges[1]) - assert low < high - - if previous_edge is None: - assert low == -127 - else: - assert low - previous_edge == 1, '{}-{}-{} error, item={}'.format(platform, key_data[0], key_data[1], item) - previous_edge = high - - assert 10 <= cooling_level <= 20 - if previous_cooling_level is not None: - assert cooling_level > previous_cooling_level - previous_cooling_level = cooling_level - -@patch('sonic_platform.thermal.Thermal.monitor_asic_themal_zone', MagicMock()) -@patch('sonic_platform.device_data.DeviceDataManager.get_platform_name') -@patch('sonic_platform.thermal.Thermal.get_min_allowed_cooling_level_by_thermal_zone') -@patch('sonic_platform.thermal.Thermal.get_min_amb_temperature') -@patch('sonic_platform.thermal.Thermal.check_module_temperature_trustable') -def test_thermal_recover_policy(mock_check_trustable, mock_get_min_amb, moc_get_min_allowed, mock_platform_name): - from sonic_platform.thermal_infos import ChassisInfo - from sonic_platform.thermal_actions import ThermalRecoverAction - chassis = MockChassis() - mock_platform_name.return_value = 'invalid' - info = ChassisInfo() - info._chassis = chassis - thermal_info_dict = {ChassisInfo.INFO_NAME: info} - - Thermal.expect_cooling_level = None - action = ThermalRecoverAction() - moc_get_min_allowed.return_value = 2 - action.execute(thermal_info_dict) - assert Thermal.expect_cooling_level == 6 - Thermal.last_set_cooling_level = Thermal.expect_cooling_level - - Thermal.expect_cooling_level = None - mock_platform_name.return_value = 'x86_64-mlnx_msn2700-r0' - mock_check_trustable.return_value = 'trust' - mock_get_min_amb.return_value = 29999 - moc_get_min_allowed.return_value = None - action.execute(thermal_info_dict) - assert Thermal.expect_cooling_level is None - - moc_get_min_allowed.return_value = 4 - action.execute(thermal_info_dict) - assert Thermal.expect_cooling_level == 4 - Thermal.last_set_cooling_level = Thermal.expect_cooling_level - - mock_check_trustable.return_value = 'untrust' - mock_get_min_amb.return_value = 31001 - action.execute(thermal_info_dict) - assert Thermal.expect_cooling_level == 5 - - -@patch('sonic_platform.thermal.Thermal.set_cooling_state') -@patch('sonic_platform.utils.read_int_from_file') -def test_monitor_asic_themal_zone(mock_read_int, mock_set_cooling_state): - mock_read_int.side_effect = [111000, 105000] - Thermal.monitor_asic_themal_zone() - assert Thermal.expect_cooling_state == MAX_COOLING_LEVEL - Thermal.commit_cooling_level({}) - mock_set_cooling_state.assert_called_with(MAX_COOLING_LEVEL) - mock_read_int.reset() - mock_read_int.side_effect = [104000, 105000] - Thermal.monitor_asic_themal_zone() - assert Thermal.expect_cooling_state is None - - -def test_set_expect_cooling_level(): - Thermal.set_expect_cooling_level(5) - assert Thermal.expect_cooling_level == 5 - - Thermal.set_expect_cooling_level(3) - assert Thermal.expect_cooling_level == 5 - - Thermal.set_expect_cooling_level(10) - assert Thermal.expect_cooling_level == 10 - - -@patch('sonic_platform.thermal.Thermal.commit_cooling_level', MagicMock()) -@patch('sonic_platform.thermal_conditions.AnyFanFaultCondition.is_match') -@patch('sonic_platform.thermal_manager.ThermalManager._collect_thermal_information') -@patch('sonic_platform.thermal.Thermal.set_expect_cooling_level') -def test_run_policy(mock_expect, mock_collect_info, mock_match, thermal_manager): - chassis = MockChassis() - mock_collect_info.side_effect = Exception('') - thermal_manager.run_policy(chassis) - mock_expect.assert_called_with(MAX_COOLING_LEVEL) - - mock_collect_info.side_effect = None - mock_expect.reset_mock() - mock_match.side_effect = Exception('') - thermal_manager.run_policy(chassis) - mock_expect.assert_called_with(MAX_COOLING_LEVEL) - - thermal_manager.stop() - mock_expect.reset_mock() - thermal_manager.run_policy(chassis) - assert mock_expect.call_count == 0 - diff --git a/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json b/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json deleted file mode 100644 index 5155c07185..0000000000 --- a/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "thermal_control_algorithm": { - "run_at_boot_up": "false", - "fan_speed_when_suspend": "60" - }, - "info_types": [ - { - "type": "fan_info" - }, - { - "type": "psu_info" - }, - { - "type": "chassis_info" - } - ], - "policies": [ - { - "name": "any fan absence", - "conditions": [ - { - "type": "fan.any.absence" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "any psu absence", - "conditions": [ - { - "type": "psu.any.absence" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "any fan broken", - "conditions": [ - { - "type": "fan.any.fault" - } - ], - "actions": [ - { - "type": "fan.all.set_speed", - "speed": "100" - } - ] - }, - { - "name": "all fan and psu presence", - "conditions": [ - { - "type": "fan.all.presence" - }, - { - "type": "psu.all.presence" - }, - { - "type": "fan.all.good" - } - ], - "actions": [ - { - "type": "thermal.recover", - "status": "true" - } - ] - } - ] -} \ No newline at end of file diff --git a/platform/mellanox/non-upstream-patches/patches/0049-leds-mlxreg-Provide-conversion-for-hardware-LED-colo.patch b/platform/mellanox/non-upstream-patches/patches/0049-leds-mlxreg-Provide-conversion-for-hardware-LED-colo.patch new file mode 100644 index 0000000000..7842ae66e6 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0049-leds-mlxreg-Provide-conversion-for-hardware-LED-colo.patch @@ -0,0 +1,96 @@ +From 4db801c656712234c840883b68429e6d45080ea3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 6 Jul 2021 18:38:29 +0000 +Subject: [PATCH backport v5.10.43 49/67] leds: mlxreg: Provide conversion for + hardware LED color code + +In case register is set by hardware, convert hardware color code to +expose correct color to "sysfs". +For some LED color at initial state is set by hardware. Hardware +controls LED color until the first software write access to any LED +register - the first software access cancels hardware control. +If LED is under hardware control - detect the color in brightness_get() +function. + +Signed-off-by: Vadim Pasternak +--- + drivers/leds/leds-mlxreg.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c +index 82aea1cd0c12..aa82f6a521f8 100644 +--- a/drivers/leds/leds-mlxreg.c ++++ b/drivers/leds/leds-mlxreg.c +@@ -17,7 +17,9 @@ + #define MLXREG_LED_OFFSET_BLINK_3HZ 0x01 /* Offset from solid: 3Hz blink */ + #define MLXREG_LED_OFFSET_BLINK_6HZ 0x02 /* Offset from solid: 6Hz blink */ + #define MLXREG_LED_IS_OFF 0x00 /* Off */ +-#define MLXREG_LED_RED_SOLID 0x05 /* Solid red */ ++#define MLXREG_LED_RED_SOLID_HW 0x01 /* Solid red or orange by hardware */ ++#define MLXREG_LED_RED_SOLID 0x05 /* Solid red or orange */ ++#define MLXREG_LED_GREEN_SOLID_HW 0x09 /* Solid green by hardware */ + #define MLXREG_LED_GREEN_SOLID 0x0D /* Solid green */ + #define MLXREG_LED_AMBER_SOLID 0x09 /* Solid amber */ + #define MLXREG_LED_BLINK_3HZ 167 /* ~167 msec off/on - HW support */ +@@ -30,6 +32,7 @@ + * @data: led configuration data; + * @led_classdev: led class data; + * @base_color: base led color (other colors have constant offset from base); ++ * @base_color_hw: base led color set by hardware; + * @led_data: led data; + * @data_parent: pointer to private device control data of parent; + */ +@@ -37,6 +40,7 @@ struct mlxreg_led_data { + struct mlxreg_core_data *data; + struct led_classdev led_cdev; + u8 base_color; ++ u8 base_color_hw; + void *data_parent; + char led_cdev_name[MLXREG_CORE_LABEL_MAX_SIZE]; + }; +@@ -124,8 +128,17 @@ mlxreg_led_get_hw(struct mlxreg_led_data *led_data) + regval = regval & ~data->mask; + regval = (ror32(data->mask, data->bit) == 0xf0) ? ror32(regval, + data->bit) : ror32(regval, data->bit + 4); +- if (regval >= led_data->base_color && +- regval <= (led_data->base_color + MLXREG_LED_OFFSET_BLINK_6HZ)) ++ ++ /* ++ * For some LED color at initial state is set by hardware. Hardware controls LED color ++ * until the first write access to any LED register. If LED is under hardware control - ++ * convert the value to the software mask to expose correct color. The first LED set by ++ * software cancels hardware control. ++ */ ++ if ((regval >= led_data->base_color && ++ regval <= (led_data->base_color + MLXREG_LED_OFFSET_BLINK_6HZ)) || ++ (led_data->base_color_hw && regval >= led_data->base_color_hw && ++ regval <= (led_data->base_color_hw + MLXREG_LED_OFFSET_BLINK_6HZ))) + return LED_FULL; + + return LED_OFF; +@@ -217,16 +230,20 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv) + + led_cdev = &led_data->led_cdev; + led_data->data_parent = priv; +- if (strstr(data->label, "red") || +- strstr(data->label, "orange")) { ++ if (strstr(data->label, "red")) { ++ brightness = LED_OFF; ++ led_data->base_color = MLXREG_LED_RED_SOLID; ++ } else if (strstr(data->label, "orange")) { + brightness = LED_OFF; + led_data->base_color = MLXREG_LED_RED_SOLID; ++ led_data->base_color_hw = MLXREG_LED_RED_SOLID_HW; + } else if (strstr(data->label, "amber")) { + brightness = LED_OFF; + led_data->base_color = MLXREG_LED_AMBER_SOLID; + } else { + brightness = LED_OFF; + led_data->base_color = MLXREG_LED_GREEN_SOLID; ++ led_data->base_color_hw = MLXREG_LED_GREEN_SOLID_HW; + } + snprintf(led_data->led_cdev_name, sizeof(led_data->led_cdev_name), + "mlxreg:%s", data->label); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch b/platform/mellanox/non-upstream-patches/patches/0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch new file mode 100644 index 0000000000..8c1da27b35 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch @@ -0,0 +1,38 @@ +From 3d0e396f29b5da17385c279946b70ee5cd373efe Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 7 Jul 2021 10:18:14 +0000 +Subject: [PATCH backport 5.10 050/182] leds: mlxreg: Skip setting LED color + during initialization + +Hardware controls LED through CPLD device and LED control ownership +passes to the software after it performs the first write operation for +any LED on a system. +For example, hardware sets "system" LED "green blink" during boot and +might change it to "red", in case something is went wrong from hardware +point of view. +The motivation for not setting LED during kernel initialization is for +keeping hardware settings visible for user, until user will not decide +to set LEDs according to user OS specific requirements. + +Signed-off-by: Vadim Pasternak +--- + drivers/leds/leds-mlxreg.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c +index 82aea1cd0c12..7df4653a80d7 100644 +--- a/drivers/leds/leds-mlxreg.c ++++ b/drivers/leds/leds-mlxreg.c +@@ -243,9 +243,6 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv) + if (err) + return err; + +- if (led_cdev->brightness) +- mlxreg_led_brightness_set(led_cdev, +- led_cdev->brightness); + dev_info(led_cdev->dev, "label: %s, mask: 0x%02x, offset:0x%02x\n", + data->label, data->mask, data->reg); + } +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0051-leds-mlxreg-Allow-multi-instantiation-of-same-name-L.patch b/platform/mellanox/non-upstream-patches/patches/0051-leds-mlxreg-Allow-multi-instantiation-of-same-name-L.patch new file mode 100644 index 0000000000..d546eaf4b1 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0051-leds-mlxreg-Allow-multi-instantiation-of-same-name-L.patch @@ -0,0 +1,77 @@ +From 6782d682cb0510d0fee33f456ed3492834bad97d Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 7 Jul 2021 10:29:27 +0000 +Subject: leds: mlxreg: Allow multi-instantiation of same name LED for modular + systems + +It could be more than one instance of LED with the same name in the +modular systems. For example, "status" or "uid" LED can be located +on chassis and on each line card of modular system. +In order to avoid conflicts with duplicated names, append platform +device Id, which is unique, to LED name after driver name. +Thus, for example, "status" LED on chassis is to be called, like it is +called now on non-modular systems, on which platform device Id is not +specified: "mlxreg:status:green". While for the line cards LEDs it will +be called like: "pcicard48:status:green", "ibcard66:status:green", +etc. Where line card prefix is specified according to the type of bus +connecting line card to the chassis. + +LED driver works on top of register space of the programmable devices +(CPLD or FPGA), providing the logic for LED control. The programmable +devices on the line cards are connected through I2C bus and LED driver +will work over I2C. On main board programmable device is connected +through LPC, and LED driver works over LPC. + +The motivation it to provide support for new modular systems which +could be equipped with the different types of replaceable line cards +and management board. + +Line cards are connected to the chassis through I2C interface for the +chassis management operations and through PCIe for the networking +operations. + +The first type of line card supports 16x100GbE QSFP28 Ethernet ports. +Those line cards equipped with the programmable devices aimed for +system control of Nvidia Ethernet switch ASIC control, Nvidia FPGA, +Nvidia gearboxes (PHYs). +The next coming card generations are supposed to support: +- Line cards with 8x200Gbe QSFP28 Ethernet ports. +- Line cards with 4x400Gbe QSFP-DD Ethernet ports. +- Smart cards equipped with Nvidia ARM CPU for offloading and for fast + access to the storage (EBoF). +- Fabric cards for inter-connection. + +Signed-off-by: Vadim Pasternak +--- + drivers/leds/leds-mlxreg.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c +index 0f2608a34..099ff4be2 100644 +--- a/drivers/leds/leds-mlxreg.c ++++ b/drivers/leds/leds-mlxreg.c +@@ -245,8 +245,19 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv) + led_data->base_color = MLXREG_LED_GREEN_SOLID; + led_data->base_color_hw = MLXREG_LED_GREEN_SOLID_HW; + } +- snprintf(led_data->led_cdev_name, sizeof(led_data->led_cdev_name), +- "mlxreg:%s", data->label); ++ ++ /* ++ * Id greater than zero is used for LEDs located on replaceable unit, ++ * like line card or fabric card. In this case Id is set to I2C bus ++ * number. Otherwise LEDs located on the main board. The field "identity" ++ * specifies the type of bus connecting line card to the chassis. ++ */ ++ if (priv->pdev->id > 0) ++ sprintf(led_data->led_cdev_name, "%scard%d:%s", led_pdata->identity, ++ priv->pdev->id, data->label); ++ else ++ sprintf(led_data->led_cdev_name, "%s:%s", "mlxreg", ++ data->label); + led_cdev->name = led_data->led_cdev_name; + led_cdev->brightness = brightness; + led_cdev->max_brightness = LED_ON; +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0098-1-Revert-mlxsw-Use-u16-for-local_port-field.patch b/platform/mellanox/non-upstream-patches/patches/0098-1-Revert-mlxsw-Use-u16-for-local_port-field.patch new file mode 100644 index 0000000000..9d8488161f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0098-1-Revert-mlxsw-Use-u16-for-local_port-field.patch @@ -0,0 +1,771 @@ +From 3a6322534307154e067d0596f52f287ecd0f599e Mon Sep 17 00:00:00 2001 +From: Ciju Rajan K +Date: Thu, 17 Aug 2023 10:00:25 +0000 +Subject: Revert "mlxsw: Use u16 for local_port field instead of u8" + +This reverts commit 0639995c2017338c563db36f631e94d19ae45c74. +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 32 ++++---- + drivers/net/ethernet/mellanox/mlxsw/core.h | 34 ++++----- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 6 +- + drivers/net/ethernet/mellanox/mlxsw/reg.h | 106 +++++++++++++------------- + 4 files changed, 89 insertions(+), 89 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index 631c19222fc4..7938bad70e37 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -47,7 +47,7 @@ static struct workqueue_struct *mlxsw_owq; + struct mlxsw_core_port { + struct devlink_port devlink_port; + void *port_driver_priv; +- u16 local_port; ++ u8 local_port; + }; + + void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port) +@@ -669,7 +669,7 @@ static void mlxsw_emad_process_response(struct mlxsw_core *mlxsw_core, + } + + /* called with rcu read lock held */ +-static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u16 local_port, ++static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u8 local_port, + void *priv) + { + struct mlxsw_core *mlxsw_core = priv; +@@ -2094,7 +2094,7 @@ int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, + EXPORT_SYMBOL(mlxsw_core_skb_transmit); + + void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core, +- struct sk_buff *skb, u16 local_port) ++ struct sk_buff *skb, u8 local_port) + { + if (mlxsw_core->driver->ptp_transmitted) + mlxsw_core->driver->ptp_transmitted(mlxsw_core, skb, +@@ -2172,7 +2172,7 @@ mlxsw_core_rx_listener_state_set(struct mlxsw_core *mlxsw_core, + rxl_item->enabled = enabled; + } + +-static void mlxsw_core_event_listener_func(struct sk_buff *skb, u16 local_port, ++static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port, + void *priv) + { + struct mlxsw_event_listener_item *event_listener_item = priv; +@@ -2599,7 +2599,7 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, + { + struct mlxsw_rx_listener_item *rxl_item; + const struct mlxsw_rx_listener *rxl; +- u16 local_port; ++ u8 local_port; + bool found = false; + + if (rx_info->is_lag) { +@@ -2657,7 +2657,7 @@ static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core, + } + + void mlxsw_core_lag_mapping_set(struct mlxsw_core *mlxsw_core, +- u16 lag_id, u8 port_index, u16 local_port) ++ u16 lag_id, u8 port_index, u8 local_port) + { + int index = mlxsw_core_lag_mapping_index(mlxsw_core, + lag_id, port_index); +@@ -2677,7 +2677,7 @@ u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core, + EXPORT_SYMBOL(mlxsw_core_lag_mapping_get); + + void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, +- u16 lag_id, u16 local_port) ++ u16 lag_id, u8 local_port) + { + int i; + +@@ -2705,7 +2705,7 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, + } + EXPORT_SYMBOL(mlxsw_core_res_get); + +-static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, ++static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, + enum devlink_port_flavour flavour, + u32 port_number, bool split, + u32 split_port_subnumber, +@@ -2736,7 +2736,7 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, + return err; + } + +-static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port) ++static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) + { + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; +@@ -2746,7 +2746,7 @@ static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port + memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); + } + +-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, ++int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, + u32 port_number, bool split, + u32 split_port_subnumber, + bool splittable, u32 lanes, +@@ -2761,7 +2761,7 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, + } + EXPORT_SYMBOL(mlxsw_core_port_init); + +-void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port) ++void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) + { + __mlxsw_core_port_fini(mlxsw_core, local_port); + } +@@ -2794,7 +2794,7 @@ void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core) + } + EXPORT_SYMBOL(mlxsw_core_cpu_port_fini); + +-void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, ++void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv, struct net_device *dev) + { + struct mlxsw_core_port *mlxsw_core_port = +@@ -2806,7 +2806,7 @@ void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, + } + EXPORT_SYMBOL(mlxsw_core_port_eth_set); + +-void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port, ++void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv) + { + struct mlxsw_core_port *mlxsw_core_port = +@@ -2818,7 +2818,7 @@ void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port, + } + EXPORT_SYMBOL(mlxsw_core_port_ib_set); + +-void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, ++void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv) + { + struct mlxsw_core_port *mlxsw_core_port = +@@ -2831,7 +2831,7 @@ void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, + EXPORT_SYMBOL(mlxsw_core_port_clear); + + enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, +- u16 local_port) ++ u8 local_port) + { + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; +@@ -2844,7 +2844,7 @@ EXPORT_SYMBOL(mlxsw_core_port_type_get); + + struct devlink_port * + mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, +- u16 local_port) ++ u8 local_port) + { + struct mlxsw_core_port *mlxsw_core_port = + &mlxsw_core->ports[local_port]; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index 1fc783174292..56efb8e48022 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -49,7 +49,7 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, + void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, bool reload); + + struct mlxsw_tx_info { +- u16 local_port; ++ u8 local_port; + bool is_emad; + }; + +@@ -58,11 +58,11 @@ bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core, + int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, + const struct mlxsw_tx_info *tx_info); + void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core, +- struct sk_buff *skb, u16 local_port); ++ struct sk_buff *skb, u8 local_port); + + struct mlxsw_rx_listener { +- void (*func)(struct sk_buff *skb, u16 local_port, void *priv); +- u16 local_port; ++ void (*func)(struct sk_buff *skb, u8 local_port, void *priv); ++ u8 local_port; + u8 mirror_reason; + u16 trap_id; + }; +@@ -194,35 +194,35 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, + struct mlxsw_rx_info *rx_info); + + void mlxsw_core_lag_mapping_set(struct mlxsw_core *mlxsw_core, +- u16 lag_id, u8 port_index, u16 local_port); ++ u16 lag_id, u8 port_index, u8 local_port); + u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core, + u16 lag_id, u8 port_index); + void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, +- u16 lag_id, u16 local_port); ++ u16 lag_id, u8 local_port); + + void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port); +-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, ++int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, + u32 port_number, bool split, u32 split_port_subnumber, + bool splittable, u32 lanes, + const unsigned char *switch_id, + unsigned char switch_id_len); +-void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u16 local_port); ++void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port); + int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core, + void *port_driver_priv, + const unsigned char *switch_id, + unsigned char switch_id_len); + void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core); +-void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, ++void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv, struct net_device *dev); +-void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port, ++void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv); +-void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, ++void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, + void *port_driver_priv); + enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, +- u16 local_port); ++ u8 local_port); + struct devlink_port * + mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, +- u16 local_port); ++ u8 local_port); + struct mlxsw_env *mlxsw_core_env(const struct mlxsw_core *mlxsw_core); + int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module); + +@@ -290,11 +290,11 @@ struct mlxsw_driver { + struct netlink_ext_ack *extack); + void (*fini)(struct mlxsw_core *mlxsw_core); + int (*basic_trap_groups_set)(struct mlxsw_core *mlxsw_core); +- int (*port_type_set)(struct mlxsw_core *mlxsw_core, u16 local_port, ++ int (*port_type_set)(struct mlxsw_core *mlxsw_core, u8 local_port, + enum devlink_port_type new_type); +- int (*port_split)(struct mlxsw_core *mlxsw_core, u16 local_port, ++ int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port, + unsigned int count, struct netlink_ext_ack *extack); +- int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u16 local_port, ++ int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port, + struct netlink_ext_ack *extack); + int (*sb_pool_get)(struct mlxsw_core *mlxsw_core, + unsigned int sb_index, u16 pool_index, +@@ -368,7 +368,7 @@ struct mlxsw_driver { + * is responsible for freeing the passed-in SKB. + */ + void (*ptp_transmitted)(struct mlxsw_core *mlxsw_core, +- struct sk_buff *skb, u16 local_port); ++ struct sk_buff *skb, u8 local_port); + + u8 txhdr_len; + const struct mlxsw_config_profile *profile; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 1ddd11320b99..3d07c2dcf08d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -38,7 +38,7 @@ struct mlxsw_m { + struct mlxsw_m_port { + struct net_device *dev; + struct mlxsw_m *mlxsw_m; +- u16 local_port; ++ u8 local_port; + u8 module; + }; + +@@ -201,7 +201,7 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) + } + + static int +-mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module) ++mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) + { + struct mlxsw_m_port *mlxsw_m_port; + struct net_device *dev; +@@ -264,7 +264,7 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module) + return err; + } + +-static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port) ++static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u8 local_port) + { + struct mlxsw_m_port *mlxsw_m_port = mlxsw_m->ports[local_port]; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h +index 2ec9ec6078e2..a9119451d999 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h +@@ -161,7 +161,7 @@ MLXSW_ITEM32(reg, sspr, sub_port, 0x00, 8, 8); + */ + MLXSW_ITEM32(reg, sspr, system_port, 0x04, 0, 16); + +-static inline void mlxsw_reg_sspr_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(sspr, payload); + mlxsw_reg_sspr_m_set(payload, 1); +@@ -407,7 +407,7 @@ static inline void mlxsw_reg_sfd_uc_pack(char *payload, int rec_index, + enum mlxsw_reg_sfd_rec_policy policy, + const char *mac, u16 fid_vid, + enum mlxsw_reg_sfd_rec_action action, +- u16 local_port) ++ u8 local_port) + { + mlxsw_reg_sfd_rec_pack(payload, rec_index, + MLXSW_REG_SFD_REC_TYPE_UNICAST, mac, action); +@@ -419,7 +419,7 @@ static inline void mlxsw_reg_sfd_uc_pack(char *payload, int rec_index, + + static inline void mlxsw_reg_sfd_uc_unpack(char *payload, int rec_index, + char *mac, u16 *p_fid_vid, +- u16 *p_local_port) ++ u8 *p_local_port) + { + mlxsw_reg_sfd_rec_mac_memcpy_from(payload, rec_index, mac); + *p_fid_vid = mlxsw_reg_sfd_uc_fid_vid_get(payload, rec_index); +@@ -685,7 +685,7 @@ MLXSW_ITEM32_INDEXED(reg, sfn, mac_system_port, MLXSW_REG_SFN_BASE_LEN, 0, 16, + + static inline void mlxsw_reg_sfn_mac_unpack(char *payload, int rec_index, + char *mac, u16 *p_vid, +- u16 *p_local_port) ++ u8 *p_local_port) + { + mlxsw_reg_sfn_rec_mac_memcpy_from(payload, rec_index, mac); + *p_vid = mlxsw_reg_sfn_mac_fid_get(payload, rec_index); +@@ -800,7 +800,7 @@ enum mlxsw_reg_spms_state { + */ + MLXSW_ITEM_BIT_ARRAY(reg, spms, state, 0x04, 0x400, 2); + +-static inline void mlxsw_reg_spms_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_spms_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(spms, payload); + mlxsw_reg_spms_local_port_set(payload, local_port); +@@ -840,7 +840,7 @@ MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8); + */ + MLXSW_ITEM32(reg, spvid, pvid, 0x04, 0, 12); + +-static inline void mlxsw_reg_spvid_pack(char *payload, u16 local_port, u16 pvid) ++static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid) + { + MLXSW_REG_ZERO(spvid, payload); + mlxsw_reg_spvid_local_port_set(payload, local_port); +@@ -929,7 +929,7 @@ MLXSW_ITEM32_INDEXED(reg, spvm, rec_vid, + MLXSW_REG_SPVM_BASE_LEN, 0, 12, + MLXSW_REG_SPVM_REC_LEN, 0, false); + +-static inline void mlxsw_reg_spvm_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port, + u16 vid_begin, u16 vid_end, + bool is_member, bool untagged) + { +@@ -991,7 +991,7 @@ MLXSW_ITEM32(reg, spaft, allow_prio_tagged, 0x04, 30, 1); + */ + MLXSW_ITEM32(reg, spaft, allow_tagged, 0x04, 29, 1); + +-static inline void mlxsw_reg_spaft_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port, + bool allow_untagged) + { + MLXSW_REG_ZERO(spaft, payload); +@@ -1317,7 +1317,7 @@ MLXSW_ITEM32(reg, sldr, num_ports, 0x04, 24, 8); + MLXSW_ITEM32_INDEXED(reg, sldr, system_port, 0x08, 0, 16, 4, 0, false); + + static inline void mlxsw_reg_sldr_lag_add_port_pack(char *payload, u8 lag_id, +- u16 local_port) ++ u8 local_port) + { + MLXSW_REG_ZERO(sldr, payload); + mlxsw_reg_sldr_op_set(payload, MLXSW_REG_SLDR_OP_LAG_ADD_PORT_LIST); +@@ -1327,7 +1327,7 @@ static inline void mlxsw_reg_sldr_lag_add_port_pack(char *payload, u8 lag_id, + } + + static inline void mlxsw_reg_sldr_lag_remove_port_pack(char *payload, u8 lag_id, +- u16 local_port) ++ u8 local_port) + { + MLXSW_REG_ZERO(sldr, payload); + mlxsw_reg_sldr_op_set(payload, MLXSW_REG_SLDR_OP_LAG_REMOVE_PORT_LIST); +@@ -1501,7 +1501,7 @@ MLXSW_ITEM32(reg, slcor, lag_id, 0x00, 0, 10); + MLXSW_ITEM32(reg, slcor, port_index, 0x04, 0, 10); + + static inline void mlxsw_reg_slcor_pack(char *payload, +- u16 local_port, u16 lag_id, ++ u8 local_port, u16 lag_id, + enum mlxsw_reg_slcor_col col) + { + MLXSW_REG_ZERO(slcor, payload); +@@ -1511,7 +1511,7 @@ static inline void mlxsw_reg_slcor_pack(char *payload, + } + + static inline void mlxsw_reg_slcor_port_add_pack(char *payload, +- u16 local_port, u16 lag_id, ++ u8 local_port, u16 lag_id, + u8 port_index) + { + mlxsw_reg_slcor_pack(payload, local_port, lag_id, +@@ -1520,21 +1520,21 @@ static inline void mlxsw_reg_slcor_port_add_pack(char *payload, + } + + static inline void mlxsw_reg_slcor_port_remove_pack(char *payload, +- u16 local_port, u16 lag_id) ++ u8 local_port, u16 lag_id) + { + mlxsw_reg_slcor_pack(payload, local_port, lag_id, + MLXSW_REG_SLCOR_COL_LAG_REMOVE_PORT); + } + + static inline void mlxsw_reg_slcor_col_enable_pack(char *payload, +- u16 local_port, u16 lag_id) ++ u8 local_port, u16 lag_id) + { + mlxsw_reg_slcor_pack(payload, local_port, lag_id, + MLXSW_REG_SLCOR_COL_LAG_COLLECTOR_ENABLED); + } + + static inline void mlxsw_reg_slcor_col_disable_pack(char *payload, +- u16 local_port, u16 lag_id) ++ u8 local_port, u16 lag_id) + { + mlxsw_reg_slcor_pack(payload, local_port, lag_id, + MLXSW_REG_SLCOR_COL_LAG_COLLECTOR_ENABLED); +@@ -1581,7 +1581,7 @@ enum mlxsw_reg_spmlr_learn_mode { + */ + MLXSW_ITEM32(reg, spmlr, learn_mode, 0x04, 30, 2); + +-static inline void mlxsw_reg_spmlr_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port, + enum mlxsw_reg_spmlr_learn_mode mode) + { + MLXSW_REG_ZERO(spmlr, payload); +@@ -1666,7 +1666,7 @@ MLXSW_ITEM32(reg, svfa, counter_set_type, 0x08, 24, 8); + */ + MLXSW_ITEM32(reg, svfa, counter_index, 0x08, 0, 24); + +-static inline void mlxsw_reg_svfa_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port, + enum mlxsw_reg_svfa_mt mt, bool valid, + u16 fid, u16 vid) + { +@@ -1705,7 +1705,7 @@ MLXSW_ITEM32(reg, svpe, local_port, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, svpe, vp_en, 0x00, 8, 1); + +-static inline void mlxsw_reg_svpe_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_svpe_pack(char *payload, u8 local_port, + bool enable) + { + MLXSW_REG_ZERO(svpe, payload); +@@ -1838,7 +1838,7 @@ MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_learn_enable, MLXSW_REG_SPVMLR_BASE_LEN, + MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_vid, MLXSW_REG_SPVMLR_BASE_LEN, 0, 12, + MLXSW_REG_SPVMLR_REC_LEN, 0x00, false); + +-static inline void mlxsw_reg_spvmlr_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port, + u16 vid_begin, u16 vid_end, + bool learn_enable) + { +@@ -1907,7 +1907,7 @@ MLXSW_ITEM32_INDEXED(reg, cwtp, profile_max, MLXSW_REG_CWTP_BASE_LEN, + #define MLXSW_REG_CWTP_MAX_PROFILE 2 + #define MLXSW_REG_CWTP_DEFAULT_PROFILE 1 + +-static inline void mlxsw_reg_cwtp_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_cwtp_pack(char *payload, u8 local_port, + u8 traffic_class) + { + int i; +@@ -2025,7 +2025,7 @@ MLXSW_ITEM32(reg, cwtpm, ntcp_r, 64, 0, 2); + + #define MLXSW_REG_CWTPM_RESET_PROFILE 0 + +-static inline void mlxsw_reg_cwtpm_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_cwtpm_pack(char *payload, u8 local_port, + u8 traffic_class, u8 profile, + bool wred, bool ecn) + { +@@ -2116,7 +2116,7 @@ MLXSW_ITEM32(reg, ppbt, acl_info, 0x10, 0, 16); + + static inline void mlxsw_reg_ppbt_pack(char *payload, enum mlxsw_reg_pxbt_e e, + enum mlxsw_reg_pxbt_op op, +- u16 local_port, u16 acl_info) ++ u8 local_port, u16 acl_info) + { + MLXSW_REG_ZERO(ppbt, payload); + mlxsw_reg_ppbt_e_set(payload, e); +@@ -3260,7 +3260,7 @@ enum mlxsw_reg_qpts_trust_state { + */ + MLXSW_ITEM32(reg, qpts, trust_state, 0x04, 0, 3); + +-static inline void mlxsw_reg_qpts_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_qpts_pack(char *payload, u8 local_port, + enum mlxsw_reg_qpts_trust_state ts) + { + MLXSW_REG_ZERO(qpts, payload); +@@ -3476,7 +3476,7 @@ MLXSW_ITEM32(reg, qtct, switch_prio, 0x00, 0, 4); + */ + MLXSW_ITEM32(reg, qtct, tclass, 0x04, 0, 4); + +-static inline void mlxsw_reg_qtct_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port, + u8 switch_prio, u8 tclass) + { + MLXSW_REG_ZERO(qtct, payload); +@@ -3643,7 +3643,7 @@ MLXSW_ITEM32(reg, qeec, max_shaper_bs, 0x1C, 0, 6); + #define MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2 11 + #define MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3 11 + +-static inline void mlxsw_reg_qeec_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_qeec_pack(char *payload, u8 local_port, + enum mlxsw_reg_qeec_hr hr, u8 index, + u8 next_index) + { +@@ -3654,7 +3654,7 @@ static inline void mlxsw_reg_qeec_pack(char *payload, u16 local_port, + mlxsw_reg_qeec_next_element_index_set(payload, next_index); + } + +-static inline void mlxsw_reg_qeec_ptps_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_qeec_ptps_pack(char *payload, u8 local_port, + bool ptps) + { + MLXSW_REG_ZERO(qeec, payload); +@@ -3692,7 +3692,7 @@ MLXSW_ITEM32(reg, qrwe, dscp, 0x04, 1, 1); + */ + MLXSW_ITEM32(reg, qrwe, pcp, 0x04, 0, 1); + +-static inline void mlxsw_reg_qrwe_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_qrwe_pack(char *payload, u8 local_port, + bool rewrite_pcp, bool rewrite_dscp) + { + MLXSW_REG_ZERO(qrwe, payload); +@@ -3772,7 +3772,7 @@ MLXSW_ITEM32_INDEXED(reg, qpdsm, prio_entry_color2_dscp, + MLXSW_REG_QPDSM_BASE_LEN, 8, 6, + MLXSW_REG_QPDSM_PRIO_ENTRY_REC_LEN, 0x00, false); + +-static inline void mlxsw_reg_qpdsm_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_qpdsm_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(qpdsm, payload); + mlxsw_reg_qpdsm_local_port_set(payload, local_port); +@@ -3813,7 +3813,7 @@ MLXSW_ITEM32(reg, qpdp, local_port, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, qpdp, switch_prio, 0x04, 0, 4); + +-static inline void mlxsw_reg_qpdp_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_qpdp_pack(char *payload, u8 local_port, + u8 switch_prio) + { + MLXSW_REG_ZERO(qpdp, payload); +@@ -3859,7 +3859,7 @@ MLXSW_ITEM16_INDEXED(reg, qpdpm, dscp_entry_prio, + MLXSW_REG_QPDPM_BASE_LEN, 0, 4, + MLXSW_REG_QPDPM_DSCP_ENTRY_REC_LEN, 0x00, false); + +-static inline void mlxsw_reg_qpdpm_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_qpdpm_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(qpdpm, payload); + mlxsw_reg_qpdpm_local_port_set(payload, local_port); +@@ -3901,7 +3901,7 @@ MLXSW_ITEM32(reg, qtctm, local_port, 0x00, 16, 8); + MLXSW_ITEM32(reg, qtctm, mc, 0x04, 0, 1); + + static inline void +-mlxsw_reg_qtctm_pack(char *payload, u16 local_port, bool mc) ++mlxsw_reg_qtctm_pack(char *payload, u8 local_port, bool mc) + { + MLXSW_REG_ZERO(qtctm, payload); + mlxsw_reg_qtctm_local_port_set(payload, local_port); +@@ -4065,7 +4065,7 @@ MLXSW_ITEM32_INDEXED(reg, pmlp, tx_lane, 0x04, 16, 4, 0x04, 0x00, false); + */ + MLXSW_ITEM32_INDEXED(reg, pmlp, rx_lane, 0x04, 24, 4, 0x04, 0x00, false); + +-static inline void mlxsw_reg_pmlp_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_pmlp_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(pmlp, payload); + mlxsw_reg_pmlp_local_port_set(payload, local_port); +@@ -4112,7 +4112,7 @@ MLXSW_ITEM32(reg, pmtu, admin_mtu, 0x08, 16, 16); + */ + MLXSW_ITEM32(reg, pmtu, oper_mtu, 0x0C, 16, 16); + +-static inline void mlxsw_reg_pmtu_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_pmtu_pack(char *payload, u8 local_port, + u16 new_mtu) + { + MLXSW_REG_ZERO(pmtu, payload); +@@ -4306,7 +4306,7 @@ enum mlxsw_reg_ptys_connector_type { + */ + MLXSW_ITEM32(reg, ptys, connector_type, 0x2C, 0, 4); + +-static inline void mlxsw_reg_ptys_eth_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, + u32 proto_admin, bool autoneg) + { + MLXSW_REG_ZERO(ptys, payload); +@@ -4316,7 +4316,7 @@ static inline void mlxsw_reg_ptys_eth_pack(char *payload, u16 local_port, + mlxsw_reg_ptys_an_disable_admin_set(payload, !autoneg); + } + +-static inline void mlxsw_reg_ptys_ext_eth_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_ptys_ext_eth_pack(char *payload, u8 local_port, + u32 proto_admin, bool autoneg) + { + MLXSW_REG_ZERO(ptys, payload); +@@ -4358,7 +4358,7 @@ static inline void mlxsw_reg_ptys_ext_eth_unpack(char *payload, + mlxsw_reg_ptys_ext_eth_proto_oper_get(payload); + } + +-static inline void mlxsw_reg_ptys_ib_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port, + u16 proto_admin, u16 link_width) + { + MLXSW_REG_ZERO(ptys, payload); +@@ -4416,7 +4416,7 @@ MLXSW_ITEM32(reg, ppad, local_port, 0x00, 16, 8); + MLXSW_ITEM_BUF(reg, ppad, mac, 0x02, 6); + + static inline void mlxsw_reg_ppad_pack(char *payload, bool single_base_mac, +- u16 local_port) ++ u8 local_port) + { + MLXSW_REG_ZERO(ppad, payload); + mlxsw_reg_ppad_single_base_mac_set(payload, !!single_base_mac); +@@ -4490,7 +4490,7 @@ MLXSW_ITEM32(reg, paos, ee, 0x04, 30, 1); + */ + MLXSW_ITEM32(reg, paos, e, 0x04, 0, 2); + +-static inline void mlxsw_reg_paos_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_paos_pack(char *payload, u8 local_port, + enum mlxsw_port_admin_status status) + { + MLXSW_REG_ZERO(paos, payload); +@@ -4633,7 +4633,7 @@ static inline void mlxsw_reg_pfcc_prio_pack(char *payload, u8 pfc_en) + mlxsw_reg_pfcc_pfcrx_set(payload, pfc_en); + } + +-static inline void mlxsw_reg_pfcc_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(pfcc, payload); + mlxsw_reg_pfcc_local_port_set(payload, local_port); +@@ -5132,7 +5132,7 @@ MLXSW_ITEM64(reg, ppcnt, tc_no_buffer_discard_uc, + MLXSW_ITEM64(reg, ppcnt, wred_discard, + MLXSW_REG_PPCNT_COUNTERS_OFFSET + 0x00, 0, 64); + +-static inline void mlxsw_reg_ppcnt_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port, + enum mlxsw_reg_ppcnt_grp grp, + u8 prio_tc) + { +@@ -5243,7 +5243,7 @@ MLXSW_ITEM_BIT_ARRAY(reg, pptb, prio_to_buff_msb, 0x0C, 0x04, 4); + + #define MLXSW_REG_PPTB_ALL_PRIO 0xFF + +-static inline void mlxsw_reg_pptb_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_pptb_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(pptb, payload); + mlxsw_reg_pptb_mm_set(payload, MLXSW_REG_PPTB_MM_UM); +@@ -5340,7 +5340,7 @@ MLXSW_ITEM32_INDEXED(reg, pbmc, buf_xoff_threshold, 0x0C, 16, 16, + MLXSW_ITEM32_INDEXED(reg, pbmc, buf_xon_threshold, 0x0C, 0, 16, + 0x08, 0x04, false); + +-static inline void mlxsw_reg_pbmc_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_pbmc_pack(char *payload, u8 local_port, + u16 xoff_timer_value, u16 xoff_refresh) + { + MLXSW_REG_ZERO(pbmc, payload); +@@ -5398,7 +5398,7 @@ MLXSW_ITEM32(reg, pspa, local_port, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, pspa, sub_port, 0x00, 8, 8); + +-static inline void mlxsw_reg_pspa_pack(char *payload, u8 swid, u16 local_port) ++static inline void mlxsw_reg_pspa_pack(char *payload, u8 swid, u8 local_port) + { + MLXSW_REG_ZERO(pspa, payload); + mlxsw_reg_pspa_swid_set(payload, swid); +@@ -5513,7 +5513,7 @@ MLXSW_ITEM32(reg, pplr, local_port, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, pplr, lb_en, 0x04, 0, 8); + +-static inline void mlxsw_reg_pplr_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_pplr_pack(char *payload, u8 local_port, + bool phy_local) + { + MLXSW_REG_ZERO(pplr, payload); +@@ -5609,7 +5609,7 @@ MLXSW_ITEM32(reg, pddr, trblsh_group_opcode, 0x08, 0, 16); + */ + MLXSW_ITEM32(reg, pddr, trblsh_status_opcode, 0x0C, 0, 16); + +-static inline void mlxsw_reg_pddr_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_pddr_pack(char *payload, u8 local_port, + u8 page_select) + { + MLXSW_REG_ZERO(pddr, payload); +@@ -9160,7 +9160,7 @@ MLXSW_ITEM32(reg, mpar, enable, 0x04, 31, 1); + */ + MLXSW_ITEM32(reg, mpar, pa_id, 0x04, 0, 4); + +-static inline void mlxsw_reg_mpar_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port, + enum mlxsw_reg_mpar_i_e i_e, + bool enable, u8 pa_id) + { +@@ -9281,7 +9281,7 @@ MLXSW_ITEM32(reg, mlcr, beacon_duration, 0x04, 0, 16); + */ + MLXSW_ITEM32(reg, mlcr, beacon_remain, 0x08, 0, 16); + +-static inline void mlxsw_reg_mlcr_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_mlcr_pack(char *payload, u8 local_port, + bool active) + { + MLXSW_REG_ZERO(mlcr, payload); +@@ -9671,7 +9671,7 @@ MLXSW_ITEM32(reg, mpsc, e, 0x04, 30, 1); + */ + MLXSW_ITEM32(reg, mpsc, rate, 0x08, 0, 32); + +-static inline void mlxsw_reg_mpsc_pack(char *payload, u16 local_port, bool e, ++static inline void mlxsw_reg_mpsc_pack(char *payload, u8 local_port, bool e, + u32 rate) + { + MLXSW_REG_ZERO(mpsc, payload); +@@ -9904,7 +9904,7 @@ MLXSW_ITEM32(reg, momte, type, 0x04, 0, 8); + */ + MLXSW_ITEM_BIT_ARRAY(reg, momte, tclass_en, 0x08, 0x08, 1); + +-static inline void mlxsw_reg_momte_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_momte_pack(char *payload, u8 local_port, + enum mlxsw_reg_momte_type type) + { + MLXSW_REG_ZERO(momte, payload); +@@ -10574,7 +10574,7 @@ MLXSW_ITEM32(reg, tnqdr, local_port, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, tnqdr, dscp, 0x04, 0, 6); + +-static inline void mlxsw_reg_tnqdr_pack(char *payload, u16 local_port) ++static inline void mlxsw_reg_tnqdr_pack(char *payload, u8 local_port) + { + MLXSW_REG_ZERO(tnqdr, payload); + mlxsw_reg_tnqdr_local_port_set(payload, local_port); +@@ -10963,7 +10963,7 @@ MLXSW_ITEM32(reg, sbcm, max_buff, 0x1C, 0, 24); + */ + MLXSW_ITEM32(reg, sbcm, pool, 0x24, 0, 4); + +-static inline void mlxsw_reg_sbcm_pack(char *payload, u16 local_port, u8 pg_buff, ++static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff, + enum mlxsw_reg_sbxx_dir dir, + u32 min_buff, u32 max_buff, + bool infi_max, u8 pool) +@@ -11049,7 +11049,7 @@ MLXSW_ITEM32(reg, sbpm, min_buff, 0x18, 0, 24); + */ + MLXSW_ITEM32(reg, sbpm, max_buff, 0x1C, 0, 24); + +-static inline void mlxsw_reg_sbpm_pack(char *payload, u16 local_port, u8 pool, ++static inline void mlxsw_reg_sbpm_pack(char *payload, u8 local_port, u8 pool, + enum mlxsw_reg_sbxx_dir dir, bool clr, + u32 min_buff, u32 max_buff) + { +@@ -11244,7 +11244,7 @@ MLXSW_ITEM32(reg, sbib, local_port, 0x00, 16, 8); + */ + MLXSW_ITEM32(reg, sbib, buff_size, 0x08, 0, 24); + +-static inline void mlxsw_reg_sbib_pack(char *payload, u16 local_port, ++static inline void mlxsw_reg_sbib_pack(char *payload, u8 local_port, + u32 buff_size) + { + MLXSW_REG_ZERO(sbib, payload); +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0098-2-Revert-mlxsw-i2c-Fix-chunk-size-setting.patch b/platform/mellanox/non-upstream-patches/patches/0098-2-Revert-mlxsw-i2c-Fix-chunk-size-setting.patch new file mode 100644 index 0000000000..513c6962c1 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0098-2-Revert-mlxsw-i2c-Fix-chunk-size-setting.patch @@ -0,0 +1,26 @@ +From 0dda3bcede5f26c2bd44edbd90c7e9f0aab9ccf0 Mon Sep 17 00:00:00 2001 +From: Ciju Rajan K +Date: Thu, 17 Aug 2023 10:00:59 +0000 +Subject: Revert "mlxsw: i2c: Fix chunk size setting in output mailbox buffer" + +This reverts commit ac91378962238d34030bb4035308f88ba173165f. +--- + drivers/net/ethernet/mellanox/mlxsw/i2c.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +index cc99ec3f4e96..b8a5c0cbb6b5 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +@@ -447,7 +447,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size, + } else { + /* No input mailbox is case of initialization query command. */ + reg_size = MLXSW_I2C_MAX_DATA_SIZE; +- num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size); ++ num = reg_size / mlxsw_i2c->block_size; + + if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { + dev_err(&client->dev, "Could not acquire lock"); +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0098-3-Revert-mlxsw-core_hwmon-Adjust-module-label-names.patch b/platform/mellanox/non-upstream-patches/patches/0098-3-Revert-mlxsw-core_hwmon-Adjust-module-label-names.patch new file mode 100644 index 0000000000..353cc4a008 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0098-3-Revert-mlxsw-core_hwmon-Adjust-module-label-names.patch @@ -0,0 +1,28 @@ +From e0f5c6c6572fd70ad8fa0d268ee95fb8aba1bd98 Mon Sep 17 00:00:00 2001 +From: Ciju Rajan K +Date: Thu, 17 Aug 2023 10:01:22 +0000 +Subject: Revert "mlxsw: core_hwmon: Adjust module label names based on MTCAP + sensor counter" + +This reverts commit 33aa62a331425d5828d417eeac7fab697eb45286. +--- + drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index 464787b10b73..d41afdfbd085 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -377,8 +377,7 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + + return sprintf(buf, "front panel %03u\n", +- mlwsw_hwmon_attr->type_index + 1 - +- mlwsw_hwmon_attr->hwmon->sensor_count); ++ mlwsw_hwmon_attr->type_index); + } + + static ssize_t +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch b/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch index c53175073e..34822879ad 100644 --- a/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch +++ b/platform/mellanox/non-upstream-patches/patches/0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch @@ -1,7 +1,8 @@ -From 45dc72bca025600611d6d08e00758618ddb5d7d0 Mon Sep 17 00:00:00 2001 +From 320a964b80a8f9245da0515a26c2d41e035b3d10 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:41 +0200 -Subject: [PATCH] mlxsw: core_hwmon: Fix variable names for hwmon attributes +Subject: [PATCH backport 5.10 099/182] mlxsw: core_hwmon: Fix variable names + for hwmon attributes Replace all local variables 'mlwsw_hwmon_attr' by 'mlxsw_hwmon_attr'. All variable prefixes should start with 'mlxsw' according to the naming @@ -15,7 +16,7 @@ Signed-off-by: Ido Schimmel 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index d41afdfbd..3788d02b5 100644 +index d41afdfbd085..3788d02b5244 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -57,14 +57,14 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, @@ -251,5 +252,5 @@ index d41afdfbd..3788d02b5 100644 return sprintf(buf, "gearbox %03u\n", index); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch b/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch index cf8c9365af..fcab6bb552 100644 --- a/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch +++ b/platform/mellanox/non-upstream-patches/patches/0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch @@ -1,8 +1,8 @@ -From d2d0080ec104f01fbf0d6b4750f70f1ebe013495 Mon Sep 17 00:00:00 2001 +From 2f12c9f7cd1d91732ee64d11611cc4cb6baf69a6 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:42 +0200 -Subject: [PATCH] mlxsw: core_thermal: Rename labels according to naming - convention +Subject: [PATCH backport 5.10 100/182] mlxsw: core_thermal: Rename labels + according to naming convention Rename labels for error flow handling in order to align with naming convention used in rest of 'mlxsw' code. @@ -15,10 +15,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index cc4cddbdb..e5997b6a0 100644 +index 91abc7a3f7ea..f471f03e0094 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -401,11 +401,11 @@ static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, +@@ -393,11 +393,11 @@ static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, trip->min_state, THERMAL_WEIGHT_DEFAULT); if (err < 0) @@ -32,7 +32,7 @@ index cc4cddbdb..e5997b6a0 100644 for (j = i - 1; j >= 0; j--) thermal_zone_unbind_cooling_device(tzdev, j, cdev); return err; -@@ -807,7 +807,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, +@@ -766,7 +766,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, for (i = 0; i < thermal->tz_module_num; i++) { err = mlxsw_thermal_module_init(dev, core, thermal, i); if (err) @@ -41,7 +41,7 @@ index cc4cddbdb..e5997b6a0 100644 } for (i = 0; i < thermal->tz_module_num; i++) { -@@ -816,12 +816,13 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, +@@ -775,12 +775,13 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, continue; err = mlxsw_thermal_module_tz_init(module_tz); if (err) @@ -57,7 +57,7 @@ index cc4cddbdb..e5997b6a0 100644 for (i = thermal->tz_module_num - 1; i >= 0; i--) mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); kfree(thermal->tz_module_arr); -@@ -912,12 +913,12 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -871,12 +872,12 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, gearbox_tz->parent = thermal; err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); if (err) @@ -72,7 +72,7 @@ index cc4cddbdb..e5997b6a0 100644 for (i--; i >= 0; i--) mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); kfree(thermal->tz_gearbox_arr); -@@ -961,7 +962,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -920,7 +921,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); if (err) { dev_err(dev, "Failed to probe PWMs\n"); @@ -81,7 +81,7 @@ index cc4cddbdb..e5997b6a0 100644 } mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); -@@ -975,14 +976,14 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -934,14 +935,14 @@ int mlxsw_thermal_init(struct mlxsw_core *core, err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl), mfsl_pl); if (err) @@ -98,7 +98,7 @@ index cc4cddbdb..e5997b6a0 100644 } } for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) { -@@ -995,7 +996,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -954,7 +955,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (IS_ERR(cdev)) { err = PTR_ERR(cdev); dev_err(dev, "Failed to register cooling device\n"); @@ -107,7 +107,7 @@ index cc4cddbdb..e5997b6a0 100644 } thermal->cdevs[i] = cdev; } -@@ -1020,38 +1021,40 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -978,38 +979,40 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (IS_ERR(thermal->tzdev)) { err = PTR_ERR(thermal->tzdev); dev_err(dev, "Failed to register thermal zone\n"); @@ -158,5 +158,5 @@ index cc4cddbdb..e5997b6a0 100644 return err; } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch b/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch index fd76e960d4..f1edc13f6e 100644 --- a/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch +++ b/platform/mellanox/non-upstream-patches/patches/0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch @@ -1,7 +1,8 @@ -From 1186332d9cbf3f7cbd2ed52dfcb594ce4e2d2df8 Mon Sep 17 00:00:00 2001 +From d0a94e237cb6d2020a0a1c27f357a9c3bfc0b1d5 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:43 +0200 -Subject: [PATCH] mlxsw: core_thermal: Remove obsolete API for query resource +Subject: [PATCH backport 5.10 101/182] mlxsw: core_thermal: Remove obsolete + API for query resource Remove obsolete API mlxsw_core_res_query_enabled(), which is only relevant for end-of-life SwitchX-2 ASICs. Support for these ASICs was @@ -18,7 +19,7 @@ Signed-off-by: Ido Schimmel 4 files changed, 23 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index 7938bad70..0b1888318 100644 +index 7938bad70e37..0b1888318ef1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -129,12 +129,6 @@ void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) @@ -35,7 +36,7 @@ index 7938bad70..0b1888318 100644 { return mlxsw_core->driver->temp_warn_enabled; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 56efb8e48..0ceb7dae9 100644 +index 56efb8e48022..0ceb7dae95f6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -30,8 +30,6 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core); @@ -48,7 +49,7 @@ index 56efb8e48..0ceb7dae9 100644 bool diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 3788d02b5..8b170ad92 100644 +index 3788d02b5244..8b170ad92302 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -655,9 +655,6 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) @@ -62,10 +63,10 @@ index 3788d02b5..8b170ad92 100644 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); if (err) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index e5997b6a0..9b0cd6f79 100644 +index f471f03e0094..80942c78d9e5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -787,9 +787,6 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, +@@ -746,9 +746,6 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, char mgpir_pl[MLXSW_REG_MGPIR_LEN]; int i, err; @@ -75,7 +76,7 @@ index e5997b6a0..9b0cd6f79 100644 mlxsw_reg_mgpir_pack(mgpir_pl); err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); if (err) -@@ -834,9 +831,6 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal) +@@ -793,9 +790,6 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal) { int i; @@ -85,7 +86,7 @@ index e5997b6a0..9b0cd6f79 100644 for (i = thermal->tz_module_num - 1; i >= 0; i--) mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); kfree(thermal->tz_module_arr); -@@ -884,9 +878,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -843,9 +837,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, int i; int err; @@ -95,7 +96,7 @@ index e5997b6a0..9b0cd6f79 100644 mlxsw_reg_mgpir_pack(mgpir_pl); err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); if (err) -@@ -930,9 +921,6 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal) +@@ -889,9 +880,6 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal) { int i; @@ -106,5 +107,5 @@ index e5997b6a0..9b0cd6f79 100644 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); kfree(thermal->tz_gearbox_arr); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch b/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch index 8dfb08c212..197eb7843e 100644 --- a/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch +++ b/platform/mellanox/non-upstream-patches/patches/0102-mlxsw-reg-Add-mgpir_-prefix-to-MGPIR-fields-comments.patch @@ -1,7 +1,8 @@ -From ad972c6b6591023ddc7547bbcbc5c5e1941b29c5 Mon Sep 17 00:00:00 2001 +From 2e6cd3d593c0bf1cc38093a73ec7777a5b806bfe Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:44 +0200 -Subject: [PATCH] mlxsw: reg: Add "mgpir_" prefix to MGPIR fields comments +Subject: [PATCH backport 5.10 102/182] mlxsw: reg: Add "mgpir_" prefix to + MGPIR fields comments Do the same as for other registers and have "mgpir_" prefix for the MGPIR fields. @@ -14,10 +15,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index a9119451d..7f7cdb3fc 100644 +index 7f9b902049db..c3fb2e4d4458 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10131,24 +10131,24 @@ enum mlxsw_reg_mgpir_device_type { +@@ -10130,24 +10130,24 @@ enum mlxsw_reg_mgpir_device_type { MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE, }; @@ -47,5 +48,5 @@ index a9119451d..7f7cdb3fc 100644 * Access: RO */ -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch b/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch index 2c6249423b..438d496fb9 100644 --- a/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch +++ b/platform/mellanox/non-upstream-patches/patches/0103-mlxsw-core-Remove-unnecessary-asserts.patch @@ -1,7 +1,7 @@ -From 4392d92a40328fe18d1152fae6fada74f46fa1a3 Mon Sep 17 00:00:00 2001 +From 7b7f5f88374c3377fc28e48a0bc77ae4aa783fda Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 7 Dec 2021 16:07:31 +0200 -Subject: [PATCH] mlxsw: core: Remove unnecessary asserts +Subject: [PATCH backport 5.10 103/182] mlxsw: core: Remove unnecessary asserts Remove unnecessary asserts for module index validation. Leave only one that is actually necessary in mlxsw_env_pmpe_listener_func() where the @@ -14,10 +14,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 24 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 61f7a40c0..4cbed2e3b 100644 +index 6dd4ae2f45f4..c1d51b4b6b36 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -416,9 +416,6 @@ int mlxsw_env_reset_module(struct net_device *netdev, +@@ -414,9 +414,6 @@ int mlxsw_env_reset_module(struct net_device *netdev, !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) return 0; @@ -27,7 +27,7 @@ index 61f7a40c0..4cbed2e3b 100644 mutex_lock(&mlxsw_env->module_info_lock); if (mlxsw_env->module_info[module].num_ports_up) { -@@ -458,9 +455,6 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -456,9 +453,6 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, u32 status_bits; int err; @@ -37,7 +37,7 @@ index 61f7a40c0..4cbed2e3b 100644 mutex_lock(&mlxsw_env->module_info_lock); params->policy = mlxsw_env->module_info[module].power_mode_policy; -@@ -562,9 +556,6 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -560,9 +554,6 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, bool low_power; int err = 0; @@ -47,7 +47,7 @@ index 61f7a40c0..4cbed2e3b 100644 if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH && policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) { NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy"); -@@ -903,9 +894,6 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, +@@ -901,9 +892,6 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -57,7 +57,7 @@ index 61f7a40c0..4cbed2e3b 100644 mutex_lock(&mlxsw_env->module_info_lock); *p_counter = mlxsw_env->module_info[module].module_overheat_counter; mutex_unlock(&mlxsw_env->module_info_lock); -@@ -918,9 +906,6 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) +@@ -916,9 +904,6 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -67,7 +67,7 @@ index 61f7a40c0..4cbed2e3b 100644 mutex_lock(&mlxsw_env->module_info_lock); mlxsw_env->module_info[module].num_ports_mapped++; mutex_unlock(&mlxsw_env->module_info_lock); -@@ -931,9 +916,6 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) +@@ -929,9 +914,6 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -77,7 +77,7 @@ index 61f7a40c0..4cbed2e3b 100644 mutex_lock(&mlxsw_env->module_info_lock); mlxsw_env->module_info[module].num_ports_mapped--; mutex_unlock(&mlxsw_env->module_info_lock); -@@ -945,9 +927,6 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) +@@ -943,9 +925,6 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); int err = 0; @@ -87,7 +87,7 @@ index 61f7a40c0..4cbed2e3b 100644 mutex_lock(&mlxsw_env->module_info_lock); if (mlxsw_env->module_info[module].power_mode_policy != -@@ -977,9 +956,6 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) +@@ -975,9 +954,6 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -98,5 +98,5 @@ index 61f7a40c0..4cbed2e3b 100644 mlxsw_env->module_info[module].num_ports_up--; -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch index db900ff41b..97ee7b4112 100644 --- a/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0104-mlxsw-reg-Extend-MTMP-register-with-new-slot-number-.patch @@ -1,7 +1,8 @@ -From 5c2fb60aa437b4858f15bb8bfb02d9df43b4dd95 Mon Sep 17 00:00:00 2001 +From 58426cf3ccba63cbc0b9ddc2abfc1173ca8ba368 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:45 +0200 -Subject: [PATCH] mlxsw: reg: Extend MTMP register with new slot number field +Subject: [PATCH backport 5.10 104/182] mlxsw: reg: Extend MTMP register with + new slot number field Extend MTMP (Management Temperature Register) with new field specifying the slot index. The purpose of this field is to support access to MTMP @@ -23,10 +24,10 @@ Signed-off-by: Ido Schimmel 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 4cbed2e3b..0b43029b2 100644 +index c1d51b4b6b36..32faedfd2ea8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -143,7 +143,7 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +@@ -142,7 +142,7 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, int page; int err; @@ -36,7 +37,7 @@ index 4cbed2e3b..0b43029b2 100644 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); if (err) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 8b170ad92..71ca3b561 100644 +index 8b170ad92302..71ca3b561e62 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -66,7 +66,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, @@ -79,10 +80,10 @@ index 8b170ad92..71ca3b561 100644 MLXSW_REG(mtmp), mtmp_pl); if (err) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 9b0cd6f79..8d88633c9 100644 +index 80942c78d9e5..f4f0f8ce8597 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -280,7 +280,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, +@@ -272,7 +272,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, int temp; int err; @@ -91,7 +92,7 @@ index 9b0cd6f79..8d88633c9 100644 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); if (err) { -@@ -440,7 +440,7 @@ mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core, +@@ -432,7 +432,7 @@ mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core, int err; /* Read module temperature and thresholds. */ @@ -100,7 +101,7 @@ index 9b0cd6f79..8d88633c9 100644 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); if (err) { /* Set temperature and thresholds to zero to avoid passing -@@ -585,7 +585,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, +@@ -577,7 +577,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, int err; index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module; @@ -110,7 +111,7 @@ index 9b0cd6f79..8d88633c9 100644 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); if (err) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 7f7cdb3fc..52cb58c6d 100644 +index c3fb2e4d4458..0428904b99d2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8541,6 +8541,12 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7); @@ -142,5 +143,5 @@ index 7f7cdb3fc..52cb58c6d 100644 mlxsw_reg_mtmp_mte_set(payload, max_temp_enable); mlxsw_reg_mtmp_mtr_set(payload, max_temp_reset); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch index 3c8cfdd7be..c5412a8ddb 100644 --- a/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0105-mlxsw-reg-Extend-MTBR-register-with-new-slot-number-.patch @@ -1,7 +1,8 @@ -From c9c0ae28ab85836ee15920ddafaa3ba45e0dcaeb Mon Sep 17 00:00:00 2001 +From c9c07da3e3dadf102a25e27f49d0ce4f414c096c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:46 +0200 -Subject: [PATCH] mlxsw: reg: Extend MTBR register with new slot number field +Subject: [PATCH backport 5.10 105/182] mlxsw: reg: Extend MTBR register with + new slot number field Extend MTBR (Management Temperature Bulk Register) with new field specifying the slot number. The purpose of this field is to support @@ -22,10 +23,10 @@ Signed-off-by: Ido Schimmel 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 0b43029b2..7feefb38b 100644 +index 32faedfd2ea8..c2aa05be5bcc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -593,8 +593,8 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, +@@ -591,8 +591,8 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, u16 temp; int err; @@ -37,7 +38,7 @@ index 0b43029b2..7feefb38b 100644 if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 71ca3b561..f4bc711a1 100644 +index 71ca3b561e62..f4bc711a16cf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -271,8 +271,8 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, @@ -52,7 +53,7 @@ index 71ca3b561..f4bc711a1 100644 if (err) { dev_err(dev, "Failed to query module temperature sensor\n"); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 52cb58c6d..56927c772 100644 +index 0428904b99d2..df210bd9a29c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8707,6 +8707,12 @@ MLXSW_ITEM_BIT_ARRAY(reg, mtwe, sensor_warning, 0x0, 0x10, 1); @@ -83,5 +84,5 @@ index 52cb58c6d..56927c772 100644 mlxsw_reg_mtbr_num_rec_set(payload, num_rec); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch index bf6f065a9c..56fe2c80c4 100644 --- a/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0106-mlxsw-reg-Extend-MCIA-register-with-new-slot-number-.patch @@ -1,7 +1,8 @@ -From d494bb0c59dd1f6150f189e2878babf53b67e111 Mon Sep 17 00:00:00 2001 +From 4f10b61f33bdaee774b31b7fe37a76058b755561 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:47 +0200 -Subject: [PATCH] mlxsw: reg: Extend MCIA register with new slot number field +Subject: [PATCH backport 5.10 106/182] mlxsw: reg: Extend MCIA register with + new slot number field Extend MCIA (Management Cable Info Access Register) with new field specifying the slot number. The purpose of this field is to support @@ -21,7 +22,7 @@ Signed-off-by: Ido Schimmel 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 7feefb38b..21eacbe0a 100644 +index c2aa05be5bcc..a516c04ad19b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -35,8 +35,8 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, @@ -35,7 +36,7 @@ index 7feefb38b..21eacbe0a 100644 err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); if (err) return err; -@@ -111,7 +111,8 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, +@@ -110,7 +110,8 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, } } @@ -45,7 +46,7 @@ index 7feefb38b..21eacbe0a 100644 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); if (err) -@@ -185,12 +186,12 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +@@ -184,12 +185,12 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM; else page = MLXSW_REG_MCIA_TH_PAGE_NUM; @@ -60,7 +61,7 @@ index 7feefb38b..21eacbe0a 100644 MLXSW_REG_MCIA_PAGE0_LO, off, MLXSW_REG_MCIA_TH_ITEM_SIZE, MLXSW_REG_MCIA_I2C_ADDR_HIGH); -@@ -371,7 +372,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, +@@ -369,7 +370,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, size = min_t(u8, page->length - bytes_read, MLXSW_REG_MCIA_EEPROM_SIZE); @@ -70,7 +71,7 @@ index 7feefb38b..21eacbe0a 100644 page->i2c_address); mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 56927c772..2714e316c 100644 +index df210bd9a29c..bdbe198a9053 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8798,6 +8798,12 @@ MLXSW_ITEM32(reg, mcia, l, 0x00, 31, 1); @@ -86,7 +87,7 @@ index 56927c772..2714e316c 100644 enum { MLXSW_REG_MCIA_STATUS_GOOD = 0, /* No response from module's EEPROM. */ -@@ -8897,11 +8903,13 @@ MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); +@@ -8896,11 +8902,13 @@ MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) / \ MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH + 1) @@ -104,5 +105,5 @@ index 56927c772..2714e316c 100644 mlxsw_reg_mcia_l_set(payload, lock); mlxsw_reg_mcia_page_number_set(payload, page_number); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch b/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch index 46f34b6a2f..d03711b1c0 100644 --- a/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch +++ b/platform/mellanox/non-upstream-patches/patches/0107-mlxsw-reg-Extend-MCION-register-with-new-slot-number.patch @@ -1,7 +1,8 @@ -From 9c4ce1a56515e927399a87b63deeacd77ada6b3b Mon Sep 17 00:00:00 2001 +From aba06998f55ba715e6161a427356fccc17b466fc Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:50 +0200 -Subject: [PATCH] mlxsw: reg: Extend MCION register with new slot number field +Subject: [PATCH backport 5.10 107/182] mlxsw: reg: Extend MCION register with + new slot number field Extend MCION (Management Cable IO and Notifications Register) with new field specifying the slot number. The purpose of this field is to @@ -22,10 +23,10 @@ Signed-off-by: Ido Schimmel 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 21eacbe0a..d88033ec6 100644 +index a516c04ad19b..2ac8444aa8b2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -460,7 +460,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -458,7 +458,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, params->policy = mlxsw_env->module_info[module].power_mode_policy; @@ -35,10 +36,10 @@ index 21eacbe0a..d88033ec6 100644 if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode"); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 2714e316c..243d91f1d 100644 +index bdbe198a9053..acde0cd00944 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -9328,6 +9328,12 @@ MLXSW_REG_DEFINE(mcion, MLXSW_REG_MCION_ID, MLXSW_REG_MCION_LEN); +@@ -9327,6 +9327,12 @@ MLXSW_REG_DEFINE(mcion, MLXSW_REG_MCION_ID, MLXSW_REG_MCION_LEN); */ MLXSW_ITEM32(reg, mcion, module, 0x00, 16, 8); @@ -51,7 +52,7 @@ index 2714e316c..243d91f1d 100644 enum { MLXSW_REG_MCION_MODULE_STATUS_BITS_PRESENT_MASK = BIT(0), MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK = BIT(8), -@@ -9339,9 +9345,10 @@ enum { +@@ -9338,9 +9344,10 @@ enum { */ MLXSW_ITEM32(reg, mcion, module_status_bits, 0x04, 0, 16); @@ -64,5 +65,5 @@ index 2714e316c..243d91f1d 100644 } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch b/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch index 8eff1b9973..721b79aa4c 100644 --- a/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0108-mlxsw-reg-Extend-PMMP-register-with-new-slot-number-.patch @@ -1,7 +1,8 @@ -From d707ce17ce596c2deb97b481dffb24b8c4537fa2 Mon Sep 17 00:00:00 2001 +From 0aebe300b70a084161c12e813396025b255d91d7 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:51 +0200 -Subject: [PATCH] mlxsw: reg: Extend PMMP register with new slot number field +Subject: [PATCH backport 5.10 108/182] mlxsw: reg: Extend PMMP register with + new slot number field Extend PMMP (Port Module Memory Map Properties Register) with new field specifying the slot number. The purpose of this field is to @@ -21,10 +22,10 @@ Signed-off-by: Ido Schimmel 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index d88033ec6..49c58197b 100644 +index 2ac8444aa8b2..ad27a1c90f92 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -503,7 +503,7 @@ static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, +@@ -501,7 +501,7 @@ static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, u16 eeprom_override_mask, eeprom_override; char pmmp_pl[MLXSW_REG_PMMP_LEN]; @@ -34,7 +35,7 @@ index d88033ec6..49c58197b 100644 /* Mask all the bits except low power mode. */ eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK; diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 243d91f1d..c19db16bf 100644 +index acde0cd00944..aad0cb1497aa 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5633,6 +5633,12 @@ MLXSW_REG_DEFINE(pmmp, MLXSW_REG_PMMP_ID, MLXSW_REG_PMMP_LEN); @@ -63,5 +64,5 @@ index 243d91f1d..c19db16bf 100644 } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch b/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch index 95a723bd26..acd11709cc 100644 --- a/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch +++ b/platform/mellanox/non-upstream-patches/patches/0109-mlxsw-reg-Extend-MGPIR-register-with-new-slot-fields.patch @@ -1,7 +1,8 @@ -From 1373ed22ae41e92c081bb80df4b3c4c0630edbb9 Mon Sep 17 00:00:00 2001 +From 441a7861ef61f4d0d55dee542d4704487694f68c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 22 Dec 2021 06:11:50 +0000 -Subject: [PATCH] mlxsw: reg: Extend MGPIR register with new slot fields +Subject: [PATCH backport 5.10 109/182] mlxsw: reg: Extend MGPIR register with + new slot fields Extend MGPIR (Management General Peripheral Information Register) with new fields specifying the slot number and number of the slots available @@ -25,10 +26,10 @@ Signed-off-by: Ido Schimmel 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 49c58197b..b1a1204e7 100644 +index ad27a1c90f92..8ab15d5bd7f5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -985,12 +985,12 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -983,12 +983,12 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) u8 module_count; int i, err; @@ -44,7 +45,7 @@ index 49c58197b..b1a1204e7 100644 env = kzalloc(struct_size(env, module_info, module_count), GFP_KERNEL); if (!env) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index f4bc711a1..2bc4c4556 100644 +index f4bc711a16cf..2bc4c4556895 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -656,13 +656,13 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) @@ -80,10 +81,10 @@ index f4bc711a1..2bc4c4556 100644 !gbox_num) return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 8d88633c9..56e0291f1 100644 +index f4f0f8ce8597..21a7415c8ef5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -787,13 +787,13 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, +@@ -746,13 +746,13 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, char mgpir_pl[MLXSW_REG_MGPIR_LEN]; int i, err; @@ -99,7 +100,7 @@ index 8d88633c9..56e0291f1 100644 thermal->tz_module_arr = kcalloc(thermal->tz_module_num, sizeof(*thermal->tz_module_arr), -@@ -878,13 +878,13 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -837,13 +837,13 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, int i; int err; @@ -116,7 +117,7 @@ index 8d88633c9..56e0291f1 100644 !gbox_num) return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c -index 3d07c2dcf..b2ffcfda8 100644 +index 3d07c2dcf08d..b2ffcfda8374 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -280,13 +280,13 @@ static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) @@ -136,10 +137,10 @@ index 3d07c2dcf..b2ffcfda8 100644 return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index c19db16bf..e981630fd 100644 +index aad0cb1497aa..a5fa25d4bd8f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10167,6 +10167,12 @@ enum mlxsw_reg_mgpir_device_type { +@@ -10166,6 +10166,12 @@ enum mlxsw_reg_mgpir_device_type { MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE, }; @@ -152,7 +153,7 @@ index c19db16bf..e981630fd 100644 /* mgpir_device_type * Access: RO */ -@@ -10184,21 +10190,29 @@ MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); +@@ -10183,21 +10189,29 @@ MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); */ MLXSW_ITEM32(reg, mgpir, num_of_devices, 0x00, 0, 8); @@ -184,7 +185,7 @@ index c19db16bf..e981630fd 100644 { if (num_of_devices) *num_of_devices = mlxsw_reg_mgpir_num_of_devices_get(payload); -@@ -10209,6 +10223,8 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, +@@ -10208,6 +10222,8 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, mlxsw_reg_mgpir_devices_per_flash_get(payload); if (num_of_modules) *num_of_modules = mlxsw_reg_mgpir_num_of_modules_get(payload); @@ -194,5 +195,5 @@ index c19db16bf..e981630fd 100644 /* MFDE - Monitoring FW Debug Register -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch b/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch index ae90d51ca8..110f94ebeb 100644 --- a/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch +++ b/platform/mellanox/non-upstream-patches/patches/0110-mlxsw-core_env-Pass-slot-index-during-PMAOS-register.patch @@ -1,8 +1,8 @@ -From 562fe3c68c9dbcff172eeae8b4f0a84484b5e3e9 Mon Sep 17 00:00:00 2001 +From 7c2049bccef11b265fd4a4458b92277ea8ea97fc Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:52 +0200 -Subject: [PATCH] mlxsw: core_env: Pass slot index during PMAOS register write - call +Subject: [PATCH backport 5.10 110/182] mlxsw: core_env: Pass slot index during + PMAOS register write call Pass the slot index down to PMAOS pack helper alongside with the module. @@ -15,10 +15,10 @@ Signed-off-by: Ido Schimmel 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index b1a1204e7..45058d4cf 100644 +index 8ab15d5bd7f5..b7c1fd3dbf45 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -400,7 +400,7 @@ static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module) +@@ -398,7 +398,7 @@ static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module) { char pmaos_pl[MLXSW_REG_PMAOS_LEN]; @@ -27,7 +27,7 @@ index b1a1204e7..45058d4cf 100644 mlxsw_reg_pmaos_rst_set(pmaos_pl, true); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); -@@ -488,7 +488,7 @@ static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, +@@ -486,7 +486,7 @@ static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, enum mlxsw_reg_pmaos_admin_status admin_status; char pmaos_pl[MLXSW_REG_PMAOS_LEN]; @@ -36,7 +36,7 @@ index b1a1204e7..45058d4cf 100644 admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED : MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED; mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status); -@@ -878,7 +878,7 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, +@@ -876,7 +876,7 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, for (i = 0; i < module_count; i++) { char pmaos_pl[MLXSW_REG_PMAOS_LEN]; @@ -46,7 +46,7 @@ index b1a1204e7..45058d4cf 100644 MLXSW_REG_PMAOS_E_GENERATE_EVENT); mlxsw_reg_pmaos_ee_set(pmaos_pl, true); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index e981630fd..748a22ec4 100644 +index a5fa25d4bd8f..07f68fd1a4e5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5481,9 +5481,10 @@ enum mlxsw_reg_pmaos_e { @@ -62,5 +62,5 @@ index e981630fd..748a22ec4 100644 } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch b/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch index e785735732..d73ec6067a 100644 --- a/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch +++ b/platform/mellanox/non-upstream-patches/patches/0111-mlxsw-reg-Add-new-field-to-Management-General-Periph.patch @@ -1,8 +1,8 @@ -From fe27f006de6b428fe59acb1960373b32e59adf0b Mon Sep 17 00:00:00 2001 +From 4b630e780a6fa8b387e79e252169d5743faf5321 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:49 +0200 -Subject: [PATCH] mlxsw: reg: Add new field to Management General Peripheral - Information Register +Subject: [PATCH backport 5.10 111/182] mlxsw: reg: Add new field to Management + General Peripheral Information Register Add new field 'max_modules_per_slot' to provide maximum number of modules that can be connected per slot. This field will always be zero, @@ -17,10 +17,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 748a22ec4..9de037b9a 100644 +index 07f68fd1a4e5..98c627ffe039 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10191,6 +10191,12 @@ MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); +@@ -10190,6 +10190,12 @@ MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8); */ MLXSW_ITEM32(reg, mgpir, num_of_devices, 0x00, 0, 8); @@ -34,5 +34,5 @@ index 748a22ec4..9de037b9a 100644 * Number of slots in the system. * Access: RO -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch b/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch index 8b4290613c..5e44880f26 100644 --- a/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch +++ b/platform/mellanox/non-upstream-patches/patches/0112-mlxsw-core-Extend-interfaces-for-cable-info-access-w.patch @@ -1,8 +1,8 @@ -From 5577988f783619b9d55f19c983ee8667f52165b7 Mon Sep 17 00:00:00 2001 +From 0b0f4813bdd0b4ed70074d616f68bb6c774662bc Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Fri, 3 Dec 2021 11:48:53 +0200 -Subject: [PATCH] mlxsw: core: Extend interfaces for cable info access with - slot argument +Subject: [PATCH backport 5.10 112/182] mlxsw: core: Extend interfaces for + cable info access with slot argument Extend all cable info APIs with 'slot_index' argument. @@ -24,7 +24,7 @@ Signed-off-by: Ido Schimmel 7 files changed, 155 insertions(+), 107 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 45058d4cf..fefb9bb02 100644 +index b7c1fd3dbf45..fc4468a6b0f6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -27,16 +27,18 @@ struct mlxsw_env { @@ -50,7 +50,7 @@ index 45058d4cf..fefb9bb02 100644 err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); if (err) return err; -@@ -65,8 +67,8 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, +@@ -64,8 +66,8 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, } static int @@ -61,7 +61,7 @@ index 45058d4cf..fefb9bb02 100644 bool qsfp, unsigned int *p_read_size) { char mcia_pl[MLXSW_REG_MCIA_LEN]; -@@ -111,7 +113,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, +@@ -110,7 +112,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, } } @@ -70,7 +70,7 @@ index 45058d4cf..fefb9bb02 100644 i2c_addr); err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); -@@ -129,8 +131,9 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, +@@ -128,8 +130,9 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, return 0; } @@ -82,7 +82,7 @@ index 45058d4cf..fefb9bb02 100644 { unsigned int module_temp, module_crit, module_emerg; union { -@@ -144,8 +147,9 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +@@ -143,8 +146,9 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, int page; int err; @@ -94,7 +94,7 @@ index 45058d4cf..fefb9bb02 100644 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); if (err) return err; -@@ -174,7 +178,8 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +@@ -173,7 +177,8 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, */ /* Validate module identifier value. */ @@ -104,7 +104,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) return err; -@@ -186,12 +191,12 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +@@ -185,12 +190,12 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM; else page = MLXSW_REG_MCIA_TH_PAGE_NUM; @@ -119,7 +119,7 @@ index 45058d4cf..fefb9bb02 100644 MLXSW_REG_MCIA_PAGE0_LO, off, MLXSW_REG_MCIA_TH_ITEM_SIZE, MLXSW_REG_MCIA_I2C_ADDR_HIGH); -@@ -208,8 +213,8 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, +@@ -207,8 +212,8 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, return 0; } @@ -130,7 +130,7 @@ index 45058d4cf..fefb9bb02 100644 { u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE]; u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE; -@@ -217,8 +222,9 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, +@@ -216,8 +221,9 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, unsigned int read_size; int err; @@ -142,7 +142,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) return err; -@@ -247,9 +253,10 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, +@@ -246,9 +252,10 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, break; case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: /* Verify if transceiver provides diagnostic monitoring page */ @@ -156,7 +156,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) return err; -@@ -288,8 +295,9 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, +@@ -286,8 +293,9 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, EXPORT_SYMBOL(mlxsw_env_get_module_info); int mlxsw_env_get_module_eeprom(struct net_device *netdev, @@ -168,7 +168,7 @@ index 45058d4cf..fefb9bb02 100644 { int offset = ee->offset; unsigned int read_size; -@@ -302,12 +310,14 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev, +@@ -300,12 +308,14 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev, memset(data, 0, ee->len); /* Validate module identifier value. */ @@ -185,7 +185,7 @@ index 45058d4cf..fefb9bb02 100644 ee->len - i, data + i, qsfp, &read_size); if (err) { -@@ -353,7 +363,8 @@ static int mlxsw_env_mcia_status_process(const char *mcia_pl, +@@ -351,7 +361,8 @@ static int mlxsw_env_mcia_status_process(const char *mcia_pl, } int @@ -195,7 +195,7 @@ index 45058d4cf..fefb9bb02 100644 const struct ethtool_module_eeprom *page, struct netlink_ext_ack *extack) { -@@ -372,7 +383,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, +@@ -370,7 +381,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, size = min_t(u8, page->length - bytes_read, MLXSW_REG_MCIA_EEPROM_SIZE); @@ -204,7 +204,7 @@ index 45058d4cf..fefb9bb02 100644 device_addr + bytes_read, size, page->i2c_address); mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank); -@@ -396,18 +407,20 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, +@@ -394,18 +405,20 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, } EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page); @@ -228,7 +228,7 @@ index 45058d4cf..fefb9bb02 100644 { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); u32 req = *flags; -@@ -432,7 +445,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, +@@ -430,7 +443,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, goto out; } @@ -237,7 +237,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) { netdev_err(netdev, "Failed to reset module\n"); goto out; -@@ -447,7 +460,8 @@ int mlxsw_env_reset_module(struct net_device *netdev, +@@ -445,7 +458,8 @@ int mlxsw_env_reset_module(struct net_device *netdev, EXPORT_SYMBOL(mlxsw_env_reset_module); int @@ -247,7 +247,7 @@ index 45058d4cf..fefb9bb02 100644 struct ethtool_module_power_mode_params *params, struct netlink_ext_ack *extack) { -@@ -460,7 +474,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -458,7 +472,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, params->policy = mlxsw_env->module_info[module].power_mode_policy; @@ -256,7 +256,7 @@ index 45058d4cf..fefb9bb02 100644 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode"); -@@ -483,12 +497,12 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -481,12 +495,12 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, EXPORT_SYMBOL(mlxsw_env_get_module_power_mode); static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, @@ -271,7 +271,7 @@ index 45058d4cf..fefb9bb02 100644 admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED : MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED; mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status); -@@ -498,12 +512,13 @@ static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, +@@ -496,12 +510,13 @@ static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, } static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, @@ -287,7 +287,7 @@ index 45058d4cf..fefb9bb02 100644 mlxsw_reg_pmmp_sticky_set(pmmp_pl, true); /* Mask all the bits except low power mode. */ eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK; -@@ -516,24 +531,26 @@ static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, +@@ -514,24 +529,26 @@ static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, } static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, @@ -318,7 +318,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to enable module"); goto err_module_enable_set; -@@ -542,14 +559,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, +@@ -540,14 +557,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, return 0; err_module_enable_set: @@ -338,7 +338,7 @@ index 45058d4cf..fefb9bb02 100644 enum ethtool_module_power_mode_policy policy, struct netlink_ext_ack *extack) { -@@ -573,8 +592,8 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -571,8 +590,8 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, goto out_set_policy; low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO; @@ -349,7 +349,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) goto out; -@@ -587,14 +606,14 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, +@@ -585,14 +604,14 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, @@ -366,7 +366,7 @@ index 45058d4cf..fefb9bb02 100644 MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl); if (err) -@@ -615,13 +634,15 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, +@@ -613,13 +632,15 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, return 0; } @@ -384,7 +384,7 @@ index 45058d4cf..fefb9bb02 100644 mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, sensor_index); err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl); if (err) -@@ -629,6 +650,7 @@ static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, +@@ -627,6 +648,7 @@ static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, if (enable) { err = mlxsw_env_module_temp_thresholds_get(mlxsw_core, @@ -392,7 +392,7 @@ index 45058d4cf..fefb9bb02 100644 sensor_index - MLXSW_REG_MTMP_MODULE_INDEX_MIN, SFP_TEMP_HIGH_WARN, -@@ -656,14 +678,14 @@ static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, +@@ -654,14 +676,14 @@ static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, } static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core, @@ -410,7 +410,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) return err; -@@ -671,7 +693,8 @@ static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core, +@@ -669,7 +691,8 @@ static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core, continue; sensor_index = i + MLXSW_REG_MTMP_MODULE_INDEX_MIN; @@ -420,7 +420,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) return err; } -@@ -778,6 +801,7 @@ static void mlxsw_env_temp_warn_event_unregister(struct mlxsw_env *mlxsw_env) +@@ -776,6 +799,7 @@ static void mlxsw_env_temp_warn_event_unregister(struct mlxsw_env *mlxsw_env) struct mlxsw_env_module_plug_unplug_event { struct mlxsw_env *mlxsw_env; @@ -428,7 +428,7 @@ index 45058d4cf..fefb9bb02 100644 u8 module; struct work_struct work; }; -@@ -798,7 +822,9 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) +@@ -796,7 +820,9 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) mlxsw_env->module_info[event->module].is_overheat = false; mutex_unlock(&mlxsw_env->module_info_lock); @@ -439,7 +439,7 @@ index 45058d4cf..fefb9bb02 100644 &has_temp_sensor); /* Do not disable events on modules without sensors or faulty sensors * because FW returns errors. -@@ -810,7 +836,8 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) +@@ -808,7 +834,8 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) goto out; sensor_index = event->module + MLXSW_REG_MTMP_MODULE_INDEX_MIN; @@ -449,7 +449,7 @@ index 45058d4cf..fefb9bb02 100644 out: kfree(event); -@@ -837,6 +864,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, +@@ -835,6 +862,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, return; event->mlxsw_env = mlxsw_env; @@ -457,7 +457,7 @@ index 45058d4cf..fefb9bb02 100644 event->module = module; INIT_WORK(&event->work, mlxsw_env_pmpe_event_work); mlxsw_core_schedule_work(&event->work); -@@ -871,14 +899,14 @@ mlxsw_env_module_plug_event_unregister(struct mlxsw_env *mlxsw_env) +@@ -869,14 +897,14 @@ mlxsw_env_module_plug_event_unregister(struct mlxsw_env *mlxsw_env) static int mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, @@ -474,7 +474,7 @@ index 45058d4cf..fefb9bb02 100644 mlxsw_reg_pmaos_e_set(pmaos_pl, MLXSW_REG_PMAOS_E_GENERATE_EVENT); mlxsw_reg_pmaos_ee_set(pmaos_pl, true); -@@ -890,8 +918,8 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, +@@ -888,8 +916,8 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, } int @@ -485,7 +485,7 @@ index 45058d4cf..fefb9bb02 100644 { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); -@@ -903,7 +931,8 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, +@@ -901,7 +929,8 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, } EXPORT_SYMBOL(mlxsw_env_module_overheat_counter_get); @@ -495,7 +495,7 @@ index 45058d4cf..fefb9bb02 100644 { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); -@@ -913,7 +942,8 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) +@@ -911,7 +940,8 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) } EXPORT_SYMBOL(mlxsw_env_module_port_map); @@ -505,7 +505,7 @@ index 45058d4cf..fefb9bb02 100644 { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); -@@ -923,7 +953,8 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) +@@ -921,7 +951,8 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) } EXPORT_SYMBOL(mlxsw_env_module_port_unmap); @@ -515,7 +515,7 @@ index 45058d4cf..fefb9bb02 100644 { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); int err = 0; -@@ -940,8 +971,8 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) +@@ -938,8 +969,8 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) /* Transition to high power mode following first port using the module * being put administratively up. */ @@ -526,7 +526,7 @@ index 45058d4cf..fefb9bb02 100644 if (err) goto out_unlock; -@@ -953,7 +984,8 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) +@@ -951,7 +982,8 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) } EXPORT_SYMBOL(mlxsw_env_module_port_up); @@ -536,7 +536,7 @@ index 45058d4cf..fefb9bb02 100644 { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); -@@ -971,7 +1003,8 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) +@@ -969,7 +1001,8 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) /* Transition to low power mode following last port using the module * being put administratively down. */ @@ -546,7 +546,7 @@ index 45058d4cf..fefb9bb02 100644 out_unlock: mutex_unlock(&mlxsw_env->module_info_lock); -@@ -1016,12 +1049,13 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1014,12 +1047,13 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) if (err) goto err_module_plug_event_register; @@ -563,7 +563,7 @@ index 45058d4cf..fefb9bb02 100644 goto err_temp_event_enable; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h -index da121b1a8..03d027870 100644 +index da121b1a84b4..03d027870d65 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h @@ -9,46 +9,55 @@ @@ -640,7 +640,7 @@ index da121b1a8..03d027870 100644 int mlxsw_env_init(struct mlxsw_core *core, struct mlxsw_env **p_env); void mlxsw_env_fini(struct mlxsw_env *env); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 2bc4c4556..5df54a5bf 100644 +index 2bc4c4556895..5df54a5bf292 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -311,8 +311,9 @@ static int mlxsw_hwmon_module_temp_critical_get(struct device *dev, @@ -668,10 +668,10 @@ index 2bc4c4556..5df54a5bf 100644 dev_err(dev, "Failed to query module temperature thresholds\n"); return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 56e0291f1..3f9062f1c 100644 +index 21a7415c8ef5..4f84c4bb66af 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -159,13 +159,13 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, +@@ -151,13 +151,13 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, * EEPROM if we got valid thresholds from MTMP. */ if (!emerg_temp || !crit_temp) { @@ -688,7 +688,7 @@ index 56e0291f1..3f9062f1c 100644 &emerg_temp); if (err) diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c -index b2ffcfda8..104f1ba02 100644 +index b2ffcfda8374..104f1ba0242f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -59,7 +59,8 @@ static int mlxsw_m_port_open(struct net_device *dev) @@ -769,7 +769,7 @@ index b2ffcfda8..104f1ba02 100644 } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index 9f068c030..5066fcc46 100644 +index 4110e15c22c7..e0424f490c6f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1377,7 +1377,7 @@ static int mlxsw_sp_port_overheat_init_val_set(struct mlxsw_sp_port *mlxsw_sp_po @@ -782,7 +782,7 @@ index 9f068c030..5066fcc46 100644 if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c -index 369b9d0dc..c9298b236 100644 +index 369b9d0dc5d4..c9298b236182 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c @@ -566,7 +566,7 @@ mlxsw_sp_port_get_transceiver_overheat_stats(struct mlxsw_sp_port *mlxsw_sp_port @@ -824,5 +824,5 @@ index 369b9d0dc..c9298b236 100644 static int -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch b/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch index d2e9385ffa..ad8bd09c45 100644 --- a/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch +++ b/platform/mellanox/non-upstream-patches/patches/0113-mlxsw-core-Extend-port-module-data-structures-for-li.patch @@ -1,8 +1,8 @@ -From 8e7c606209b97b89b58d21a2c33c319ade1ba867 Mon Sep 17 00:00:00 2001 +From fe0bf4454c709fa1ddb5fa105e88f2d57cb5ef5a Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:27 +0200 -Subject: [PATCH] mlxsw: core: Extend port module data structures for line - cards +Subject: [PATCH backport 5.10 113/182] mlxsw: core: Extend port module data + structures for line cards The port module core is tasked with module operations such as setting power mode policy and reset. The per-module information is currently @@ -21,7 +21,7 @@ Signed-off-by: Ido Schimmel 1 file changed, 157 insertions(+), 66 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index fefb9bb02..2a6630547 100644 +index fc4468a6b0f6..606d89b6f50f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -20,13 +20,19 @@ struct mlxsw_env_module_info { @@ -47,7 +47,7 @@ index fefb9bb02..2a6630547 100644 static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, u8 slot_index, int id, bool *qsfp, bool *cmis) -@@ -407,6 +413,15 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, +@@ -405,6 +411,15 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page); @@ -63,7 +63,7 @@ index fefb9bb02..2a6630547 100644 static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 slot_index, u8 module) { -@@ -423,6 +438,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, +@@ -421,6 +436,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, u8 module, u32 *flags) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -71,7 +71,7 @@ index fefb9bb02..2a6630547 100644 u32 req = *flags; int err; -@@ -430,15 +446,16 @@ int mlxsw_env_reset_module(struct net_device *netdev, +@@ -428,15 +444,16 @@ int mlxsw_env_reset_module(struct net_device *netdev, !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) return 0; @@ -91,7 +91,7 @@ index fefb9bb02..2a6630547 100644 !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) { netdev_err(netdev, "Cannot reset module without \"phy-shared\" flag when shared by multiple ports\n"); err = -EINVAL; -@@ -454,7 +471,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, +@@ -452,7 +469,7 @@ int mlxsw_env_reset_module(struct net_device *netdev, *flags &= ~(ETH_RESET_PHY | (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT)); out: @@ -100,7 +100,7 @@ index fefb9bb02..2a6630547 100644 return err; } EXPORT_SYMBOL(mlxsw_env_reset_module); -@@ -466,13 +483,15 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -464,13 +481,15 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, struct netlink_ext_ack *extack) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -118,7 +118,7 @@ index fefb9bb02..2a6630547 100644 mlxsw_reg_mcion_pack(mcion_pl, slot_index, module); err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); -@@ -491,7 +510,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -489,7 +508,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, params->mode = ETHTOOL_MODULE_POWER_MODE_HIGH; out: @@ -127,7 +127,7 @@ index fefb9bb02..2a6630547 100644 return err; } EXPORT_SYMBOL(mlxsw_env_get_module_power_mode); -@@ -573,6 +592,7 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -571,6 +590,7 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, struct netlink_ext_ack *extack) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -135,7 +135,7 @@ index fefb9bb02..2a6630547 100644 bool low_power; int err = 0; -@@ -582,13 +602,14 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -580,13 +600,14 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, return -EOPNOTSUPP; } @@ -153,7 +153,7 @@ index fefb9bb02..2a6630547 100644 goto out_set_policy; low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO; -@@ -598,9 +619,9 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -596,9 +617,9 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, goto out; out_set_policy: @@ -165,7 +165,7 @@ index fefb9bb02..2a6630547 100644 return err; } EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); -@@ -711,6 +732,7 @@ struct mlxsw_env_module_temp_warn_event { +@@ -709,6 +730,7 @@ struct mlxsw_env_module_temp_warn_event { static void mlxsw_env_mtwe_event_work(struct work_struct *work) { struct mlxsw_env_module_temp_warn_event *event; @@ -173,7 +173,7 @@ index fefb9bb02..2a6630547 100644 struct mlxsw_env *mlxsw_env; int i, sensor_warning; bool is_overheat; -@@ -719,7 +741,7 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) +@@ -717,7 +739,7 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) work); mlxsw_env = event->mlxsw_env; @@ -182,7 +182,7 @@ index fefb9bb02..2a6630547 100644 /* 64-127 of sensor_index are mapped to the port modules * sequentially (module 0 is mapped to sensor_index 64, * module 1 to sensor_index 65 and so on) -@@ -727,9 +749,10 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) +@@ -725,9 +747,10 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) sensor_warning = mlxsw_reg_mtwe_sensor_warning_get(event->mtwe_pl, i + MLXSW_REG_MTMP_MODULE_INDEX_MIN); @@ -196,7 +196,7 @@ index fefb9bb02..2a6630547 100644 if ((is_overheat && sensor_warning) || (!is_overheat && !sensor_warning)) { -@@ -737,21 +760,21 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) +@@ -735,21 +758,21 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work) * warning OR current state in "no warning" and MTWE * does not report warning. */ @@ -224,7 +224,7 @@ index fefb9bb02..2a6630547 100644 } } -@@ -809,6 +832,7 @@ struct mlxsw_env_module_plug_unplug_event { +@@ -807,6 +830,7 @@ struct mlxsw_env_module_plug_unplug_event { static void mlxsw_env_pmpe_event_work(struct work_struct *work) { struct mlxsw_env_module_plug_unplug_event *event; @@ -232,7 +232,7 @@ index fefb9bb02..2a6630547 100644 struct mlxsw_env *mlxsw_env; bool has_temp_sensor; u16 sensor_index; -@@ -818,9 +842,12 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) +@@ -816,9 +840,12 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work) work); mlxsw_env = event->mlxsw_env; @@ -248,7 +248,7 @@ index fefb9bb02..2a6630547 100644 err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, event->slot_index, -@@ -847,12 +874,14 @@ static void +@@ -845,12 +872,14 @@ static void mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, void *priv) { @@ -264,7 +264,7 @@ index fefb9bb02..2a6630547 100644 return; module_status = mlxsw_reg_pmpe_module_status_get(pmpe_pl); -@@ -864,7 +893,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, +@@ -862,7 +891,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, return; event->mlxsw_env = mlxsw_env; @@ -273,7 +273,7 @@ index fefb9bb02..2a6630547 100644 event->module = module; INIT_WORK(&event->work, mlxsw_env_pmpe_event_work); mlxsw_core_schedule_work(&event->work); -@@ -922,10 +951,12 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 slot_ind +@@ -920,10 +949,12 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 slot_ind u8 module, u64 *p_counter) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -289,7 +289,7 @@ index fefb9bb02..2a6630547 100644 return 0; } -@@ -935,10 +966,12 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -933,10 +964,12 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 slot_index, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -305,7 +305,7 @@ index fefb9bb02..2a6630547 100644 } EXPORT_SYMBOL(mlxsw_env_module_port_map); -@@ -946,10 +979,12 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -944,10 +977,12 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 slot_index, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -321,7 +321,7 @@ index fefb9bb02..2a6630547 100644 } EXPORT_SYMBOL(mlxsw_env_module_port_unmap); -@@ -957,15 +992,17 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -955,15 +990,17 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -342,7 +342,7 @@ index fefb9bb02..2a6630547 100644 goto out_inc; /* Transition to high power mode following first port using the module -@@ -977,9 +1014,9 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -975,9 +1012,9 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index, goto out_unlock; out_inc: @@ -354,7 +354,7 @@ index fefb9bb02..2a6630547 100644 return err; } EXPORT_SYMBOL(mlxsw_env_module_port_up); -@@ -988,16 +1025,18 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -986,16 +1023,18 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, u8 module) { struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); @@ -377,7 +377,7 @@ index fefb9bb02..2a6630547 100644 goto out_unlock; /* Transition to low power mode following last port using the module -@@ -1007,38 +1046,83 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -1005,38 +1044,83 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index, NULL); out_unlock: @@ -475,7 +475,7 @@ index fefb9bb02..2a6630547 100644 *p_env = env; err = mlxsw_env_temp_warn_event_register(mlxsw_core); -@@ -1049,13 +1133,17 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1047,13 +1131,17 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) if (err) goto err_module_plug_event_register; @@ -495,7 +495,7 @@ index fefb9bb02..2a6630547 100644 if (err) goto err_temp_event_enable; -@@ -1067,7 +1155,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1065,7 +1153,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) err_module_plug_event_register: mlxsw_env_temp_warn_event_unregister(env); err_temp_warn_event_register: @@ -506,7 +506,7 @@ index fefb9bb02..2a6630547 100644 kfree(env); return err; } -@@ -1078,6 +1168,7 @@ void mlxsw_env_fini(struct mlxsw_env *env) +@@ -1076,6 +1166,7 @@ void mlxsw_env_fini(struct mlxsw_env *env) /* Make sure there is no more event work scheduled. */ mlxsw_core_flush_owq(); mlxsw_env_temp_warn_event_unregister(env); @@ -516,5 +516,5 @@ index fefb9bb02..2a6630547 100644 kfree(env); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch b/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch index 77ebf26108..d8e3d30a4b 100644 --- a/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch +++ b/platform/mellanox/non-upstream-patches/patches/0114-mlxsw-core-Move-port-module-events-enablement-to-a-s.patch @@ -1,8 +1,8 @@ -From 9eb9b3172a238d5818d2925e2db6b0f686b31411 Mon Sep 17 00:00:00 2001 +From 3c3be37747cb938fff1178f88d611eb00159297b Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:28 +0200 -Subject: [PATCH] mlxsw: core: Move port module events enablement to a separate - function +Subject: [PATCH backport 5.10 114/182] mlxsw: core: Move port module events + enablement to a separate function Use a separate function for enablement of port module events such plug/unplug and temperature threshold crossing. The motivation is to @@ -15,10 +15,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 2a6630547..94d44db1a 100644 +index 606d89b6f50f..4553dfa68f96 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -1089,6 +1089,32 @@ static void mlxsw_env_line_cards_free(struct mlxsw_env *env) +@@ -1087,6 +1087,32 @@ static void mlxsw_env_line_cards_free(struct mlxsw_env *env) kfree(env->line_cards[i]); } @@ -51,7 +51,7 @@ index 2a6630547..94d44db1a 100644 int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) { u8 module_count, num_of_slots, max_module_count; -@@ -1137,20 +1163,17 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1135,20 +1161,17 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) * is to be set after line card is activated. */ env->line_cards[0]->module_count = num_of_slots ? 0 : module_count; @@ -79,7 +79,7 @@ index 2a6630547..94d44db1a 100644 mlxsw_env_module_plug_event_unregister(env); err_module_plug_event_register: mlxsw_env_temp_warn_event_unregister(env); -@@ -1164,6 +1187,7 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1162,6 +1185,7 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) void mlxsw_env_fini(struct mlxsw_env *env) { @@ -88,5 +88,5 @@ index 2a6630547..94d44db1a 100644 /* Make sure there is no more event work scheduled. */ mlxsw_core_flush_owq(); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch b/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch index 1365785ff9..b5876fa612 100644 --- a/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch +++ b/platform/mellanox/non-upstream-patches/patches/0115-mlxsw-core_hwmon-Split-gearbox-initialization.patch @@ -1,7 +1,8 @@ -From 4d15dd7f69b89a370731b08cb3f13e5dd591c189 Mon Sep 17 00:00:00 2001 +From 1a451b46c16494cfa38bb47495ad632626502681 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:29 +0200 -Subject: [PATCH] mlxsw: core_hwmon: Split gearbox initialization +Subject: [PATCH backport 5.10 115/182] mlxsw: core_hwmon: Split gearbox + initialization Split gearbox initialization in two functions - the first one is to be used for gearbox configuration validation, the second for creation of @@ -24,7 +25,7 @@ Signed-off-by: Ido Schimmel 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 5df54a5bf..7061c18b7 100644 +index 5df54a5bf292..7061c18b7edc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -700,13 +700,11 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) @@ -117,5 +118,5 @@ index 5df54a5bf..7061c18b7 100644 kfree(mlxsw_hwmon); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch b/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch index 2c1eafe703..7c37fc22bb 100644 --- a/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch +++ b/platform/mellanox/non-upstream-patches/patches/0116-mlxsw-core_hwmon-Extend-internal-structures-to-suppo.patch @@ -1,8 +1,8 @@ -From 9780cd7afe3455d0ee428f5009514780e858c133 Mon Sep 17 00:00:00 2001 +From a18e5112ed12150e245e275e187ecd6d87d66b0e Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:30 +0200 -Subject: [PATCH] mlxsw: core_hwmon: Extend internal structures to support - multi hwmon objects +Subject: [PATCH backport 5.10 116/182] mlxsw: core_hwmon: Extend internal + structures to support multi hwmon objects Currently, mlxsw supports a single hwmon device and registers it with attributes corresponding to the various objects found on the main @@ -32,7 +32,7 @@ Signed-off-by: Ido Schimmel 1 file changed, 112 insertions(+), 80 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 7061c18b7..31b370862 100644 +index 7061c18b7edc..31b370862131 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -27,7 +27,7 @@ @@ -537,5 +537,5 @@ index 7061c18b7..31b370862 100644 kfree(mlxsw_hwmon); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch b/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch index 43208f6d2c..bc0bc548a1 100644 --- a/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch +++ b/platform/mellanox/non-upstream-patches/patches/0117-mlxsw-core_hwmon-Introduce-slot-parameter-in-hwmon-i.patch @@ -1,8 +1,8 @@ -From aa8cdb2df37cbfb7bb37f90879d385428e32ae23 Mon Sep 17 00:00:00 2001 +From 15f2f79bffb77324a389b7e174f32406924d3a3a Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:31 +0200 -Subject: [PATCH] mlxsw: core_hwmon: Introduce slot parameter in hwmon - interfaces +Subject: [PATCH backport 5.10 117/182] mlxsw: core_hwmon: Introduce slot + parameter in hwmon interfaces Add 'slot' parameter to 'mlxsw_hwmon_dev' structure. Use this parameter in mlxsw_reg_mtmp_pack(), mlxsw_reg_mtbr_pack() and @@ -18,7 +18,7 @@ Signed-off-by: Ido Schimmel 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 31b370862..0d7edabf1 100644 +index 31b370862131..0d7edabf19a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -50,6 +50,7 @@ struct mlxsw_hwmon_dev { @@ -125,5 +125,5 @@ index 31b370862..0d7edabf1 100644 err = mlxsw_hwmon_temp_init(mlxsw_hwmon->main); if (err) -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch b/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch index f88c8721bc..7d0491b840 100644 --- a/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch +++ b/platform/mellanox/non-upstream-patches/patches/0118-mlxsw-core_hwmon-Extend-hwmon-device-with-gearbox-ma.patch @@ -1,8 +1,8 @@ -From 94d3b63c64fc202bfe525cc3b500c23e92d38fbf Mon Sep 17 00:00:00 2001 +From c627292817e68e29abdf5fd9be93340251d71f7a Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:32 +0200 -Subject: [PATCH] mlxsw: core_hwmon: Extend hwmon device with gearbox mapping - field +Subject: [PATCH backport 5.10 118/182] mlxsw: core_hwmon: Extend hwmon device + with gearbox mapping field Add gearbox mapping field to 'mlxsw_hwmon_dev' structure. It should provide the mapping for gearbox sensor indexes, given gearbox number. @@ -17,7 +17,7 @@ Signed-off-by: Ido Schimmel 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 0d7edabf1..6af23f472 100644 +index 0d7edabf19a4..6af23f4724e4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -32,10 +32,11 @@ struct mlxsw_hwmon_attr { @@ -132,5 +132,5 @@ index 0d7edabf1..6af23f472 100644 sensor_index, true, true); err = mlxsw_reg_write(mlxsw_hwmon->core, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch b/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch index cf6199aa18..0ff18202c1 100644 --- a/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch +++ b/platform/mellanox/non-upstream-patches/patches/0119-mlxsw-core_thermal-Extend-internal-structures-to-sup.patch @@ -1,8 +1,8 @@ -From ab0f9b9dd1f7326242eee0b0a643d6d34e557ae3 Mon Sep 17 00:00:00 2001 +From 8851888004e82e73629f031e8af592c36b12c469 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:33 +0200 -Subject: [PATCH] mlxsw: core_thermal: Extend internal structures to support - multi thermal areas +Subject: [PATCH backport 5.10 119/182] mlxsw: core_thermal: Extend internal + structures to support multi thermal areas Introduce intermediate level for thermal zones areas. Currently all thermal zones are associated with thermal objects located @@ -29,10 +29,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 3f9062f1c..77a484a55 100644 +index 4f84c4bb66af..5f8b1e92475b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -91,6 +91,15 @@ struct mlxsw_thermal_module { +@@ -83,6 +83,15 @@ struct mlxsw_thermal_module { struct thermal_zone_device *tzdev; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; int module; /* Module or gearbox number */ @@ -48,7 +48,7 @@ index 3f9062f1c..77a484a55 100644 }; struct mlxsw_thermal { -@@ -101,10 +110,7 @@ struct mlxsw_thermal { +@@ -93,10 +102,7 @@ struct mlxsw_thermal { struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; @@ -60,7 +60,7 @@ index 3f9062f1c..77a484a55 100644 unsigned int tz_highest_score; struct thermal_zone_device *tz_highest_dev; }; -@@ -159,13 +165,15 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, +@@ -151,13 +157,15 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, * EEPROM if we got valid thresholds from MTMP. */ if (!emerg_temp || !crit_temp) { @@ -78,7 +78,7 @@ index 3f9062f1c..77a484a55 100644 SFP_TEMP_HIGH_ALARM, &emerg_temp); if (err) -@@ -432,15 +440,16 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, +@@ -424,15 +432,16 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, static void mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core, @@ -98,7 +98,7 @@ index 3f9062f1c..77a484a55 100644 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); if (err) { /* Set temperature and thresholds to zero to avoid passing -@@ -471,6 +480,7 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, +@@ -463,6 +472,7 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, /* Read module temperature and thresholds. */ mlxsw_thermal_module_temp_and_thresholds_get(thermal->core, @@ -106,7 +106,7 @@ index 3f9062f1c..77a484a55 100644 sensor_index, &temp, &crit_temp, &emerg_temp); *p_temp = temp; -@@ -585,7 +595,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, +@@ -577,7 +587,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, int err; index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module; @@ -115,7 +115,7 @@ index 3f9062f1c..77a484a55 100644 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); if (err) -@@ -745,25 +755,28 @@ static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) +@@ -704,25 +714,28 @@ static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) static int mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, @@ -147,7 +147,7 @@ index 3f9062f1c..77a484a55 100644 &crit_temp, &emerg_temp); /* Update trip point according to the module data. */ return mlxsw_thermal_module_trips_update(dev, core, module_tz, -@@ -781,34 +794,39 @@ static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz) +@@ -740,34 +753,39 @@ static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz) static int mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, @@ -198,7 +198,7 @@ index 3f9062f1c..77a484a55 100644 if (!module_tz->parent) continue; err = mlxsw_thermal_module_tz_init(module_tz); -@@ -820,20 +838,21 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, +@@ -779,20 +797,21 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, err_thermal_module_tz_init: err_thermal_module_init: @@ -227,7 +227,7 @@ index 3f9062f1c..77a484a55 100644 } static int -@@ -869,7 +888,8 @@ mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) +@@ -828,7 +847,8 @@ mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) static int mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, @@ -237,7 +237,7 @@ index 3f9062f1c..77a484a55 100644 { enum mlxsw_reg_mgpir_device_type device_type; struct mlxsw_thermal_module *gearbox_tz; -@@ -889,19 +909,20 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -848,19 +868,20 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, !gbox_num) return 0; @@ -265,7 +265,7 @@ index 3f9062f1c..77a484a55 100644 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); if (err) goto err_thermal_gearbox_tz_init; -@@ -911,19 +932,20 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -870,19 +891,20 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, err_thermal_gearbox_tz_init: for (i--; i >= 0; i--) @@ -292,7 +292,7 @@ index 3f9062f1c..77a484a55 100644 } int mlxsw_thermal_init(struct mlxsw_core *core, -@@ -943,9 +965,16 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -902,9 +924,16 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (!thermal) return -ENOMEM; @@ -309,7 +309,7 @@ index 3f9062f1c..77a484a55 100644 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); if (err) { -@@ -1012,11 +1041,11 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -970,11 +999,11 @@ int mlxsw_thermal_init(struct mlxsw_core *core, goto err_thermal_zone_device_register; } @@ -323,7 +323,7 @@ index 3f9062f1c..77a484a55 100644 if (err) goto err_thermal_gearboxes_init; -@@ -1028,9 +1057,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -986,9 +1015,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core, return 0; err_thermal_zone_device_enable: @@ -335,7 +335,7 @@ index 3f9062f1c..77a484a55 100644 err_thermal_modules_init: if (thermal->tzdev) { thermal_zone_device_unregister(thermal->tzdev); -@@ -1043,6 +1072,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -1001,6 +1030,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, thermal_cooling_device_unregister(thermal->cdevs[i]); err_reg_write: err_reg_query: @@ -344,7 +344,7 @@ index 3f9062f1c..77a484a55 100644 devm_kfree(dev, thermal); return err; } -@@ -1051,8 +1082,8 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) +@@ -1009,8 +1040,8 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) { int i; @@ -355,7 +355,7 @@ index 3f9062f1c..77a484a55 100644 if (thermal->tzdev) { thermal_zone_device_unregister(thermal->tzdev); thermal->tzdev = NULL; -@@ -1065,5 +1096,6 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) +@@ -1023,5 +1054,6 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) } } @@ -363,5 +363,5 @@ index 3f9062f1c..77a484a55 100644 devm_kfree(thermal->bus_info->dev, thermal); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch b/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch index 299d03e4c5..b0cb21b8a4 100644 --- a/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch +++ b/platform/mellanox/non-upstream-patches/patches/0120-mlxsw-core_thermal-Split-gearbox-initialization.patch @@ -1,7 +1,8 @@ -From 219381cde0a7294834aff7e3f30584182b26a2b6 Mon Sep 17 00:00:00 2001 +From ed83386ce79974230c5fa59245efe760046d944c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:34 +0200 -Subject: [PATCH] mlxsw: core_thermal: Split gearbox initialization +Subject: [PATCH backport 5.10 120/182] mlxsw: core_thermal: Split gearbox + initialization Split gearbox initialization in two routines - the first one is to be used for gearbox configuration validation, the second for creation of @@ -26,10 +27,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 77a484a55..a8ecd8fea 100644 +index 5f8b1e92475b..313856b88f6c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -887,15 +887,12 @@ mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) +@@ -846,15 +846,12 @@ mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) } static int @@ -47,7 +48,7 @@ index 77a484a55..a8ecd8fea 100644 int err; mlxsw_reg_mgpir_pack(mgpir_pl, 0); -@@ -905,8 +902,11 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -864,8 +861,11 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL, NULL); @@ -61,7 +62,7 @@ index 77a484a55..a8ecd8fea 100644 return 0; area->tz_gearbox_num = gbox_num; -@@ -916,6 +916,26 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -875,6 +875,26 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, if (!area->tz_gearbox_arr) return -ENOMEM; @@ -88,7 +89,7 @@ index 77a484a55..a8ecd8fea 100644 for (i = 0; i < area->tz_gearbox_num; i++) { gearbox_tz = &area->tz_gearbox_arr[i]; memcpy(gearbox_tz->trips, default_thermal_trips, -@@ -933,7 +953,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -892,7 +912,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, err_thermal_gearbox_tz_init: for (i--; i >= 0; i--) mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); @@ -96,7 +97,7 @@ index 77a484a55..a8ecd8fea 100644 return err; } -@@ -945,7 +964,6 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, +@@ -904,7 +923,6 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, for (i = area->tz_gearbox_num - 1; i >= 0; i--) mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); @@ -104,7 +105,7 @@ index 77a484a55..a8ecd8fea 100644 } int mlxsw_thermal_init(struct mlxsw_core *core, -@@ -1045,6 +1063,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -1003,6 +1021,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (err) goto err_thermal_modules_init; @@ -115,7 +116,7 @@ index 77a484a55..a8ecd8fea 100644 err = mlxsw_thermal_gearboxes_init(dev, core, thermal, thermal->main); if (err) goto err_thermal_gearboxes_init; -@@ -1059,6 +1081,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -1017,6 +1039,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, err_thermal_zone_device_enable: mlxsw_thermal_gearboxes_fini(thermal, thermal->main); err_thermal_gearboxes_init: @@ -124,7 +125,7 @@ index 77a484a55..a8ecd8fea 100644 mlxsw_thermal_modules_fini(thermal, thermal->main); err_thermal_modules_init: if (thermal->tzdev) { -@@ -1083,6 +1107,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) +@@ -1041,6 +1065,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) int i; mlxsw_thermal_gearboxes_fini(thermal, thermal->main); @@ -133,5 +134,5 @@ index 77a484a55..a8ecd8fea 100644 if (thermal->tzdev) { thermal_zone_device_unregister(thermal->tzdev); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch b/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch index 7157375e9c..8e9d6e621a 100644 --- a/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0121-mlxsw-core_thermal-Extend-thermal-area-with-gearbox-.patch @@ -1,8 +1,8 @@ -From 9c8482e7c487a0a19f0d6d5df06c70aa529d3023 Mon Sep 17 00:00:00 2001 +From 13a7ef7fcdc09def9d9756510f49da82283d78df Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:35 +0200 -Subject: [PATCH] mlxsw: core_thermal: Extend thermal area with gearbox mapping - field +Subject: [PATCH backport 5.10 121/182] mlxsw: core_thermal: Extend thermal + area with gearbox mapping field Add gearbox mapping field 'gearbox_sensor_map' to 'mlxsw_thermal_module' structure. It should provide the mapping for @@ -18,10 +18,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index a8ecd8fea..2efedd35b 100644 +index 313856b88f6c..bde5489d9240 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -85,9 +85,11 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = { +@@ -77,9 +77,11 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = { #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1) struct mlxsw_thermal; @@ -33,7 +33,7 @@ index a8ecd8fea..2efedd35b 100644 struct thermal_zone_device *tzdev; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; int module; /* Module or gearbox number */ -@@ -100,6 +102,7 @@ struct mlxsw_thermal_area { +@@ -92,6 +94,7 @@ struct mlxsw_thermal_area { struct mlxsw_thermal_module *tz_gearbox_arr; u8 tz_gearbox_num; u8 slot_index; @@ -41,7 +41,7 @@ index a8ecd8fea..2efedd35b 100644 }; struct mlxsw_thermal { -@@ -594,7 +597,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, +@@ -586,7 +589,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, int temp; int err; @@ -50,7 +50,7 @@ index a8ecd8fea..2efedd35b 100644 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false); err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); -@@ -768,6 +771,7 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, +@@ -727,6 +730,7 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, if (module_tz->parent) return 0; module_tz->module = module; @@ -58,7 +58,7 @@ index a8ecd8fea..2efedd35b 100644 module_tz->slot_index = area->slot_index; module_tz->parent = thermal; memcpy(module_tz->trips, default_thermal_trips, -@@ -892,36 +896,48 @@ mlxsw_thermal_gearboxes_main_init(struct device *dev, struct mlxsw_core *core, +@@ -851,36 +855,48 @@ mlxsw_thermal_gearboxes_main_init(struct device *dev, struct mlxsw_core *core, { enum mlxsw_reg_mgpir_device_type device_type; char mgpir_pl[MLXSW_REG_MGPIR_LEN]; @@ -114,7 +114,7 @@ index a8ecd8fea..2efedd35b 100644 kfree(area->tz_gearbox_arr); } -@@ -942,6 +958,7 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, +@@ -901,6 +917,7 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, sizeof(thermal->trips)); gearbox_tz->module = i; gearbox_tz->parent = thermal; @@ -123,5 +123,5 @@ index a8ecd8fea..2efedd35b 100644 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); if (err) -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch b/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch index d6aa7a49ca..c08ac6d235 100644 --- a/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch +++ b/platform/mellanox/non-upstream-patches/patches/0122-mlxsw-core_thermal-Add-line-card-id-prefix-to-line-c.patch @@ -1,8 +1,8 @@ -From 3f3548804a89b7fbe15fa92ea8686f08b990b083 Mon Sep 17 00:00:00 2001 +From 901e0ed6354f716b23854ad2f8e4eeb9a74414ab Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:36 +0200 -Subject: [PATCH] mlxsw: core_thermal: Add line card id prefix to line card - thermal zone name +Subject: [PATCH backport 5.10 122/182] mlxsw: core_thermal: Add line card id + prefix to line card thermal zone name Add prefix "lc#n" to thermal zones associated with the thermal objects found on line cards. @@ -21,10 +21,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 2efedd35b..421555d3f 100644 +index bde5489d9240..4964c9164c2d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -730,8 +730,12 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) +@@ -689,8 +689,12 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; int err; @@ -39,7 +39,7 @@ index 2efedd35b..421555d3f 100644 module_tz->tzdev = thermal_zone_device_register(tz_name, MLXSW_THERMAL_NUM_TRIPS, MLXSW_THERMAL_TRIP_MASK, -@@ -865,8 +869,12 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) +@@ -824,8 +828,12 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; int ret; @@ -55,5 +55,5 @@ index 2efedd35b..421555d3f 100644 MLXSW_THERMAL_NUM_TRIPS, MLXSW_THERMAL_TRIP_MASK, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch b/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch index 4238275988..ebe8c96cf7 100644 --- a/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch +++ b/platform/mellanox/non-upstream-patches/patches/0123-mlxsw-core_thermal-Use-exact-name-of-cooling-devices.patch @@ -1,8 +1,8 @@ -From 34251eb77f3f50ac2d574876f33c65d8d2c70e9c Mon Sep 17 00:00:00 2001 +From 7e5f922bac5153137a8b1f486728d9d95b4922bc Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Tue, 14 Dec 2021 10:57:37 +0200 -Subject: [PATCH] mlxsw: core_thermal: Use exact name of cooling devices for - binding +Subject: [PATCH backport 5.10 123/182] mlxsw: core_thermal: Use exact name of + cooling devices for binding Modular system supports additional cooling devices "mlxreg_fan1", "mlxreg_fan2", etcetera. Thermal zones in "mlxsw" driver should be @@ -17,10 +17,10 @@ Signed-off-by: Ido Schimmel 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index 421555d3f..a20a91285 100644 +index 4964c9164c2d..64c6a78f3aa0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -141,8 +141,7 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, +@@ -133,8 +133,7 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, /* Allow mlxsw thermal zone binding to an external cooling device */ for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) { @@ -31,5 +31,5 @@ index 421555d3f..a20a91285 100644 } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch b/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch index 711f4d62dc..624ab7170d 100644 --- a/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch +++ b/platform/mellanox/non-upstream-patches/patches/0124-mlxsw-core_thermal-Use-common-define-for-thermal-zon.patch @@ -1,20 +1,21 @@ -From 56370efd25ad5b77b87645d779dd577674c12864 Mon Sep 17 00:00:00 2001 +From 8d06868f51917926f99299eaac26d6f86eff3593 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak -Date: Tue, 14 Dec 2021 10:57:38 +0200 -Subject: [PATCH] mlxsw: core_thermal: Use common define for thermal zone name - length +Date: Wed, 13 Apr 2022 18:17:33 +0300 +Subject: [PATCH backport 5.10 124/182] mlxsw: core_thermal: Use common define + for thermal zone name length Replace internal define 'MLXSW_THERMAL_ZONE_MAX_NAME' by common 'THERMAL_NAME_LENGTH'. Signed-off-by: Vadim Pasternak Signed-off-by: Ido Schimmel +Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index a20a91285..e860cade5 100644 +index 64c6a78f3aa0..b9253c9f70d9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -21,7 +21,6 @@ @@ -24,8 +25,8 @@ index a20a91285..e860cade5 100644 -#define MLXSW_THERMAL_ZONE_MAX_NAME 16 #define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0) #define MLXSW_THERMAL_MAX_STATE 10 - #define MLXSW_THERMAL_MAX_DUTY 255 -@@ -726,7 +725,7 @@ static const struct thermal_cooling_device_ops mlxsw_cooling_ops = { + #define MLXSW_THERMAL_MIN_STATE 2 +@@ -685,7 +684,7 @@ static const struct thermal_cooling_device_ops mlxsw_cooling_ops = { static int mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) { @@ -34,7 +35,7 @@ index a20a91285..e860cade5 100644 int err; if (module_tz->slot_index) -@@ -865,7 +864,7 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal, +@@ -824,7 +823,7 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal, static int mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) { @@ -44,5 +45,5 @@ index a20a91285..e860cade5 100644 if (gearbox_tz->slot_index) -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch b/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch index 849645848a..13d23671a1 100644 --- a/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch +++ b/platform/mellanox/non-upstream-patches/patches/0125-devlink-add-support-to-create-line-card-and-expose-t.patch @@ -1,7 +1,8 @@ -From 242d6e2b00a25ec4184a63cec76c9f7f7c235594 Mon Sep 17 00:00:00 2001 +From 36a2e4e93d7d1ca2ed670b4cf827400ba367e290 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 22 Dec 2021 08:57:27 +0000 -Subject: [PATCH] devlink: add support to create line card and expose to user +Subject: [PATCH backport 5.10 125/182] devlink: add support to create line + card and expose to user Extend the devlink API so the driver is going to be able to create and destroy linecard instances. There can be multiple line cards per devlink @@ -16,7 +17,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 339 insertions(+), 1 deletion(-) diff --git a/include/net/devlink.h b/include/net/devlink.h -index b01bb9bca..e8f046590 100644 +index b01bb9bca5a2..e8f046590579 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -31,6 +31,7 @@ struct devlink_dev_stats { @@ -70,7 +71,7 @@ index b01bb9bca..e8f046590 100644 u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h -index cf89c318f..ff07ad596 100644 +index cf89c318f2ac..ff07ad596035 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -126,6 +126,16 @@ enum devlink_command { @@ -110,7 +111,7 @@ index cf89c318f..ff07ad596 100644 __DEVLINK_ATTR_MAX, diff --git a/net/core/devlink.c b/net/core/devlink.c -index 72047750d..645fe0612 100644 +index 72047750dcd9..645fe0612b53 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -91,6 +91,25 @@ static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ @@ -527,5 +528,5 @@ index 72047750d..645fe0612 100644 u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch b/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch index e5ea9d5d23..d95308acab 100644 --- a/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch +++ b/platform/mellanox/non-upstream-patches/patches/0126-devlink-implement-line-card-provisioning.patch @@ -1,7 +1,8 @@ -From b0a30f401ca5d69f3cd78a0bf6dd1471f7aea0be Mon Sep 17 00:00:00 2001 +From 37d223fa389636092d519ca903f186d608eed3c8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 31 Dec 2020 17:35:08 +0100 -Subject: [PATCH] devlink: implement line card provisioning +Subject: [PATCH backport 5.10 126/182] devlink: implement line card + provisioning In order to be able to configure all needed stuff on a port/netdevice of a line card without the line card being present, introduce line card @@ -28,7 +29,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 346 insertions(+), 21 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h -index e8f046590..44b60085e 100644 +index e8f046590579..44b60085ec16 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -142,11 +142,43 @@ struct devlink_port { @@ -93,7 +94,7 @@ index e8f046590..44b60085e 100644 u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h -index ff07ad596..d88336645 100644 +index ff07ad596035..d8833664522f 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -334,6 +334,18 @@ enum devlink_reload_limit { @@ -126,7 +127,7 @@ index ff07ad596..d88336645 100644 /* add new attributes above here, update the policy in devlink.c */ diff --git a/net/core/devlink.c b/net/core/devlink.c -index 645fe0612..943973ffc 100644 +index 645fe0612b53..943973ffc450 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -265,8 +265,10 @@ devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info) @@ -550,5 +551,5 @@ index 645fe0612..943973ffc 100644 u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch b/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch index 857f84b45b..548b8f4a6a 100644 --- a/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch +++ b/platform/mellanox/non-upstream-patches/patches/0127-devlink-implement-line-card-active-state.patch @@ -1,7 +1,8 @@ -From 999c148a0a19a6a6c96dbc5b6615285d80c28de9 Mon Sep 17 00:00:00 2001 +From 9edffb671d73df181e382930bda0a3870e6ac120 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 6 Jan 2021 16:03:43 +0100 -Subject: [PATCH] devlink: implement line card active state +Subject: [PATCH backport 5.10 127/182] devlink: implement line card active + state Allow driver to mark a linecard as active. Expose this state to the userspace over devlink netlink interface with proper notifications. @@ -14,7 +15,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 40 insertions(+) diff --git a/include/net/devlink.h b/include/net/devlink.h -index 44b60085e..d9b2b559c 100644 +index 44b60085ec16..d9b2b559c9a2 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -157,6 +157,7 @@ struct devlink_linecard { @@ -35,7 +36,7 @@ index 44b60085e..d9b2b559c 100644 u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h -index d88336645..5ace55666 100644 +index d8833664522f..5ace55666d27 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -341,6 +341,7 @@ enum devlink_linecard_state { @@ -47,7 +48,7 @@ index d88336645..5ace55666 100644 __DEVLINK_LINECARD_STATE_MAX, DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1 diff --git a/net/core/devlink.c b/net/core/devlink.c -index 943973ffc..724633810 100644 +index 943973ffc450..724633810758 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -9001,6 +9001,42 @@ void devlink_linecard_provision_fail(struct devlink_linecard *linecard) @@ -94,5 +95,5 @@ index 943973ffc..724633810 100644 u32 size, u16 ingress_pools_count, u16 egress_pools_count, u16 ingress_tc_count, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch b/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch index eeae6ea472..41628c616e 100644 --- a/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch +++ b/platform/mellanox/non-upstream-patches/patches/0128-devlink-add-port-to-line-card-relationship-set.patch @@ -1,7 +1,8 @@ -From ce052dd9aec77733b55fe1285a9be5c4cbcc87b3 Mon Sep 17 00:00:00 2001 +From fb810d890bd142a7cfc14fb7e5f1519eee366208 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 22 Dec 2021 14:10:14 +0000 -Subject: [PATCH] devlink: add port to line card relationship set +Subject: [PATCH backport 5.10 128/182] devlink: add port to line card + relationship set In order to properly inform user about relationship between port and line card, introduce a driver API to set line card for a port. Use this @@ -16,7 +17,7 @@ Signed-off-by: Jiri Pirko 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h -index d9b2b559c..3d4ceb290 100644 +index d9b2b559c9a2..3d4ceb2902b8 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -140,6 +140,8 @@ struct devlink_port { @@ -38,7 +39,7 @@ index d9b2b559c..3d4ceb290 100644 devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, const struct devlink_linecard_ops *ops, void *priv); diff --git a/net/core/devlink.c b/net/core/devlink.c -index 724633810..b43e93ccc 100644 +index 724633810758..b43e93ccc672 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -905,6 +905,10 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, @@ -97,5 +98,5 @@ index 724633810..b43e93ccc 100644 case DEVLINK_PORT_FLAVOUR_CPU: case DEVLINK_PORT_FLAVOUR_DSA: -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch b/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch index 9efc8b2aa0..3ea32fc35e 100644 --- a/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch +++ b/platform/mellanox/non-upstream-patches/patches/0129-devlink-introduce-linecard-info-get-message.patch @@ -1,7 +1,8 @@ -From fdc91e1289c5e491e93f7d7a872d2d656d1d0e7f Mon Sep 17 00:00:00 2001 +From 13e29cf4f38755ae717615071b07cd438e8819e6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 19 Feb 2021 09:36:15 +0100 -Subject: [PATCH] devlink: introduce linecard info get message +Subject: [PATCH backport 5.10 129/182] devlink: introduce linecard info get + message Allow the driver to provide per line card info get op to fill-up info, similar to the "devlink dev info". @@ -14,7 +15,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 140 insertions(+), 5 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h -index 3d4ceb290..059bed6ae 100644 +index 3d4ceb2902b8..059bed6aef3c 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -162,6 +162,8 @@ struct devlink_linecard { @@ -53,7 +54,7 @@ index 3d4ceb290..059bed6ae 100644 /** * struct devlink_region_ops - Region operations diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h -index 5ace55666..2c9f7d584 100644 +index 5ace55666d27..2c9f7d584b48 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -136,6 +136,8 @@ enum devlink_command { @@ -74,7 +75,7 @@ index 5ace55666..2c9f7d584 100644 /* add new attributes above here, update the policy in devlink.c */ diff --git a/net/core/devlink.c b/net/core/devlink.c -index b43e93ccc..04f8038f8 100644 +index b43e93ccc672..04f8038f8e23 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -1245,6 +1245,10 @@ struct devlink_linecard_type { @@ -241,5 +242,5 @@ index b43e93ccc..04f8038f8 100644 .cmd = DEVLINK_CMD_SB_GET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch b/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch index f6ea2b2f49..d2f92f77e3 100644 --- a/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch +++ b/platform/mellanox/non-upstream-patches/patches/0130-devlink-introduce-linecard-info-get-message.patch @@ -1,7 +1,8 @@ -From 7a39de95203f7dc033bdc81703989d627f2ca0de Mon Sep 17 00:00:00 2001 +From b8243b5c2fdb9871cd55a864b95e197ced9ad532 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 22 Dec 2021 15:11:36 +0000 -Subject: [PATCH] devlink: introduce linecard info get message +Subject: [PATCH backport 5.10 130/182] devlink: introduce linecard info get + message Allow the driver to provide per line card info get op to fill-up info, similar to the "devlink dev info". @@ -23,7 +24,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 182 insertions(+) diff --git a/include/net/devlink.h b/include/net/devlink.h -index 059bed6ae..06b61c1d7 100644 +index 059bed6aef3c..06b61c1d7938 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -160,9 +160,11 @@ struct devlink_linecard { @@ -63,7 +64,7 @@ index 059bed6ae..06b61c1d7 100644 const char *type); void devlink_linecard_provision_clear(struct devlink_linecard *linecard); diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h -index 2c9f7d584..bac94c3c1 100644 +index 2c9f7d584b48..bac94c3c1bb0 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -569,6 +569,10 @@ enum devlink_attr { @@ -78,7 +79,7 @@ index 2c9f7d584..bac94c3c1 100644 /* add new attributes above here, update the policy in devlink.c */ diff --git a/net/core/devlink.c b/net/core/devlink.c -index 04f8038f8..ca014f40a 100644 +index 04f8038f8e23..ca014f40ac02 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -1249,6 +1249,59 @@ struct devlink_info_req { @@ -311,5 +312,5 @@ index 04f8038f8..ca014f40a 100644 linecard->type = NULL; devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch b/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch index 446d2c8d8a..179d95f443 100644 --- a/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch +++ b/platform/mellanox/non-upstream-patches/patches/0131-mlxsw-reg-Add-Ports-Mapping-event-Configuration-Regi.patch @@ -1,7 +1,8 @@ -From ec8e91d320c8cccb8ad59663d2d59810ea5aecb9 Mon Sep 17 00:00:00 2001 +From 4a49468e7fc7e94a83703215445d9b3919642eb9 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 29 Jan 2021 08:45:09 +0100 -Subject: [PATCH] mlxsw: reg: Add Ports Mapping event Configuration Register +Subject: [PATCH backport 5.10 131/182] mlxsw: reg: Add Ports Mapping event + Configuration Register The PMECR register use to enable/disable event trigger in case of local port mapping change. @@ -12,7 +13,7 @@ Signed-off-by: Jiri Pirko 1 file changed, 64 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 9de037b9a..42169957c 100644 +index 98c627ffe039..93e3366cfcb9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5524,6 +5524,69 @@ static inline void mlxsw_reg_pplr_pack(char *payload, u8 local_port, @@ -85,7 +86,7 @@ index 9de037b9a..42169957c 100644 /* PMPE - Port Module Plug/Unplug Event Register * --------------------------------------------- * This register reports any operational status change of a module. -@@ -11376,6 +11439,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { +@@ -11375,6 +11438,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(pspa), MLXSW_REG(pmaos), MLXSW_REG(pplr), @@ -94,5 +95,5 @@ index 9de037b9a..42169957c 100644 MLXSW_REG(pddr), MLXSW_REG(pmtm), -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch b/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch index b0d35e8387..730e1f8980 100644 --- a/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch +++ b/platform/mellanox/non-upstream-patches/patches/0132-mlxsw-reg-Add-Management-DownStream-Device-Query-Reg.patch @@ -1,7 +1,8 @@ -From e46f9bfa89b8b9caced49a74db695e86e963b35d Mon Sep 17 00:00:00 2001 +From 5d8d4899f493e3b18712fc96a45eb020985740b1 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 3 Jan 2022 10:20:49 +0000 -Subject: [PATCH] mlxsw: reg: Add Management DownStream Device Query Register +Subject: [PATCH backport 5.10 132/182] mlxsw: reg: Add Management DownStream + Device Query Register The MDDQ register allows to query the DownStream device properties. @@ -11,10 +12,10 @@ Signed-off-by: Jiri Pirko 1 file changed, 234 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 42169957c..d5301bd6f 100644 +index 93e3366cfcb9..ad7faeb95646 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10297,6 +10297,239 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, +@@ -10296,6 +10296,239 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); } @@ -254,7 +255,7 @@ index 42169957c..d5301bd6f 100644 /* MFDE - Monitoring FW Debug Register * ----------------------------------- */ -@@ -11496,6 +11729,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { +@@ -11495,6 +11728,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mtptpt), MLXSW_REG(mfgd), MLXSW_REG(mgpir), @@ -263,5 +264,5 @@ index 42169957c..d5301bd6f 100644 MLXSW_REG(tngcr), MLXSW_REG(tnumt), -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch b/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch index bd3c3680e0..22f63a0558 100644 --- a/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch +++ b/platform/mellanox/non-upstream-patches/patches/0133-mlxsw-reg-Add-Management-DownStream-Device-Control-R.patch @@ -1,7 +1,8 @@ -From ab25c37ca20274cbf51ab603aa44f682cf5b51b5 Mon Sep 17 00:00:00 2001 +From 14d65a09a9b77a5ed632a73ff006042d26be3226 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 19 Jan 2021 12:16:58 +0100 -Subject: [PATCH] mlxsw: reg: Add Management DownStream Device Control Register +Subject: [PATCH backport 5.10 133/182] mlxsw: reg: Add Management DownStream + Device Control Register The MDDC register allows control downstream devices and line cards. @@ -11,10 +12,10 @@ Signed-off-by: Jiri Pirko 1 file changed, 37 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index d5301bd6f..9cbdf407f 100644 +index ad7faeb95646..cddfe5702140 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10530,6 +10530,42 @@ mlxsw_reg_mddq_slot_name_unpack(const char *payload, char *slot_ascii_name) +@@ -10529,6 +10529,42 @@ mlxsw_reg_mddq_slot_name_unpack(const char *payload, char *slot_ascii_name) mlxsw_reg_mddq_slot_ascii_name_memcpy_from(payload, slot_ascii_name); } @@ -57,7 +58,7 @@ index d5301bd6f..9cbdf407f 100644 /* MFDE - Monitoring FW Debug Register * ----------------------------------- */ -@@ -11730,6 +11766,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { +@@ -11729,6 +11765,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mfgd), MLXSW_REG(mgpir), MLXSW_REG(mddq), @@ -66,5 +67,5 @@ index d5301bd6f..9cbdf407f 100644 MLXSW_REG(tngcr), MLXSW_REG(tnumt), -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch b/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch index b8569f2ac2..9aefc453b8 100644 --- a/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch +++ b/platform/mellanox/non-upstream-patches/patches/0134-mlxsw-reg-Add-Management-Binary-Code-Transfer-Regist.patch @@ -1,7 +1,8 @@ -From 618665ccbf600c2838fb2e181246aef0fa90bac2 Mon Sep 17 00:00:00 2001 +From e9afbd683a14e3369ba25dcb9c8147a8b478b5c0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 10 Dec 2020 18:27:38 +0100 -Subject: [PATCH] mlxsw: reg: Add Management Binary Code Transfer Register +Subject: [PATCH backport 5.10 134/182] mlxsw: reg: Add Management Binary Code + Transfer Register The MBCT register allows to transfer binary codes from the Host to the management FW by transferring it by chunks of maximum 1KB. @@ -12,10 +13,10 @@ Signed-off-by: Jiri Pirko 1 file changed, 120 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 9cbdf407f..89b21910f 100644 +index cddfe5702140..e060f054e0a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10297,6 +10297,125 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, +@@ -10296,6 +10296,125 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); } @@ -141,7 +142,7 @@ index 9cbdf407f..89b21910f 100644 /* MDDQ - Management DownStream Device Query Register * -------------------------------------------------- * This register allows to query the DownStream device properties. The desired -@@ -11765,6 +11884,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { +@@ -11764,6 +11883,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mtptpt), MLXSW_REG(mfgd), MLXSW_REG(mgpir), @@ -150,5 +151,5 @@ index 9cbdf407f..89b21910f 100644 MLXSW_REG(mddc), MLXSW_REG(mfde), -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch b/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch index 79a82fec69..f35efc3b2b 100644 --- a/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch +++ b/platform/mellanox/non-upstream-patches/patches/0135-mlxsw-core_linecards-Add-line-card-objects-and-imple.patch @@ -1,8 +1,8 @@ -From 3c23c52a44d6f87f7caaf09babb6196e523d1e7c Mon Sep 17 00:00:00 2001 +From 59c953deed31161dc358e6d397af2b5b0f5ee61c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 22 Dec 2021 16:06:54 +0000 -Subject: [PATCH] mlxsw: core_linecards: Add line card objects and implement - provisioning +Subject: [PATCH backport 5.10 135/182] mlxsw: core_linecards: Add line card + objects and implement provisioning Introduce objects for line cards and an infrastructure around that. Use devlink_linecard_create/destroy() to register the line card with @@ -21,7 +21,7 @@ Signed-off-by: Jiri Pirko create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_linecards.c diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile -index 892724380..ca7260a14 100644 +index 892724380ea2..ca7260a145f5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -1,7 +1,8 @@ @@ -35,7 +35,7 @@ index 892724380..ca7260a14 100644 mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index 0b1888318..246db548f 100644 +index 0b1888318ef1..246db548f011 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -82,6 +82,7 @@ struct mlxsw_core { @@ -112,7 +112,7 @@ index 0b1888318..246db548f 100644 kfree(mlxsw_core->lag.mapping); mlxsw_ports_fini(mlxsw_core); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 0ceb7dae9..d3c5d8289 100644 +index 0ceb7dae95f6..d3c5d8289a85 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -30,6 +30,8 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core); @@ -175,7 +175,7 @@ index 0ceb7dae9..d3c5d8289 100644 #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c new file mode 100644 -index 000000000..a324ce243 +index 000000000000..a324ce2436e8 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -0,0 +1,775 @@ @@ -955,7 +955,7 @@ index 000000000..a324ce243 + +MODULE_FIRMWARE(MLXSW_LINECARDS_INI_BUNDLE_FILE); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index 5066fcc46..d7a230828 100644 +index e0424f490c6f..bc233a5c8a79 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2076,6 +2076,72 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, @@ -1041,7 +1041,7 @@ index 5066fcc46..d7a230828 100644 MLXSW_SP_RXL_NO_MARK(FID_MISS, TRAP_TO_CPU, FID_MISS, false), /* L3 traps */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h -index 57f9e2460..f3e522de2 100644 +index 57f9e24602d0..f3e522de2f68 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -132,6 +132,12 @@ enum mlxsw_event_trap_id { @@ -1058,5 +1058,5 @@ index 57f9e2460..f3e522de2 100644 #endif /* _MLXSW_TRAP_H */ -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch b/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch index b889ad9387..50e93d73a8 100644 --- a/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0136-mlxsw-core_linecards-Implement-line-card-activation-.patch @@ -1,7 +1,8 @@ -From f2ecea65348e527345e9e7a59766162eb2297a53 Mon Sep 17 00:00:00 2001 +From e7379493c9f7e30f7d20459ed07a435095e9a889 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 22 Jan 2021 14:45:06 +0100 -Subject: [PATCH] mlxsw: core_linecards: Implement line card activation process +Subject: [PATCH backport 5.10 136/182] mlxsw: core_linecards: Implement line + card activation process Allow to process events generated upon line card getting "ready" and "active". @@ -13,7 +14,7 @@ Signed-off-by: Jiri Pirko 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index d3c5d8289..ecd91bb8c 100644 +index d3c5d8289a85..ecd91bb8ca77 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -521,6 +521,9 @@ struct mlxsw_linecard { @@ -27,7 +28,7 @@ index d3c5d8289..ecd91bb8c 100644 struct mlxsw_linecard_types_info; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c -index a324ce243..134437f49 100644 +index a324ce2436e8..134437f49219 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -67,6 +67,8 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) @@ -201,5 +202,5 @@ index a324ce243..134437f49 100644 void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch b/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch index d8abff2cb1..77348d45f2 100644 --- a/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch +++ b/platform/mellanox/non-upstream-patches/patches/0137-mlxsw-core-Extend-driver-ops-by-remove-selected-port.patch @@ -1,7 +1,8 @@ -From 063ca0577ceb2355884555d96a24a740a2c03bdb Mon Sep 17 00:00:00 2001 +From a0e62e8df42c4ae6eabba2ea0c2d076d8c8d06fb Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 22 Dec 2021 16:26:43 +0000 -Subject: [PATCH] mlxsw: core: Extend driver ops by remove selected ports op +Subject: [PATCH backport 5.10 137/182] mlxsw: core: Extend driver ops by + remove selected ports op In case of line card implementation, the core has to have a way to remove relevant ports manually. Extend the Spectrum driver ops by an op @@ -15,7 +16,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 32 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index 246db548f..2b4f9844b 100644 +index 246db548f011..2b4f9844b1d6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -2870,6 +2870,15 @@ mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, @@ -35,7 +36,7 @@ index 246db548f..2b4f9844b 100644 { return mlxsw_core->env; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index ecd91bb8c..70f97ef74 100644 +index ecd91bb8ca77..70f97ef74a2c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -223,6 +223,10 @@ enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, @@ -61,7 +62,7 @@ index ecd91bb8c..70f97ef74 100644 unsigned int sb_index, u16 pool_index, struct devlink_sb_pool_info *pool_info); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index d7a230828..75b418fbe 100644 +index bc233a5c8a79..82acff318dcd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1736,6 +1736,20 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) @@ -94,5 +95,5 @@ index d7a230828..75b418fbe 100644 .sb_pool_set = mlxsw_sp_sb_pool_set, .sb_port_pool_get = mlxsw_sp_sb_port_pool_get, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch b/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch index 0e886cc290..5a56db150d 100644 --- a/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch +++ b/platform/mellanox/non-upstream-patches/patches/0138-mlxsw-spectrum-Add-port-to-linecard-mapping.patch @@ -1,7 +1,8 @@ -From fd68af1d7a7c58c3f7db6ec95aba528137ec4c2d Mon Sep 17 00:00:00 2001 +From 718b7aec4ec4c7e3c327b2ffbf43b27126688836 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 3 Jan 2022 11:22:42 +0000 -Subject: [PATCH] mlxsw: spectrum: Add port to linecard mapping +Subject: [PATCH backport 5.10 138/182] mlxsw: spectrum: Add port to linecard + mapping For each port get slot_index using PMLP register. For ports residing on a linecard, identify it with the linecard by setting mapping @@ -19,7 +20,7 @@ Signed-off-by: Jiri Pirko 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index 2b4f9844b..68ef007ac 100644 +index 2b4f9844b1d6..68ef007ac48c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -48,6 +48,7 @@ struct mlxsw_core_port { @@ -82,7 +83,7 @@ index 2b4f9844b..68ef007ac 100644 if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 70f97ef74..8e738ddb3 100644 +index 70f97ef74a2c..8e738ddb39c8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -202,7 +202,8 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, @@ -96,7 +97,7 @@ index 70f97ef74..8e738ddb3 100644 const unsigned char *switch_id, unsigned char switch_id_len); diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c -index 104f1ba02..30925f573 100644 +index 104f1ba0242f..30925f57362e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -210,7 +210,7 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) @@ -109,7 +110,7 @@ index 104f1ba02..30925f573 100644 0, mlxsw_m->base_mac, sizeof(mlxsw_m->base_mac)); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index 75b418fbe..31eec40a3 100644 +index 82acff318dcd..c87267d002c6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1399,7 +1399,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, @@ -122,7 +123,7 @@ index 75b418fbe..31eec40a3 100644 port_mapping->lane / lanes, splittable, lanes, diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c -index 1e561132e..090b9a103 100644 +index 1e561132eb1e..090b9a103c04 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -280,7 +280,7 @@ static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port, @@ -135,7 +136,7 @@ index 1e561132e..090b9a103 100644 mlxsw_sib->hw_id, sizeof(mlxsw_sib->hw_id)); if (err) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c -index 131b2a53d..bf8a54776 100644 +index 131b2a53d261..bf8a54776861 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1085,7 +1085,7 @@ static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, @@ -148,5 +149,5 @@ index 131b2a53d..bf8a54776 100644 mlxsw_sx->hw_id, sizeof(mlxsw_sx->hw_id)); if (err) { -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch b/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch index 1a532d88fa..8f7fc94e03 100644 --- a/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch +++ b/platform/mellanox/non-upstream-patches/patches/0139-mlxsw-reg-Introduce-Management-Temperature-Extended-.patch @@ -1,8 +1,8 @@ -From a719653b2a7f0943e757c04dab73df324e469436 Mon Sep 17 00:00:00 2001 +From 44b270551552a48c2a0799f1660b7bfdd0c10519 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 12 May 2021 22:57:37 +0300 -Subject: [PATCH] mlxsw: reg: Introduce Management Temperature Extended - Capabilities Register +Subject: [PATCH backport 5.10 139/182] mlxsw: reg: Introduce Management + Temperature Extended Capabilities Register Introduce new register MTECR (Management Temperature Extended Capabilities Register). This register exposes the capabilities of the @@ -16,10 +16,10 @@ Signed-off-by: Jiri Pirko 1 file changed, 67 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index 89b21910f..c1ce0b42e 100644 +index e060f054e0a9..5757c4f40277 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10297,6 +10297,72 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, +@@ -10296,6 +10296,72 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, *num_of_slots = mlxsw_reg_mgpir_num_of_slots_get(payload); } @@ -92,7 +92,7 @@ index 89b21910f..c1ce0b42e 100644 /* MBCT - Management Binary Code Transfer Register * ----------------------------------------------- * This register allows to transfer binary codes from the Host to -@@ -11884,6 +11950,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { +@@ -11883,6 +11949,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mtptpt), MLXSW_REG(mfgd), MLXSW_REG(mgpir), @@ -101,5 +101,5 @@ index 89b21910f..c1ce0b42e 100644 MLXSW_REG(mddq), MLXSW_REG(mddc), -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch b/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch index d48940325e..35b85c12d3 100644 --- a/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch +++ b/platform/mellanox/non-upstream-patches/patches/0140-mlxsw-core-Add-APIs-for-thermal-sensor-mapping.patch @@ -1,7 +1,8 @@ -From 1ea36b4966e21d9d599da7e4e3195364841d9318 Mon Sep 17 00:00:00 2001 +From 3614c1e72e48e03c64ce88d269d97ee4743f9cc4 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 13 Dec 2021 12:29:10 +0000 -Subject: [PATCH] mlxsw: core: Add APIs for thermal sensor mapping +Subject: [PATCH backport 5.10 140/182] mlxsw: core: Add APIs for thermal + sensor mapping Add APIs mlxsw_env_sensor_map_init() and mlxsw_env_sensor_map_fini((). The purpose of the first one is to allocate and create thermal sensors @@ -21,10 +22,10 @@ Signed-off-by: Vadim Pasternak 2 files changed, 59 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index 94d44db1a..c27cd424b 100644 +index 4553dfa68f96..4f3fc25af013 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -626,6 +626,53 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, +@@ -624,6 +624,53 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index, } EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); @@ -79,7 +80,7 @@ index 94d44db1a..c27cd424b 100644 u8 slot_index, u8 module, bool *p_has_temp_sensor) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h -index 03d027870..336c9ee57 100644 +index 03d027870d65..336c9ee579cb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h @@ -9,6 +9,11 @@ @@ -109,5 +110,5 @@ index 03d027870..336c9ee57 100644 mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 slot_index, u8 module, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch b/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch index 2c1bd96646..1d0966082d 100644 --- a/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch +++ b/platform/mellanox/non-upstream-patches/patches/0141-mlxsw-reg-Add-Management-DownStream-Device-Tunneling.patch @@ -1,8 +1,8 @@ -From 46563dcd511270f67a9e771497ccfc73907aa4d3 Mon Sep 17 00:00:00 2001 +From d7353e41900e4d6fa44fa5e51a483b9f01432846 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Feb 2021 10:17:53 +0100 -Subject: [PATCH] mlxsw: reg: Add Management DownStream Device Tunneling - Register +Subject: [PATCH backport 5.10 141/182] mlxsw: reg: Add Management DownStream + Device Tunneling Register The MDDT register allows deliver query and request messages (PRM registers, commands) to a DownStream device. @@ -13,10 +13,10 @@ Signed-off-by: Jiri Pirko 1 file changed, 91 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h -index c1ce0b42e..f8c828e05 100644 +index 5757c4f40277..7b71e9ae3d51 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h -@@ -10482,6 +10482,96 @@ mlxsw_reg_mbct_unpack(const char *payload, u8 *p_slot_index, +@@ -10481,6 +10481,96 @@ mlxsw_reg_mbct_unpack(const char *payload, u8 *p_slot_index, *p_fsm_state = mlxsw_reg_mbct_fsm_state_get(payload); } @@ -113,7 +113,7 @@ index c1ce0b42e..f8c828e05 100644 /* MDDQ - Management DownStream Device Query Register * -------------------------------------------------- * This register allows to query the DownStream device properties. The desired -@@ -11952,6 +12042,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { +@@ -11951,6 +12041,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mgpir), MLXSW_REG(mtecr), MLXSW_REG(mbct), @@ -122,5 +122,5 @@ index c1ce0b42e..f8c828e05 100644 MLXSW_REG(mddc), MLXSW_REG(mfde), -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch b/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch index 1126d7013e..c08636be76 100644 --- a/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch +++ b/platform/mellanox/non-upstream-patches/patches/0142-mlxsw-core_linecards-Probe-devices-for-provisioned-l.patch @@ -1,8 +1,8 @@ -From 70bc337251ccbfe095a89457ded233c3ad5b9bbc Mon Sep 17 00:00:00 2001 +From 51f5cf36b8b2c94d8a71bfa17d5f71257048c314 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 26 Feb 2021 13:15:09 +0100 -Subject: [PATCH] mlxsw: core_linecards: Probe devices for provisioned line - card and attach them +Subject: [PATCH backport 5.10 142/182] mlxsw: core_linecards: Probe devices + for provisioned line card and attach them In case the line card is provisioned, go over all possible existing devices (gearboxes) on it and attach them, so devlink core is aware of @@ -15,7 +15,7 @@ Signed-off-by: Jiri Pirko 2 files changed, 108 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 8e738ddb3..593470d14 100644 +index 8e738ddb39c8..593470d14815 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -533,6 +533,9 @@ struct mlxsw_linecard { @@ -29,7 +29,7 @@ index 8e738ddb3..593470d14 100644 struct mlxsw_linecard_types_info; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c -index 134437f49..720ad6d82 100644 +index 134437f49219..720ad6d82798 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -64,27 +64,120 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) @@ -220,5 +220,5 @@ index 134437f49..720ad6d82 100644 mutex_destroy(&linecard->lock); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch b/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch index f4dc89aec2..78fe94419a 100644 --- a/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch +++ b/platform/mellanox/non-upstream-patches/patches/0143-mlxsw-core_linecards-Expose-device-FW-version-over-d.patch @@ -1,8 +1,8 @@ -From 8279b3c273fac860394fb922c70c336993e6f087 Mon Sep 17 00:00:00 2001 +From e4830f23af9d14fac42764dd077f49de8de7bff2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 10 Jun 2021 15:32:00 +0200 -Subject: [PATCH] mlxsw: core_linecards: Expose device FW version over device - info +Subject: [PATCH backport 5.10 143/182] mlxsw: core_linecards: Expose device FW + version over device info Extend MDDQ to obtain FW version of line card device and implement device_info_get() op to fill up the info with that. @@ -13,7 +13,7 @@ Signed-off-by: Jiri Pirko 1 file changed, 100 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c -index 720ad6d82..cb872f918 100644 +index 720ad6d82798..cb872f918f01 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -64,13 +64,31 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) @@ -173,5 +173,5 @@ index 720ad6d82..cb872f918 100644 static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch b/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch index 642cd79ca4..87018bd867 100644 --- a/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch +++ b/platform/mellanox/non-upstream-patches/patches/0144-mlxsw-core-Introduce-flash-update-components.patch @@ -1,7 +1,8 @@ -From a1421cadee435540d09a5526525f692821a271cd Mon Sep 17 00:00:00 2001 +From 1eb0843255d6e92aa96d0ea11a15ab1f86b20e4f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 26 Feb 2021 18:40:28 +0100 -Subject: [PATCH] mlxsw: core: Introduce flash update components +Subject: [PATCH backport 5.10 144/182] mlxsw: core: Introduce flash update + components Introduce an infrastructure allowing to have multiple components for flashing purposes that can be registered from inside the driver. Convert @@ -15,7 +16,7 @@ Signed-off-by: Jiri Pirko 3 files changed, 125 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index 68ef007ac..f55071982 100644 +index 68ef007ac48c..f55071982271 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -91,6 +91,10 @@ struct mlxsw_core { @@ -188,7 +189,7 @@ index 68ef007ac..f55071982 100644 return; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 593470d14..30f00da0a 100644 +index 593470d14815..30f00da0a48d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -41,6 +41,18 @@ mlxsw_core_fw_rev_minor_subminor_validate(const struct mlxsw_fw_rev *rev, @@ -211,7 +212,7 @@ index 593470d14..30f00da0a 100644 const struct mlxsw_bus *mlxsw_bus, void *bus_priv, bool reload, diff --git a/include/net/devlink.h b/include/net/devlink.h -index 06b61c1d7..fafbec26d 100644 +index 06b61c1d7938..fafbec26d2c4 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -19,6 +19,7 @@ @@ -239,5 +240,5 @@ index 06b61c1d7..fafbec26d 100644 const char *component; u32 overwrite_mask; -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch b/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch index 1fc1f2c96d..de282a124f 100644 --- a/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch +++ b/platform/mellanox/non-upstream-patches/patches/0145-mlxfw-Get-the-PSID-value-using-op-instead-of-passing.patch @@ -1,8 +1,8 @@ -From ecf655b1e2329f2376f014c2cad0f81ec2ac5deb Mon Sep 17 00:00:00 2001 +From 81cb237570a4d0251455d17e073337f73c1b4aa9 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 4 Jun 2021 10:25:35 +0200 -Subject: [PATCH] mlxfw: Get the PSID value using op instead of passing it in - struct +Subject: [PATCH backport 5.10 145/182] mlxfw: Get the PSID value using op + instead of passing it in struct In preparation for line card device flashing, where the PSID is going to be obtained dynamically using MGIR register for each individual line @@ -17,7 +17,7 @@ Signed-off-by: Jiri Pirko 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c -index 02558ac2a..06edfd5b1 100644 +index 02558ac2ace6..06edfd5b12e0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -494,6 +494,20 @@ struct mlx5_mlxfw_dev { @@ -60,7 +60,7 @@ index 02558ac2a..06edfd5b1 100644 }, .mlx5_core_dev = dev diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h -index 7654841a0..b83651246 100644 +index 7654841a05c2..b83651246c1f 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h @@ -11,8 +11,6 @@ @@ -82,7 +82,7 @@ index 7654841a0..b83651246 100644 u32 *p_max_size, u8 *p_align_bits, u16 *p_max_write_size); diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c -index bcd166911..329ddf1b3 100644 +index bcd166911d44..329ddf1b3b89 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c @@ -303,7 +303,8 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev, @@ -152,7 +152,7 @@ index bcd166911..329ddf1b3 100644 err_fsm_reactivate: err_state_wait_idle_to_locked: diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index f55071982..8c1280781 100644 +index f55071982271..8c128078105a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -890,6 +890,21 @@ struct mlxsw_core_fw_info { @@ -196,5 +196,5 @@ index f55071982..8c1280781 100644 }, .mlxsw_core = mlxsw_core -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch b/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch index c551268717..8855ba192e 100644 --- a/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch +++ b/platform/mellanox/non-upstream-patches/patches/0146-mlxsw-core_linecards-Implement-line-card-device-flas.patch @@ -1,7 +1,8 @@ -From b721c11b90bb0ef2fcd0bfccd6334948153edea2 Mon Sep 17 00:00:00 2001 +From 0e642e558b98e1a686b39acb53f53c1fb9735b02 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 5 Mar 2021 09:33:21 +0100 -Subject: [PATCH] mlxsw: core_linecards: Implement line card device flashing +Subject: [PATCH backport 5.10 146/182] mlxsw: core_linecards: Implement line + card device flashing Generate flash component name and register it internally within mlxsw for flashing. Also, propagate the component name to devlink core which @@ -15,7 +16,7 @@ Signed-off-by: Jiri Pirko 1 file changed, 334 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c -index cb872f918..9f9ee582f 100644 +index cb872f918f01..9f9ee582fce2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -73,6 +73,7 @@ struct mlxsw_linecard_device_info { @@ -396,5 +397,5 @@ index cb872f918..9f9ee582f 100644 } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch b/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch index e7b719158e..22c42d0ce4 100644 --- a/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch +++ b/platform/mellanox/non-upstream-patches/patches/0147-mlxsw-core_linecards-Introduce-ops-for-linecards-sta.patch @@ -1,8 +1,8 @@ -From 19bae5f5978a43a22258843cc999b592d0e4b414 Mon Sep 17 00:00:00 2001 +From 5e3bebf1e096e4770cad3aaf3d03fa22429fe5f9 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 22 Jan 2021 15:01:06 +0100 -Subject: [PATCH] mlxsw: core_linecards: Introduce ops for linecards status - change tracking +Subject: [PATCH backport 5.10 147/182] mlxsw: core_linecards: Introduce ops + for linecards status change tracking Introduce an infrastructure allowing the core to register set of ops which are called whenever line card gets provisione/unprovisioned @@ -15,7 +15,7 @@ Signed-off-by: Jiri Pirko 2 files changed, 150 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 30f00da0a..10ea541bb 100644 +index 30f00da0a48d..10ea541bb19d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -582,4 +582,26 @@ int mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, @@ -46,7 +46,7 @@ index 30f00da0a..10ea541bb 100644 + #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c -index 9f9ee582f..3a2fdd22d 100644 +index 9f9ee582fce2..3a2fdd22dc21 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -576,6 +576,59 @@ static void mlxsw_linecard_provision_fail(struct mlxsw_core *mlxsw_core, @@ -273,5 +273,5 @@ index 9f9ee582f..3a2fdd22d 100644 + MODULE_FIRMWARE(MLXSW_LINECARDS_INI_BUNDLE_FILE); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch b/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch index f9e7a010e6..e5e39186aa 100644 --- a/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch +++ b/platform/mellanox/non-upstream-patches/patches/0148-mlxsw-core-Add-interfaces-for-line-card-initializati.patch @@ -1,8 +1,8 @@ -From 8d6f7da411b62b4450db1ebb8b687dbc5a386300 Mon Sep 17 00:00:00 2001 +From d037308b118ee4a1ccf557dc3f1c47b81bb62c4c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 13 Dec 2021 12:54:36 +0000 -Subject: [PATCH] mlxsw: core: Add interfaces for line card initialization and - de-initialization +Subject: [PATCH backport 5.10 148/182] mlxsw: core: Add interfaces for line + card initialization and de-initialization Add callback functions for line card cables info initialization and de-initialization. @@ -19,10 +19,10 @@ Signed-off-by: Vadim Pasternak 1 file changed, 78 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -index c27cd424b..f9c770eec 100644 +index 4f3fc25af013..98f7cf672d9e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c -@@ -1162,6 +1162,77 @@ mlxsw_env_module_event_disable(struct mlxsw_env *mlxsw_env, u8 slot_index) +@@ -1160,6 +1160,77 @@ mlxsw_env_module_event_disable(struct mlxsw_env *mlxsw_env, u8 slot_index) { } @@ -100,7 +100,7 @@ index c27cd424b..f9c770eec 100644 int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) { u8 module_count, num_of_slots, max_module_count; -@@ -1198,6 +1269,10 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1196,6 +1267,10 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) mutex_init(&env->line_cards_lock); *p_env = env; @@ -111,7 +111,7 @@ index c27cd424b..f9c770eec 100644 err = mlxsw_env_temp_warn_event_register(mlxsw_core); if (err) goto err_temp_warn_event_register; -@@ -1225,6 +1300,8 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) +@@ -1223,6 +1298,8 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) err_module_plug_event_register: mlxsw_env_temp_warn_event_unregister(env); err_temp_warn_event_register: @@ -120,7 +120,7 @@ index c27cd424b..f9c770eec 100644 mutex_destroy(&env->line_cards_lock); mlxsw_env_line_cards_free(env); err_mlxsw_env_line_cards_alloc: -@@ -1239,6 +1316,7 @@ void mlxsw_env_fini(struct mlxsw_env *env) +@@ -1237,6 +1314,7 @@ void mlxsw_env_fini(struct mlxsw_env *env) /* Make sure there is no more event work scheduled. */ mlxsw_core_flush_owq(); mlxsw_env_temp_warn_event_unregister(env); @@ -129,5 +129,5 @@ index c27cd424b..f9c770eec 100644 mlxsw_env_line_cards_free(env); kfree(env); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch b/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch index c64cbb6cbd..e688440377 100644 --- a/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch +++ b/platform/mellanox/non-upstream-patches/patches/0149-mlxsw-core_thermal-Add-interfaces-for-line-card-init.patch @@ -1,8 +1,8 @@ -From 62b2da593b9ee1042b0d65c7b84e9f463497ecd8 Mon Sep 17 00:00:00 2001 +From 71416a2dd1900ac8eb9b7d5cd08911d331b074ff Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 12 May 2021 22:57:39 +0300 -Subject: [PATCH] mlxsw: core_thermal: Add interfaces for line card - initialization and de-initialization +Subject: [PATCH backport 5.10 149/182] mlxsw: core_thermal: Add interfaces for + line card initialization and de-initialization Add callback functions for line card thermal area initialization and de-initialization. Each line card is associated with the relevant @@ -34,10 +34,10 @@ Signed-off-by: Jiri Pirko 1 file changed, 129 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -index e860cade5..88a2f63c8 100644 +index b9253c9f70d9..529108aea3c6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -96,6 +96,7 @@ struct mlxsw_thermal_module { +@@ -88,6 +88,7 @@ struct mlxsw_thermal_module { }; struct mlxsw_thermal_area { @@ -45,7 +45,7 @@ index e860cade5..88a2f63c8 100644 struct mlxsw_thermal_module *tz_module_arr; u8 tz_module_num; struct mlxsw_thermal_module *tz_gearbox_arr; -@@ -113,6 +114,7 @@ struct mlxsw_thermal { +@@ -105,6 +106,7 @@ struct mlxsw_thermal { u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; struct mlxsw_thermal_area *main; @@ -53,7 +53,7 @@ index e860cade5..88a2f63c8 100644 unsigned int tz_highest_score; struct thermal_zone_device *tz_highest_dev; }; -@@ -989,6 +991,126 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, +@@ -948,6 +950,126 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal, mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]); } @@ -180,7 +180,7 @@ index e860cade5..88a2f63c8 100644 int mlxsw_thermal_init(struct mlxsw_core *core, const struct mlxsw_bus_info *bus_info, struct mlxsw_thermal **p_thermal) -@@ -1094,6 +1216,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -1052,6 +1174,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (err) goto err_thermal_gearboxes_init; @@ -191,7 +191,7 @@ index e860cade5..88a2f63c8 100644 err = thermal_zone_device_enable(thermal->tzdev); if (err) goto err_thermal_zone_device_enable; -@@ -1102,6 +1228,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, +@@ -1060,6 +1186,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, return 0; err_thermal_zone_device_enable: @@ -200,7 +200,7 @@ index e860cade5..88a2f63c8 100644 mlxsw_thermal_gearboxes_fini(thermal, thermal->main); err_thermal_gearboxes_init: mlxsw_thermal_gearboxes_main_fini(thermal->main); -@@ -1129,6 +1257,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) +@@ -1087,6 +1215,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) { int i; @@ -209,5 +209,5 @@ index e860cade5..88a2f63c8 100644 mlxsw_thermal_gearboxes_main_fini(thermal->main); mlxsw_thermal_modules_fini(thermal, thermal->main); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch b/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch index 9b9e513386..3c229622de 100644 --- a/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch +++ b/platform/mellanox/non-upstream-patches/patches/0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch @@ -1,8 +1,8 @@ -From 97f2a14ec9543588b37be8fc54aad9ed13cceec9 Mon Sep 17 00:00:00 2001 +From 7405ad4281c96aedcf879357d03487556abed05d Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 12 May 2021 22:57:42 +0300 -Subject: [PATCH] mlxsw: core_hwmon: Add interfaces for line card - initialization and de-initialization +Subject: [PATCH backport 5.10 150/182] mlxsw: core_hwmon: Add interfaces for + line card initialization and de-initialization Add callback functions for line card 'hwmon' initialization and de-initialization. Each line card is associated with the relevant @@ -29,7 +29,7 @@ Signed-off-by: Jiri Pirko 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 6af23f472..a27146cca 100644 +index 6af23f4724e4..a27146ccafc5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -19,6 +19,7 @@ @@ -231,5 +231,5 @@ index 6af23f472..a27146cca 100644 mlxsw_hwmon_gearbox_main_fini(mlxsw_hwmon->main); kfree(mlxsw_hwmon->main); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch b/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch index dc18597031..8aeb3848a0 100644 --- a/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch +++ b/platform/mellanox/non-upstream-patches/patches/0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch @@ -1,7 +1,8 @@ -From 37eabf5ec0121c1a5092f48360b3d1208a22e655 Mon Sep 17 00:00:00 2001 +From e3a3f15e69b566577c2ebe0b6f3bc019476c6879 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 30 Dec 2021 16:02:59 +0000 -Subject: [PATCH] mlxsw: minimal: Prepare driver for modular system support +Subject: [PATCH backport 5.10 151/182] mlxsw: minimal: Prepare driver for + modular system support As a preparation for line cards support: - Allocate per line card array according to the queried number of slots @@ -23,7 +24,7 @@ Signed-off-by: Vadim Pasternak 1 file changed, 242 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c -index 30925f573..59c5053dc 100644 +index 30925f57362e..59c5053dc5fd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -24,22 +24,40 @@ static const struct mlxsw_fw_rev mlxsw_m_fw_rev = { @@ -491,5 +492,5 @@ index 30925f573..59c5053dc 100644 static const struct mlxsw_config_profile mlxsw_m_config_profile; -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch b/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch index 99c1af62b7..d81e11aa19 100644 --- a/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch +++ b/platform/mellanox/non-upstream-patches/patches/0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch @@ -1,8 +1,8 @@ -From bf88a40c8d0379e1ce8a6cc0a2bf4f935f90307c Mon Sep 17 00:00:00 2001 +From da7c615b231402e3084dae855468be117538535c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 15 Dec 2021 08:59:14 +0000 -Subject: [PATCH] mlxsw: core: Extend bus init function with event handler - argument +Subject: [PATCH backport 5.10 152/182] mlxsw: core: Extend bus init function + with event handler argument The purpose of new argument - is to introduce system event handler for treating line card activation / deactivation signals on modular system. @@ -16,7 +16,7 @@ Signed-off-by: Vadim Pasternak 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index 8c1280781..a9bb43837 100644 +index 8c128078105a..a9bb43837b33 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -2005,7 +2005,8 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, @@ -30,7 +30,7 @@ index 8c1280781..a9bb43837 100644 goto err_bus_init; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h -index 10ea541bb..b09f9013d 100644 +index 10ea541bb19d..b09f9013db77 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -390,6 +390,7 @@ struct mlxsw_driver { @@ -52,10 +52,10 @@ index 10ea541bb..b09f9013d 100644 bool (*skb_transmit_busy)(void *bus_priv, const struct mlxsw_tx_info *tx_info); diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -index b8a5c0cbb..b75416561 100644 +index ce843ea91464..0cdb9b9d8353 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -@@ -530,7 +530,8 @@ static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb, +@@ -509,7 +509,8 @@ static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb, static int mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, const struct mlxsw_config_profile *profile, @@ -66,7 +66,7 @@ index b8a5c0cbb..b75416561 100644 struct mlxsw_i2c *mlxsw_i2c = bus_priv; char *mbox; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c -index dbb16ce25..e8e91130c 100644 +index dbb16ce25bdf..e8e91130cdf5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1411,9 +1411,12 @@ static void mlxsw_pci_free_irq_vectors(struct mlxsw_pci *mlxsw_pci) @@ -86,5 +86,5 @@ index dbb16ce25..e8e91130c 100644 struct mlxsw_pci *mlxsw_pci = bus_priv; struct pci_dev *pdev = mlxsw_pci->pdev; -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch b/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch index 43bda72b4d..8a0bc5f280 100644 --- a/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch +++ b/platform/mellanox/non-upstream-patches/patches/0153-mlxsw-i2c-Add-support-for-system-events-handling.patch @@ -1,7 +1,8 @@ -From c5235b3c4a8ab2b758140d75a7422117e917478c Mon Sep 17 00:00:00 2001 +From 8d7807e7b8326c537aa7db4fe31b2ca183d32248 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 19 Dec 2021 09:12:58 +0000 -Subject: [PATCH] mlxsw: i2c: Add support for system events handling +Subject: [PATCH backport v5.10.164 1/1] mlxsw: i2c: Add support for system + events handling Extend i2c bus driver with interrupt handler to support system specific hotplug events, related to line card state change. @@ -17,7 +18,7 @@ Signed-off-by: Vadim Pasternak 1 file changed, 110 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -index b75416561..e5883b4e8 100644 +index cc99ec3f4e96..02f5733cfcc6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -9,6 +9,7 @@ @@ -41,33 +42,33 @@ index b75416561..e5883b4e8 100644 /** * struct mlxsw_i2c - device private data: * @cmd: command attributes; -@@ -64,6 +71,12 @@ +@@ -63,6 +70,12 @@ + * @core: switch core pointer; * @bus_info: bus info block; * @block_size: maximum block size allowed to pass to under layer; - * @status: status to indicate chip reset or in-service update; + * @pdata: device platform data; + * @dwork_irq: interrupts delayed work queue; + * @lock - lock for interrupts sync; + * @sys_event_handler: system events handler callback; + * @irq: IRQ line number; + * @irq_unhandled_count: number of unhandled interrupts; + * @status: status to indicate chip reset or in-service update; */ struct mlxsw_i2c { - struct { -@@ -78,6 +91,12 @@ struct mlxsw_i2c { +@@ -77,6 +90,12 @@ struct mlxsw_i2c { + struct mlxsw_core *core; struct mlxsw_bus_info bus_info; u16 block_size; - u8 status; + struct mlxreg_core_hotplug_platform_data *pdata; + struct delayed_work dwork_irq; + spinlock_t lock; /* sync with interrupt */ + void (*sys_event_handler)(struct mlxsw_core *mlxsw_core); + int irq; + atomic_t irq_unhandled_count; + u8 status; }; - #define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \ -@@ -538,6 +557,7 @@ mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, +@@ -537,6 +556,7 @@ mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, int err; mlxsw_i2c->core = mlxsw_core; @@ -75,7 +76,7 @@ index b75416561..e5883b4e8 100644 mbox = mlxsw_cmd_mbox_alloc(); if (!mbox) -@@ -568,6 +588,87 @@ static void mlxsw_i2c_fini(void *bus_priv) +@@ -567,6 +587,87 @@ static void mlxsw_i2c_fini(void *bus_priv) mlxsw_i2c->core = NULL; } @@ -163,7 +164,7 @@ index b75416561..e5883b4e8 100644 static const struct mlxsw_bus mlxsw_i2c_bus = { .kind = "i2c", .init = mlxsw_i2c_init, -@@ -662,6 +763,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client, +@@ -661,6 +762,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client, mlxsw_i2c->bus_info.dev = &client->dev; mlxsw_i2c->bus_info.low_frequency = true; mlxsw_i2c->dev = &client->dev; @@ -171,7 +172,7 @@ index b75416561..e5883b4e8 100644 err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info, &mlxsw_i2c_bus, mlxsw_i2c, false, -@@ -671,6 +773,12 @@ static int mlxsw_i2c_probe(struct i2c_client *client, +@@ -670,6 +772,12 @@ static int mlxsw_i2c_probe(struct i2c_client *client, return err; } @@ -184,7 +185,7 @@ index b75416561..e5883b4e8 100644 return 0; errout: -@@ -684,6 +792,8 @@ static int mlxsw_i2c_remove(struct i2c_client *client) +@@ -683,6 +791,8 @@ static int mlxsw_i2c_remove(struct i2c_client *client) { struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); @@ -194,5 +195,5 @@ index b75416561..e5883b4e8 100644 mutex_destroy(&mlxsw_i2c->cmd.lock); -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch b/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch index 6500a0db87..fca84d737f 100644 --- a/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch +++ b/platform/mellanox/non-upstream-patches/patches/0154-mlxsw-core-Export-line-card-API.patch @@ -1,7 +1,7 @@ -From 8099c3baf5f819fdf187b67cc3ed0ce25360cf88 Mon Sep 17 00:00:00 2001 +From a89d212954b74f3169e3061a3623eadfb86441e6 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 19 Dec 2021 09:31:32 +0000 -Subject: [PATCH] mlxsw: core: Export line card API +Subject: [PATCH backport 5.10 154/182] mlxsw: core: Export line card API Export API mlxsw_core_linecards() for being used by 'minimal' driver. @@ -11,7 +11,7 @@ Signed-off-by: Vadim Pasternak 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c -index a9bb43837..a26c6d880 100644 +index a9bb43837b33..a26c6d880928 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -103,6 +103,7 @@ struct mlxsw_linecards *mlxsw_core_linecards(struct mlxsw_core *mlxsw_core) @@ -23,5 +23,5 @@ index a9bb43837..a26c6d880 100644 #define MLXSW_PORT_MAX_PORTS_DEFAULT 0x40 -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch b/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch index 7bce0a016d..da23b70862 100644 --- a/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch +++ b/platform/mellanox/non-upstream-patches/patches/0155-mlxsw-minimal-Add-system-event-handler.patch @@ -1,7 +1,8 @@ -From b526413a86afcd1d6bd3f4e05f25631c8103f617 Mon Sep 17 00:00:00 2001 +From deb4f328672850d9ac4d8d51be7e0d8e727387af Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 19 Dec 2021 09:25:35 +0000 -Subject: [PATCH] mlxsw: minimal: Add system event handler +Subject: [PATCH backport 5.10 155/182] mlxsw: minimal: Add system event + handler Add system event handler for treating line card specific signals on modular system. These signals indicate line card state changes, like @@ -16,7 +17,7 @@ Signed-off-by: Vadim Pasternak 1 file changed, 23 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c -index 59c5053dc..27afb28e4 100644 +index 59c5053dc5fd..27afb28e439f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -527,6 +527,28 @@ static void mlxsw_m_line_cards_free(struct mlxsw_m *mlxsw_m) @@ -57,5 +58,5 @@ index 59c5053dc..27afb28e4 100644 .res_query_enabled = true, }; -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch b/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch index 6b1049f6d1..421536ead3 100644 --- a/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch +++ b/platform/mellanox/non-upstream-patches/patches/0156-mlxsw-minimal-Add-interfaces-for-line-card-initializ.patch @@ -1,8 +1,8 @@ -From 20b2dd627f42e79a8fce30d29d4cea64f6636521 Mon Sep 17 00:00:00 2001 +From 933a623916a00d83616d653a82329750d94de0f1 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 19 Dec 2021 09:40:34 +0000 -Subject: [PATCH] mlxsw: minimal: Add interfaces for line card initialization - and de-initialization +Subject: [PATCH backport 5.10 156/182] mlxsw: minimal: Add interfaces for line + card initialization and de-initialization Add callback functions for line card 'netdevice' objects initialization and de-initialization. Each line card is associated with the set of @@ -18,7 +18,7 @@ Signed-off-by: Vadim Pasternak 1 file changed, 70 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c -index 27afb28e4..0b605c6aa 100644 +index 27afb28e439f..0b605c6aa637 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -549,6 +549,69 @@ static void mlxsw_m_sys_event_handler(struct mlxsw_core *mlxsw_core) @@ -115,5 +115,5 @@ index 27afb28e4..0b605c6aa 100644 mlxsw_m_line_cards_free(mlxsw_m); } -- -2.30.2 +2.20.1 diff --git a/platform/mellanox/non-upstream-patches/patches/0163-platform-mellanox-Introduce-support-for-rack-manager.patch b/platform/mellanox/non-upstream-patches/patches/0163-platform-mellanox-Introduce-support-for-rack-manager.patch deleted file mode 100644 index aa9f7fceb4..0000000000 --- a/platform/mellanox/non-upstream-patches/patches/0163-platform-mellanox-Introduce-support-for-rack-manager.patch +++ /dev/null @@ -1,420 +0,0 @@ -From bb18ddc163092447e40f8aba96140280e2201409 Mon Sep 17 00:00:00 2001 -From: Vadim Pasternak -Date: Mon, 14 Feb 2022 13:24:44 +0200 -Subject: [PATCH] platform: mellanox: Introduce support for rack manager switch - -The rack switch is designed to provide high bandwidth, low latency -connectivity using optical fiber as the primary interconnect. - -System supports 32 OSFP ports, non-blocking switching capacity of -25.6Tbps. -System equipped with: -- 2 replaceable power supplies (AC) with 1+1 redundancy model. -- 7 replaceable fan drawers with 6+1 redundancy model. -- 2 External Root of Trust or EROT (Glacier) devices for securing - ASICs firmware. - -Signed-off-by: Vadim Pasternak ---- - drivers/platform/x86/mlx-platform.c | 259 ++++++++++++++++++++++++++++ - 1 file changed, 259 insertions(+) - -diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c -index d0bb2becf..f1d0cc1aa 100644 ---- a/drivers/platform/x86/mlx-platform.c -+++ b/drivers/platform/x86/mlx-platform.c -@@ -90,6 +90,12 @@ - #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 - #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 - #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a -+#define MLXPLAT_CPLD_LPC_REG_EROT_OFFSET 0x91 -+#define MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET 0x92 -+#define MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET 0x93 -+#define MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET 0x94 -+#define MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET 0x95 -+#define MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET 0x96 - #define MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET 0x9a - #define MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET 0x9b - #define MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET 0x9c -@@ -109,6 +115,8 @@ - #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa - #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab - #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2 -+#define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 -+#define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 - #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 - #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8 - #define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9 -@@ -214,6 +222,7 @@ - #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0) - #define MLXPLAT_CPLD_VOLTREG_UPD_MASK GENMASK(5, 4) - #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) -+#define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) - #define MLXPLAT_CPLD_I2C_CAP_BIT 0x04 - #define MLXPLAT_CPLD_I2C_CAP_MASK GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT) - -@@ -243,6 +252,7 @@ - #define MLXPLAT_CPLD_CH2_ETH_MODULAR 3 - #define MLXPLAT_CPLD_CH3_ETH_MODULAR 43 - #define MLXPLAT_CPLD_CH4_ETH_MODULAR 51 -+#define MLXPLAT_CPLD_CH2_RACK_SWITCH 18 - - /* Number of LPC attached MUX platform devices */ - #define MLXPLAT_CPLD_LPC_MUX_DEVS 4 -@@ -280,6 +290,9 @@ - /* Minimum power required for turning on Ethernet modular system (WATT) */ - #define MLXPLAT_CPLD_ETH_MODULAR_PWR_MIN 50 - -+/* Default value for PWM control register for rack switch system */ -+#define MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT 0xf4 -+ - /* mlxplat_priv - platform private data - * @pdev_i2c - i2c controller platform device - * @pdev_mux - array of mux platform devices -@@ -460,6 +473,36 @@ static struct i2c_mux_reg_platform_data mlxplat_modular_mux_data[] = { - }, - }; - -+/* Platform channels for rack swicth system family */ -+static const int mlxplat_rack_switch_channels[] = { -+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -+}; -+ -+/* Platform rack switch mux data */ -+static struct i2c_mux_reg_platform_data mlxplat_rack_switch_mux_data[] = { -+ { -+ .parent = 1, -+ .base_nr = MLXPLAT_CPLD_CH1, -+ .write_only = 1, -+ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, -+ .reg_size = 1, -+ .idle_in_use = 1, -+ .values = mlxplat_rack_switch_channels, -+ .n_values = ARRAY_SIZE(mlxplat_rack_switch_channels), -+ }, -+ { -+ .parent = 1, -+ .base_nr = MLXPLAT_CPLD_CH2_RACK_SWITCH, -+ .write_only = 1, -+ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, -+ .reg_size = 1, -+ .idle_in_use = 1, -+ .values = mlxplat_msn21xx_channels, -+ .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), -+ }, -+ -+}; -+ - /* Platform hotplug devices */ - static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { - { -@@ -2064,6 +2107,97 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_chassis_blade_data = { - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, - }; - -+/* Platform hotplug for switch systems family data */ -+static struct mlxreg_core_data mlxplat_mlxcpld_erot_ap_items_data[] = { -+ { -+ .label = "erot1_ap", -+ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, -+ .mask = BIT(0), -+ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, -+ }, -+ { -+ .label = "erot2_ap", -+ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, -+ .mask = BIT(1), -+ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, -+ }, -+}; -+ -+static struct mlxreg_core_data mlxplat_mlxcpld_erot_error_items_data[] = { -+ { -+ .label = "erot1_error", -+ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, -+ .mask = BIT(0), -+ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, -+ }, -+ { -+ .label = "erot2_error", -+ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, -+ .mask = BIT(1), -+ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, -+ }, -+}; -+ -+static struct mlxreg_core_item mlxplat_mlxcpld_rack_switch_items[] = { -+ { -+ .data = mlxplat_mlxcpld_ext_psu_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, -+ .mask = MLXPLAT_CPLD_PSU_EXT_MASK, -+ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_psu_items_data), -+ .inversed = 1, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_ext_pwr_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, -+ .mask = MLXPLAT_CPLD_PWR_EXT_MASK, -+ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_pwr_items_data), -+ .inversed = 0, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_default_ng_fan_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, -+ .mask = MLXPLAT_CPLD_FAN_NG_MASK, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), -+ .inversed = 1, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_erot_ap_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, -+ .mask = MLXPLAT_CPLD_EROT_MASK, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_ap_items_data), -+ .inversed = 1, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_erot_error_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, -+ .mask = MLXPLAT_CPLD_EROT_MASK, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_error_items_data), -+ .inversed = 1, -+ .health = false, -+ }, -+}; -+ -+static -+struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = { -+ .items = mlxplat_mlxcpld_rack_switch_items, -+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_rack_switch_items), -+ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, -+ .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, -+ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, -+ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -+}; -+ - /* Platform led default data */ - static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = { - { -@@ -2947,6 +3081,42 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, -+ { -+ .label = "erot1_reset", -+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(6), -+ .mode = 0644, -+ }, -+ { -+ .label = "erot2_reset", -+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(7), -+ .mode = 0644, -+ }, -+ { -+ .label = "erot1_recovery", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(6), -+ .mode = 0644, -+ }, -+ { -+ .label = "erot2_recovery", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(7), -+ .mode = 0644, -+ }, -+ { -+ .label = "erot1_wp", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(4), -+ .mode = 0644, -+ }, -+ { -+ .label = "erot2_wp", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(5), -+ .mode = 0644, -+ }, - { - .label = "reset_long_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, -@@ -3142,6 +3312,25 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, -+ { -+ .label = "erot1_ap_reset", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(0), -+ .mode = 0444, -+ }, -+ { -+ .label = "erot2_ap_reset", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(1), -+ .mode = 0444, -+ }, -+ { -+ .label = "spi_chnl_select", -+ .reg = MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT, -+ .mask = GENMASK(7, 0), -+ .bit = 1, -+ .mode = 0644, -+ }, - { - .label = "config1", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET, -@@ -4257,6 +4446,10 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) - case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET: -@@ -4274,6 +4467,8 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) - case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: -+ case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET: -@@ -4358,6 +4553,12 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) - case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: -@@ -4382,6 +4583,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) - case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: -+ case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET: -@@ -4492,6 +4694,12 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) - case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: -@@ -4516,6 +4724,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) - case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: -+ case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET: -+ case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: - case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: -@@ -4583,6 +4793,13 @@ static const struct reg_default mlxplat_mlxcpld_regmap_ng400[] = { - { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, - }; - -+static const struct reg_default mlxplat_mlxcpld_regmap_rack_switch[] = { -+ { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT }, -+ { MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 }, -+ { MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, 0x00 }, -+ { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, -+}; -+ - static const struct reg_default mlxplat_mlxcpld_regmap_eth_modular[] = { - { MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 0x61 }, - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, -@@ -4676,6 +4893,20 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_ng400 = { - .reg_write = mlxplat_mlxcpld_reg_write, - }; - -+static const struct regmap_config mlxplat_mlxcpld_regmap_config_rack_switch = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .max_register = 255, -+ .cache_type = REGCACHE_FLAT, -+ .writeable_reg = mlxplat_mlxcpld_writeable_reg, -+ .readable_reg = mlxplat_mlxcpld_readable_reg, -+ .volatile_reg = mlxplat_mlxcpld_volatile_reg, -+ .reg_defaults = mlxplat_mlxcpld_regmap_rack_switch, -+ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_rack_switch), -+ .reg_read = mlxplat_mlxcpld_reg_read, -+ .reg_write = mlxplat_mlxcpld_reg_write, -+}; -+ - static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = { - .reg_bits = 8, - .val_bits = 8, -@@ -4957,6 +5188,27 @@ static int __init mlxplat_dmi_modular_matched(const struct dmi_system_id *dmi) - return 1; - } - -+static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dmi) -+{ -+ int i; -+ -+ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; -+ mlxplat_mux_num = ARRAY_SIZE(mlxplat_rack_switch_mux_data); -+ mlxplat_mux_data = mlxplat_rack_switch_mux_data; -+ mlxplat_hotplug = &mlxplat_mlxcpld_rack_switch_data; -+ mlxplat_hotplug->deferred_nr = -+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; -+ mlxplat_led = &mlxplat_default_ng_led_data; -+ mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; -+ mlxplat_fan = &mlxplat_default_fan_data; -+ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) -+ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; -+ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; -+ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; -+ -+ return 1; -+} -+ - static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { - { - .callback = mlxplat_dmi_default_wc_matched, -@@ -5007,6 +5259,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0009"), - }, - }, -+ { -+ .callback = mlxplat_dmi_rack_switch_matched, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0010"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI142"), -+ }, -+ }, - { - .callback = mlxplat_dmi_ng400_matched, - .matches = { --- -2.30.2 - diff --git a/platform/mellanox/non-upstream-patches/patches/0167-DS-lan743x-Add-support-for-fixed-phy.patch b/platform/mellanox/non-upstream-patches/patches/0167-DS-lan743x-Add-support-for-fixed-phy.patch new file mode 100644 index 0000000000..b1dea01211 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0167-DS-lan743x-Add-support-for-fixed-phy.patch @@ -0,0 +1,97 @@ +From 12b2a85b4b3bb17f44611b9c320fd4e84915b122 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 6 May 2022 16:52:53 +0300 +Subject: [PATCH backport 5.10 167/182] DS: lan743x: Add support for fixed phy + +Add support for fixed phy for non DTS architecture. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/microchip/Kconfig | 11 ++++++++ + drivers/net/ethernet/microchip/lan743x_main.c | 26 ++++++++++++++++--- + 2 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig +index d0f6dfe0dcf3..6c66b55bc811 100644 +--- a/drivers/net/ethernet/microchip/Kconfig ++++ b/drivers/net/ethernet/microchip/Kconfig +@@ -54,4 +54,15 @@ config LAN743X + To compile this driver as a module, choose M here. The module will be + called lan743x. + ++config LAN743X_FIXED_PHY ++ bool "Direct R/G/MII connection without PHY" ++ default n ++ depends on LAN743X ++ select FIXED_PHY ++ help ++ Direct R/G/MII connection to a remote MII device without PHY in between. ++ No mdio bus will be used in this case and no auto-negotiation takes place. ++ The configuration settings below need to mirror the configuration of the ++ remote MII device. ++ + endif # NET_VENDOR_MICROCHIP +diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c +index 481f89d193f7..b6250a7469da 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -798,6 +798,7 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter) + + /* disable auto duplex, and speed detection. Phylib does that */ + data = lan743x_csr_read(adapter, MAC_CR); ++ + data &= ~(MAC_CR_ADD_ | MAC_CR_ASD_); + data |= MAC_CR_CNTR_RST_; + lan743x_csr_write(adapter, MAC_CR, data); +@@ -1002,7 +1003,10 @@ static void lan743x_phy_close(struct lan743x_adapter *adapter) + struct net_device *netdev = adapter->netdev; + + phy_stop(netdev->phydev); +- phy_disconnect(netdev->phydev); ++ if (IS_REACHABLE(CONFIG_LAN743X_FIXED_PHY)) ++ fixed_phy_unregister(netdev->phydev); ++ else ++ phy_disconnect(netdev->phydev); + netdev->phydev = NULL; + } + +@@ -1038,11 +1042,24 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter) + + if (!phydev) { + /* try internal phy */ +- phydev = phy_find_first(adapter->mdiobus); ++ if (IS_REACHABLE(CONFIG_LAN743X_FIXED_PHY)) { ++ struct fixed_phy_status phy_status; ++ ++ phy_status.link = 1; ++ phy_status.speed = 1000; ++ phy_status.duplex = DUPLEX_FULL; ++ phy_status.pause = 0; ++ phy_status.asym_pause = 0; ++ adapter->phy_mode = PHY_INTERFACE_MODE_RGMII; ++ phydev = fixed_phy_register(PHY_POLL, &phy_status, 0); ++ } else { ++ adapter->phy_mode = PHY_INTERFACE_MODE_GMII; ++ phydev = phy_find_first(adapter->mdiobus); ++ } ++ + if (!phydev) + goto return_error; + +- adapter->phy_mode = PHY_INTERFACE_MODE_GMII; + ret = phy_connect_direct(netdev, phydev, + lan743x_phy_link_status_change, + adapter->phy_mode); +@@ -1059,7 +1076,8 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter) + phy->fc_autoneg = phydev->autoneg; + + phy_start(phydev); +- phy_start_aneg(phydev); ++ if (!IS_REACHABLE(CONFIG_LAN743X_FIXED_PHY)) ++ phy_start_aneg(phydev); + return 0; + + return_error: +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0168-TMP-mlxsw-minimal-Ignore-error-reading-SPAD-register.patch b/platform/mellanox/non-upstream-patches/patches/0168-TMP-mlxsw-minimal-Ignore-error-reading-SPAD-register.patch new file mode 100644 index 0000000000..1a180318dd --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0168-TMP-mlxsw-minimal-Ignore-error-reading-SPAD-register.patch @@ -0,0 +1,34 @@ +From cbb77f161d60964733f332e4ccfb9f240947c3ef Mon Sep 17 00:00:00 2001 +From: root +Date: Tue, 5 Apr 2022 21:35:55 +0300 +Subject: [PATCH backport 5.10 168/182] TMP: mlxsw: minimal: Ignore error + reading SPAD register + +WA until FW will add support for SPAD register for all systems. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 0b605c6aa637..5fd319697c94 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -64,11 +64,12 @@ static int mlxsw_m_base_mac_get(struct mlxsw_m *mlxsw_m) + { + char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; + int err; +- ++#if 0 + err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(spad), spad_pl); + if (err) + return err; + mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_m->base_mac); ++#endif + return 0; + } + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch b/platform/mellanox/non-upstream-patches/patches/0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch new file mode 100644 index 0000000000..0632d1bc36 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch @@ -0,0 +1,194 @@ +From 7a45b6a2a14c292e89a09afde8fcc7d1ceb20ebd Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 22 Jun 2022 13:01:15 +0300 +Subject: [PATCH backport 5.10 171/182] platform/mellanox: mlxreg-lc: Fix + cleanup on failure and add more verbosity in error flow + +Clean client object in case of probing failure. +Prevent running remove routine in case probing failed. +Add error log for each kind of failures during probing. + +Fixes: 62f9529b8d5c ("platform/mellanox: mlxreg-lc: Add initial support for Nvidia line card devices") +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlxreg-lc.c | 85 ++++++++++++++++++++------- + 1 file changed, 63 insertions(+), 22 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxreg-lc.c b/drivers/platform/mellanox/mlxreg-lc.c +index 75c28179dd07..e3caccb1a528 100644 +--- a/drivers/platform/mellanox/mlxreg-lc.c ++++ b/drivers/platform/mellanox/mlxreg-lc.c +@@ -569,9 +569,6 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind, + dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n", + mlxreg_lc->data->slot, mlxreg_lc->state, kind, action); + +- if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED)) +- return 0; +- + switch (kind) { + case MLXREG_HOTPLUG_LC_SYNCED: + /* +@@ -725,8 +722,12 @@ mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap, + switch (regval) { + case MLXREG_LC_SN4800_C16: + err = mlxreg_lc_sn4800_c16_config_init(mlxreg_lc, regmap, data); +- if (err) ++ if (err) { ++ dev_err(dev, "Failed to config client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, ++ data->hpdev.brdinfo->addr); + return err; ++ } + break; + default: + return -ENODEV; +@@ -739,8 +740,11 @@ mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap, + mlxreg_lc->mux = platform_device_register_resndata(dev, "i2c-mux-mlxcpld", data->hpdev.nr, + NULL, 0, mlxreg_lc->mux_data, + sizeof(*mlxreg_lc->mux_data)); +- if (IS_ERR(mlxreg_lc->mux)) ++ if (IS_ERR(mlxreg_lc->mux)) { ++ dev_err(dev, "Failed to create mux infra for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); + return PTR_ERR(mlxreg_lc->mux); ++ } + + /* Register IO access driver. */ + if (mlxreg_lc->io_data) { +@@ -749,6 +753,9 @@ mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap, + platform_device_register_resndata(dev, "mlxreg-io", data->hpdev.nr, NULL, 0, + mlxreg_lc->io_data, sizeof(*mlxreg_lc->io_data)); + if (IS_ERR(mlxreg_lc->io_regs)) { ++ dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, ++ data->hpdev.brdinfo->addr); + err = PTR_ERR(mlxreg_lc->io_regs); + goto fail_register_io; + } +@@ -762,6 +769,9 @@ mlxreg_lc_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap, + mlxreg_lc->led_data, + sizeof(*mlxreg_lc->led_data)); + if (IS_ERR(mlxreg_lc->led)) { ++ dev_err(dev, "Failed to create LED objects for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, ++ data->hpdev.brdinfo->addr); + err = PTR_ERR(mlxreg_lc->led); + goto fail_register_led; + } +@@ -818,7 +828,8 @@ static int mlxreg_lc_probe(struct platform_device *pdev) + if (!data->hpdev.adapter) { + dev_err(&pdev->dev, "Failed to get adapter for bus %d\n", + data->hpdev.nr); +- return -EFAULT; ++ err = -EFAULT; ++ goto i2c_get_adapter_fail; + } + + /* Create device at the top of line card I2C tree.*/ +@@ -827,32 +838,40 @@ static int mlxreg_lc_probe(struct platform_device *pdev) + if (IS_ERR(data->hpdev.client)) { + dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n", + data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); +- +- i2c_put_adapter(data->hpdev.adapter); +- data->hpdev.adapter = NULL; +- return PTR_ERR(data->hpdev.client); ++ err = PTR_ERR(data->hpdev.client); ++ goto i2c_new_device_fail; + } + + regmap = devm_regmap_init_i2c(data->hpdev.client, + &mlxreg_lc_regmap_conf); + if (IS_ERR(regmap)) { ++ dev_err(&pdev->dev, "Failed to create regmap for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); + err = PTR_ERR(regmap); +- goto mlxreg_lc_probe_fail; ++ goto devm_regmap_init_i2c_fail; + } + + /* Set default registers. */ + for (i = 0; i < mlxreg_lc_regmap_conf.num_reg_defaults; i++) { + err = regmap_write(regmap, mlxreg_lc_regmap_default[i].reg, + mlxreg_lc_regmap_default[i].def); +- if (err) +- goto mlxreg_lc_probe_fail; ++ if (err) { ++ dev_err(&pdev->dev, "Failed to set default regmap %d for client %s at bus %d at addr 0x%02x\n", ++ i, data->hpdev.brdinfo->type, data->hpdev.nr, ++ data->hpdev.brdinfo->addr); ++ goto regmap_write_fail; ++ } + } + + /* Sync registers with hardware. */ + regcache_mark_dirty(regmap); + err = regcache_sync(regmap); +- if (err) +- goto mlxreg_lc_probe_fail; ++ if (err) { ++ dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); ++ err = PTR_ERR(regmap); ++ goto regcache_sync_fail; ++ } + + par_pdata = data->hpdev.brdinfo->platform_data; + mlxreg_lc->par_regmap = par_pdata->regmap; +@@ -863,12 +882,27 @@ static int mlxreg_lc_probe(struct platform_device *pdev) + /* Configure line card. */ + err = mlxreg_lc_config_init(mlxreg_lc, regmap, data); + if (err) +- goto mlxreg_lc_probe_fail; ++ goto mlxreg_lc_config_init_fail; + + return err; + +-mlxreg_lc_probe_fail: ++mlxreg_lc_config_init_fail: ++regcache_sync_fail: ++regmap_write_fail: ++devm_regmap_init_i2c_fail: ++ if (data->hpdev.client) { ++ i2c_unregister_device(data->hpdev.client); ++ data->hpdev.client = NULL; ++ } ++i2c_new_device_fail: + i2c_put_adapter(data->hpdev.adapter); ++ data->hpdev.adapter = NULL; ++i2c_get_adapter_fail: ++ /* Clear event notification callback and handle. */ ++ if (data->notifier) { ++ data->notifier->user_handler = NULL; ++ data->notifier->handle = NULL; ++ } + return err; + } + +@@ -877,11 +911,18 @@ static int mlxreg_lc_remove(struct platform_device *pdev) + struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev); + struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev); + +- /* Clear event notification callback. */ +- if (data->notifier) { +- data->notifier->user_handler = NULL; +- data->notifier->handle = NULL; +- } ++ /* ++ * Probing and removing are invoked by hotplug events raised on line card insertion and ++ * removing. If probing procedure fails all data is cleared. However, hotplug event still ++ * will be raised on line card removing and activate removing procedure. In this case there ++ * is nothing to remove. ++ */ ++ if (!data->notifier || !data->notifier->handle) ++ return 0; ++ ++ /* Clear event notification callback and handle. */ ++ data->notifier->user_handler = NULL; ++ data->notifier->handle = NULL; + + /* Destroy static I2C device feeding by main power. */ + mlxreg_lc_destroy_static_devices(mlxreg_lc, mlxreg_lc->main_devs, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0172-DS-platform-mlx-platform-Add-SPI-path-for-rack-switc.patch b/platform/mellanox/non-upstream-patches/patches/0172-DS-platform-mlx-platform-Add-SPI-path-for-rack-switc.patch new file mode 100644 index 0000000000..b5ec0ea19a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0172-DS-platform-mlx-platform-Add-SPI-path-for-rack-switc.patch @@ -0,0 +1,84 @@ +From b1e9734f4dc29c65e05a8f35ec67efb7784d321f Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 15 May 2022 14:31:10 +0300 +Subject: [PATCH backport 5.10 172/182] DS: platform: mlx-platform: Add SPI + path for rack switch for EROT access + +Create spidev for OOB access to External Root of Trusts devices. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 16 ++++++++++++++++ + drivers/spi/spi.c | 1 + + 2 files changed, 17 insertions(+) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 3ad85934d6e3..135ccea3a34e 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #define MLX_PLAT_DEVICE_NAME "mlxplat" + +@@ -2299,6 +2300,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = { + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + ++static struct spi_board_info rack_switch_switch_spi_board_info[] = { ++ { ++ .modalias = "spidev", ++ .irq = -1, ++ .max_speed_hz = 20000000, ++ .bus_num = 0, ++ .chip_select = 0, ++ }, ++}; ++ + /* Platform led default data */ + static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = { + { +@@ -5254,6 +5265,7 @@ static struct mlxreg_core_platform_data *mlxplat_fan; + static struct mlxreg_core_platform_data + *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS]; + static const struct regmap_config *mlxplat_regmap_config; ++static struct spi_board_info *mlxplat_spi; + + static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) + { +@@ -5551,6 +5563,7 @@ static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dm + mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; + mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; + mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; ++ mlxplat_spi = rack_switch_switch_spi_board_info; + + return 1; + } +@@ -5917,6 +5930,9 @@ static int __init mlxplat_init(void) + } + } + ++ if (mlxplat_spi) ++ spi_register_board_info(mlxplat_spi, 1); ++ + /* Add WD drivers. */ + err = mlxplat_mlxcpld_check_wd_capability(priv->regmap); + if (err) +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 857a1399850c..2efafa34ff22 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -790,6 +790,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) + + return 0; + } ++EXPORT_SYMBOL(spi_register_board_info); + + /*-------------------------------------------------------------------------*/ + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0174-DS-mlxsw-core_linecards-Skip-devlink-and-provisionin.patch b/platform/mellanox/non-upstream-patches/patches/0174-DS-mlxsw-core_linecards-Skip-devlink-and-provisionin.patch new file mode 100644 index 0000000000..6c0b439813 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0174-DS-mlxsw-core_linecards-Skip-devlink-and-provisionin.patch @@ -0,0 +1,93 @@ +From 8b0f2061c6f8d799b7da9b7f50edb18208e67bb8 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 22 Jul 2022 01:15:43 +0300 +Subject: [PATCH backport 5.10 174/182] DS: mlxsw: core_linecards: Skip devlink + and provisioning operation + +Do not execute provisioning / unprovisioning flow in not upstream +environment. + +Signed-off-by: Vadim Pasternak +--- + .../net/ethernet/mellanox/mlxsw/core_linecards.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index 3a2fdd22dc21..30665a6f3e4d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -651,8 +651,11 @@ mlxsw_linecard_provision_set(struct mlxsw_core *mlxsw_core, + linecard); + if (err) + goto err_cbs_call; ++ + linecard->provisioned = true; ++#if 0 + devlink_linecard_provision_set(linecard->devlink_linecard, type); ++#endif + return 0; + + err_cbs_call: +@@ -670,12 +673,15 @@ static void mlxsw_linecard_provision_clear(struct mlxsw_core *mlxsw_core, + linecard); + mlxsw_linecard_devices_detach(linecard->linecards->mlxsw_core, + linecard); ++#if 0 + devlink_linecard_provision_clear(linecard->devlink_linecard); ++#endif + } + + static int mlxsw_linecard_ready_set(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecard *linecard) + { ++#if 0 + char mddc_pl[MLXSW_REG_MDDC_LEN]; + int err; + +@@ -683,6 +689,7 @@ static int mlxsw_linecard_ready_set(struct mlxsw_core *mlxsw_core, + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); + if (err) + return err; ++#endif + linecard->ready = true; + return 0; + } +@@ -690,6 +697,7 @@ static int mlxsw_linecard_ready_set(struct mlxsw_core *mlxsw_core, + static int mlxsw_linecard_ready_clear(struct mlxsw_core *mlxsw_core, + struct mlxsw_linecard *linecard) + { ++#if 0 + char mddc_pl[MLXSW_REG_MDDC_LEN]; + int err; + +@@ -697,6 +705,7 @@ static int mlxsw_linecard_ready_clear(struct mlxsw_core *mlxsw_core, + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); + if (err) + return err; ++#endif + linecard->ready = false; + return 0; + } +@@ -722,7 +731,9 @@ static int mlxsw_linecard_active_set(struct mlxsw_core *mlxsw_core, + item->event_ops->got_active(mlxsw_core, linecard->slot_index, + linecard, item->priv); + } ++#if 0 + devlink_linecard_activate(linecard->devlink_linecard); ++#endif + return 0; + } + +@@ -739,7 +750,9 @@ static void mlxsw_linecard_active_clear(struct mlxsw_core *mlxsw_core, + item->event_ops->got_inactive(mlxsw_core, linecard->slot_index, + linecard, item->priv); + } ++#if 0 + devlink_linecard_deactivate(linecard->devlink_linecard); ++#endif + } + + static int __mlxsw_linecard_status_process(struct mlxsw_core *mlxsw_core, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch b/platform/mellanox/non-upstream-patches/patches/0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch deleted file mode 100644 index 17d55632e8..0000000000 --- a/platform/mellanox/non-upstream-patches/patches/0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d3b1142ce6c3fbb02c39fc8d2e9f24ecbf466973 Mon Sep 17 00:00:00 2001 -From: Michael Shych -Date: Sun, 4 Sep 2022 10:41:45 +0300 -Subject: [PATCH] platform: mellanox: fix reset_pwr_converter_fail attribute. - -Change incorrect reset_voltmon_upgrade_fail atitribute name to -reset_pwr_converter_fail. - -Signed-off-by: Michael Shych -Reviewed-by: Vadim Pasternak ---- - drivers/platform/x86/mlx-platform.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c -index f1d0cc1aa..31c5cc10f 100644 ---- a/drivers/platform/x86/mlx-platform.c -+++ b/drivers/platform/x86/mlx-platform.c -@@ -3904,7 +3904,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_chassis_blade_regs_io_data[] = { - .mode = 0444, - }, - { -- .label = "reset_voltmon_upgrade_fail", -+ .label = "reset_pwr_converter_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, --- -2.30.2 - diff --git a/platform/mellanox/non-upstream-patches/patches/0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch b/platform/mellanox/non-upstream-patches/patches/0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch deleted file mode 100644 index 7fd978b051..0000000000 --- a/platform/mellanox/non-upstream-patches/patches/0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 85ac7ddf15f380460b9e17f0e2c99aa8e476ef3f Mon Sep 17 00:00:00 2001 -From: Michael Shych -Date: Sun, 4 Sep 2022 10:46:01 +0300 -Subject: [PATCH] Documentation/ABI: fix description of fix - reset_pwr_converter_fail attribute. - -Change description of incorrect reset_voltmon_upgrade_fail atitribute -name to reset_pwr_converter_fail. - -Signed-off-by: Michael Shych -Reviewed-by: Vadim Pasternak ---- - Documentation/ABI/stable/sysfs-driver-mlxreg-io | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io -index 0913a8daf..ac503e84e 100644 ---- a/Documentation/ABI/stable/sysfs-driver-mlxreg-io -+++ b/Documentation/ABI/stable/sysfs-driver-mlxreg-io -@@ -103,13 +103,13 @@ Description: These files show the system reset cause, as following: power - What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_pwr_fail - What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_comex - What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_system --What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_voltmon_upgrade_fail -+What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_pwr_converter_fail - Date: November 2018 - KernelVersion: 5.0 - Contact: Vadim Pasternak - Description: These files show the system reset cause, as following: ComEx - power fail, reset from ComEx, system platform reset, reset -- due to voltage monitor devices upgrade failure, -+ due to power converter devices failure, - Value 1 in file means this is reset cause, 0 - otherwise. - Only one bit could be 1 at the same time, representing only - the last reset cause. --- -2.30.2 - diff --git a/platform/mellanox/non-upstream-patches/patches/0178-platform-mellanox-Introduce-support-for-next-generat.patch b/platform/mellanox/non-upstream-patches/patches/0178-platform-mellanox-Introduce-support-for-next-generat.patch deleted file mode 100644 index 922bc84b74..0000000000 --- a/platform/mellanox/non-upstream-patches/patches/0178-platform-mellanox-Introduce-support-for-next-generat.patch +++ /dev/null @@ -1,295 +0,0 @@ -From 4c485e6f50001f0ea691b0ce5c0d90a118e8d360 Mon Sep 17 00:00:00 2001 -From: Michael Shych -Date: Sun, 4 Sep 2022 14:03:58 +0300 -Subject: [PATCH] platform: mellanox: Introduce support for next-generation - 800GB/s ethernet switch. - -Introduce support for Nvidia next-generation 800GB/s ethernet switch - SN5600. -SN5600 is 51.2 Tbps Ethernet switch based on Nvidia Spectrum-4 ASIC. -It can provide up to 64x800Gb/s (ETH) full bidirectional bandwidth per port -using PAM-4 modulations. The system supports 64 Belly to Belly 2x4 OSFP cages. -The switch was designed to fit standard 2U racks. - -Features: -- 64 OSFP ports support 800GbE - 10GbE speed. -- Additional 25GbE - 1GbE service port on the front panel. -- Air-cooled with 3 + 1 redundant fan units. -- 1 + 1 redundant 3000W or 3600W PSUs. -- System management board is based on Intel Coffee-lake CPU E-2276 - with secure-boot support. - -Signed-off-by: Michael Shych -Reviewed-by: Vadim Pasternak ---- - drivers/platform/x86/mlx-platform.c | 178 ++++++++++++++++++++++++++++ - 1 file changed, 178 insertions(+) - -diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c -index 31c5cc10f..7e9f2a5ab 100644 ---- a/drivers/platform/x86/mlx-platform.c -+++ b/drivers/platform/x86/mlx-platform.c -@@ -253,6 +253,7 @@ - #define MLXPLAT_CPLD_CH3_ETH_MODULAR 43 - #define MLXPLAT_CPLD_CH4_ETH_MODULAR 51 - #define MLXPLAT_CPLD_CH2_RACK_SWITCH 18 -+#define MLXPLAT_CPLD_CH2_NG800 34 - - /* Number of LPC attached MUX platform devices */ - #define MLXPLAT_CPLD_LPC_MUX_DEVS 4 -@@ -503,6 +504,37 @@ static struct i2c_mux_reg_platform_data mlxplat_rack_switch_mux_data[] = { - - }; - -+/* Platform channels for ng800 system family */ -+static const int mlxplat_ng800_channels[] = { -+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 -+}; -+ -+/* Platform ng800 mux data */ -+static struct i2c_mux_reg_platform_data mlxplat_ng800_mux_data[] = { -+ { -+ .parent = 1, -+ .base_nr = MLXPLAT_CPLD_CH1, -+ .write_only = 1, -+ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, -+ .reg_size = 1, -+ .idle_in_use = 1, -+ .values = mlxplat_ng800_channels, -+ .n_values = ARRAY_SIZE(mlxplat_ng800_channels), -+ }, -+ { -+ .parent = 1, -+ .base_nr = MLXPLAT_CPLD_CH2_NG800, -+ .write_only = 1, -+ .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, -+ .reg_size = 1, -+ .idle_in_use = 1, -+ .values = mlxplat_msn21xx_channels, -+ .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), -+ }, -+ -+}; -+ - /* Platform hotplug devices */ - static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { - { -@@ -522,6 +554,15 @@ static struct i2c_board_info mlxplat_mlxcpld_ext_pwr[] = { - }, - }; - -+static struct i2c_board_info mlxplat_mlxcpld_pwr_ng800[] = { -+ { -+ I2C_BOARD_INFO("dps460", 0x59), -+ }, -+ { -+ I2C_BOARD_INFO("dps460", 0x5a), -+ }, -+}; -+ - static struct i2c_board_info mlxplat_mlxcpld_fan[] = { - { - I2C_BOARD_INFO("24c32", 0x50), -@@ -601,6 +642,23 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_wc_items_data[] = { - }, - }; - -+static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_ng800_items_data[] = { -+ { -+ .label = "pwr1", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, -+ .mask = BIT(0), -+ .hpdev.brdinfo = &mlxplat_mlxcpld_pwr_ng800[0], -+ .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, -+ }, -+ { -+ .label = "pwr2", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, -+ .mask = BIT(1), -+ .hpdev.brdinfo = &mlxplat_mlxcpld_pwr_ng800[1], -+ .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, -+ }, -+}; -+ - static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { - { - .label = "fan1", -@@ -1224,6 +1282,47 @@ static struct mlxreg_core_item mlxplat_mlxcpld_ext_items[] = { - } - }; - -+static struct mlxreg_core_item mlxplat_mlxcpld_ng800_items[] = { -+ { -+ .data = mlxplat_mlxcpld_default_ng_psu_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, -+ .mask = MLXPLAT_CPLD_PSU_EXT_MASK, -+ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data), -+ .inversed = 1, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_default_pwr_ng800_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, -+ .mask = MLXPLAT_CPLD_PWR_EXT_MASK, -+ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_ng800_items_data), -+ .inversed = 0, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_default_ng_fan_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, -+ .mask = MLXPLAT_CPLD_FAN_NG_MASK, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), -+ .inversed = 1, -+ .health = false, -+ }, -+ { -+ .data = mlxplat_mlxcpld_default_asic_items_data, -+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, -+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, -+ .mask = MLXPLAT_CPLD_ASIC_MASK, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), -+ .inversed = 0, -+ .health = true, -+ }, -+}; -+ - static - struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { - .items = mlxplat_mlxcpld_ext_items, -@@ -1234,6 +1333,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2, - }; - -+static -+struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ng800_data = { -+ .items = mlxplat_mlxcpld_ng800_items, -+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_ng800_items), -+ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, -+ .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, -+ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, -+ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2, -+}; -+ - static struct mlxreg_core_data mlxplat_mlxcpld_modular_pwr_items_data[] = { - { - .label = "pwr1", -@@ -3093,6 +3202,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0644, - }, -+ { -+ .label = "clk_brd_prog_en", -+ .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(1), -+ .mode = 0644, -+ }, - { - .label = "erot1_recovery", - .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, -@@ -3219,6 +3334,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, -+ { -+ .label = "reset_ac_ok_fail", -+ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(7), -+ .mode = 0444, -+ }, - { - .label = "psu1_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, -@@ -3324,6 +3445,30 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, -+ { -+ .label = "clk_brd1_boot_fail", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(4), -+ .mode = 0444, -+ }, -+ { -+ .label = "clk_brd2_boot_fail", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(5), -+ .mode = 0444, -+ }, -+ { -+ .label = "clk_brd_fail", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(6), -+ .mode = 0444, -+ }, -+ { -+ .label = "asic_pg_fail", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(7), -+ .mode = 0444, -+ }, - { - .label = "spi_chnl_select", - .reg = MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT, -@@ -3621,6 +3766,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_modular_regs_io_data[] = { - .bit = 5, - .mode = 0444, - }, -+ { -+ .label = "pwr_converter_prog_en", -+ .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, -+ .mask = GENMASK(7, 0) & ~BIT(0), -+ .mode = 0644, -+ }, - { - .label = "vpd_wp", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, -@@ -5209,6 +5360,27 @@ static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dm - return 1; - } - -+static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi) -+{ -+ int i; -+ -+ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; -+ mlxplat_mux_num = ARRAY_SIZE(mlxplat_ng800_mux_data); -+ mlxplat_mux_data = mlxplat_ng800_mux_data; -+ mlxplat_hotplug = &mlxplat_mlxcpld_ng800_data; -+ mlxplat_hotplug->deferred_nr = -+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; -+ mlxplat_led = &mlxplat_default_ng_led_data; -+ mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; -+ mlxplat_fan = &mlxplat_default_fan_data; -+ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) -+ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; -+ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; -+ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng400; -+ -+ return 1; -+} -+ - static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { - { - .callback = mlxplat_dmi_default_wc_matched, -@@ -5278,6 +5450,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0011"), - }, - }, -+ { -+ .callback = mlxplat_dmi_ng800_matched, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0013"), -+ }, -+ }, - { - .callback = mlxplat_dmi_chassis_blade_matched, - .matches = { --- -2.30.2 - diff --git a/platform/mellanox/non-upstream-patches/patches/0181-Revert-Fix-out-of-bounds-memory-accesses-in-thermal.patch b/platform/mellanox/non-upstream-patches/patches/0181-Revert-Fix-out-of-bounds-memory-accesses-in-thermal.patch new file mode 100644 index 0000000000..9580965684 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0181-Revert-Fix-out-of-bounds-memory-accesses-in-thermal.patch @@ -0,0 +1,99 @@ +From f2dffe0f83a05dfbf0190316f0d260f7d7ff76a8 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 23 Jan 2023 21:38:24 +0200 +Subject: [PATCH backport 5.10 181/182] Revert "mlxsw: thermal: Fix + out-of-bounds memory accesses" + +This reverts commit e59d839743b50cb1d3f42a786bea48cc5621d254. +--- + .../ethernet/mellanox/mlxsw/core_thermal.c | 52 +++++++++++++++++-- + 1 file changed, 47 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 529108aea3c6..88a2f63c8839 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -23,8 +23,16 @@ + #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2) + #define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0) + #define MLXSW_THERMAL_MAX_STATE 10 +-#define MLXSW_THERMAL_MIN_STATE 2 + #define MLXSW_THERMAL_MAX_DUTY 255 ++/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values ++ * MLXSW_THERMAL_MAX_STATE + x, where x is between 2 and 10 are used for ++ * setting fan speed dynamic minimum. For example, if value is set to 14 (40%) ++ * cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to ++ * introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100. ++ */ ++#define MLXSW_THERMAL_SPEED_MIN (MLXSW_THERMAL_MAX_STATE + 2) ++#define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2) ++#define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */ + + /* External cooling devices, allowed for binding to mlxsw thermal zones. */ + static char * const mlxsw_thermal_external_allowed_cdev[] = { +@@ -656,16 +664,49 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev, + struct mlxsw_thermal *thermal = cdev->devdata; + struct device *dev = thermal->bus_info->dev; + char mfsc_pl[MLXSW_REG_MFSC_LEN]; ++ unsigned long cur_state, i; + int idx; ++ u8 duty; + int err; + +- if (state > MLXSW_THERMAL_MAX_STATE) +- return -EINVAL; +- + idx = mlxsw_get_cooling_device_idx(thermal, cdev); + if (idx < 0) + return idx; + ++ /* Verify if this request is for changing allowed fan dynamical ++ * minimum. If it is - update cooling levels accordingly and update ++ * state, if current state is below the newly requested minimum state. ++ * For example, if current state is 5, and minimal state is to be ++ * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed ++ * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be ++ * overwritten. ++ */ ++ if (state >= MLXSW_THERMAL_SPEED_MIN && ++ state <= MLXSW_THERMAL_SPEED_MAX) { ++ state -= MLXSW_THERMAL_MAX_STATE; ++ for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++) ++ thermal->cooling_levels[i] = max(state, i); ++ ++ mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0); ++ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl); ++ if (err) ++ return err; ++ ++ duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl); ++ cur_state = mlxsw_duty_to_state(duty); ++ ++ /* If current fan state is lower than requested dynamical ++ * minimum, increase fan speed up to dynamical minimum. ++ */ ++ if (state < cur_state) ++ return 0; ++ ++ state = cur_state; ++ } ++ ++ if (state > MLXSW_THERMAL_MAX_STATE) ++ return -EINVAL; ++ + /* Normalize the state to the valid speed range. */ + state = thermal->cooling_levels[state]; + mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state)); +@@ -1143,7 +1184,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + + /* Initialize cooling levels per PWM state. */ + for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++) +- thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i); ++ thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL, ++ i); + + thermal->polling_delay = bus_info->low_frequency ? + MLXSW_THERMAL_SLOW_POLL_INT : +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0182-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch b/platform/mellanox/non-upstream-patches/patches/0182-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch new file mode 100644 index 0000000000..40e28f821f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0182-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch @@ -0,0 +1,647 @@ +From 74ab8a216510df924ca88d2f3d5944eb107264d0 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 11 Dec 2022 09:26:48 +0200 +Subject: [PATCH backport 5.10 1/5] platform: mellanox: Introduce support of + new Nvidia L1 switch + +Add support for new L1 switch nodes providing L1 connectivity for +multi-node networking chassis. + +The purpose is to provide compute server with full management and IO +subsystems with connections to L1 switches. + +System contains the following components: +- COMe module based on Intel Coffee Lake CPU +- Switch baseboard with two ASICs, while + 24 ports of each ASICs are connected to one backplane connector + 32 ports of each ASIC are connected to 8 OSFPs +- Integrated 60mm dual-rotor FANs inside L1 node (N+2 redundancy) +- Support 48V or 54V DC input from the external power server. + +Add the structures related to the new systems to allow proper activation +of the all required platform driver. + +Add poweroff callback to support deep power cycle flow, which should +include special actions against CPLD device for performing graceful +operation. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 395 +++++++++++++++++++++++++++- + 1 file changed, 393 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 4bbe1d8f0..a2addd1b3 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -62,12 +63,19 @@ + #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 + #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a + #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b ++#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0x3c ++#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0x3d ++#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0x3e ++#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0x3f + #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 + #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 + #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 + #define MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET 0x43 + #define MLXPLAT_CPLD_LPC_REG_AGGRCX_OFFSET 0x44 + #define MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET 0x45 ++#define MLXPLAT_CPLD_LPC_REG_BRD_OFFSET 0x47 ++#define MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET 0x48 ++#define MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET 0x49 + #define MLXPLAT_CPLD_LPC_REG_GWP_OFFSET 0x4a + #define MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET 0x4b + #define MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET 0x4c +@@ -97,6 +105,9 @@ + #define MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET 0x94 + #define MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET 0x95 + #define MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET 0x96 ++#define MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET 0x97 ++#define MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET 0x98 ++#define MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET 0x99 + #define MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET 0x9a + #define MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET 0x9b + #define MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET 0x9c +@@ -128,6 +139,7 @@ + #define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1 + #define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2 + #define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3 ++#define MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET 0xd9 + #define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde + #define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf + #define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0 +@@ -211,6 +223,7 @@ + MLXPLAT_CPLD_AGGR_MASK_LC_SDWN) + #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 + #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2) ++#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT BIT(4) + #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6) + #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) +@@ -225,6 +238,16 @@ + #define MLXPLAT_CPLD_VOLTREG_UPD_MASK GENMASK(5, 4) + #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) + #define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) ++#define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) ++#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(5) ++#define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) ++#define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4) ++#define MLXPLAT_CPLD_INTRUSION_MASK BIT(6) ++#define MLXPLAT_CPLD_PWM_PG_MASK BIT(7) ++#define MLXPLAT_CPLD_L1_CHA_HEALTH_MASK (MLXPLAT_CPLD_THERMAL1_PDB_MASK | \ ++ MLXPLAT_CPLD_THERMAL2_PDB_MASK | \ ++ MLXPLAT_CPLD_INTRUSION_MASK |\ ++ MLXPLAT_CPLD_PWM_PG_MASK) + #define MLXPLAT_CPLD_I2C_CAP_BIT 0x04 + #define MLXPLAT_CPLD_I2C_CAP_MASK GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT) + +@@ -237,6 +260,8 @@ + /* Masks for aggregation for modular systems */ + #define MLXPLAT_CPLD_LPC_LC_MASK GENMASK(7, 0) + ++#define MLXPLAT_CPLD_HALT_MASK BIT(3) ++ + /* Default I2C parent bus number */ + #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 + +@@ -317,6 +342,8 @@ struct mlxplat_priv { + void *regmap; + }; + ++static struct platform_device *mlxplat_dev; ++ + /* Regions for LPC I2C controller and LPC base register space */ + static const struct resource mlxplat_lpc_resources[] = { + [0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR, +@@ -476,7 +503,7 @@ static struct i2c_mux_reg_platform_data mlxplat_modular_mux_data[] = { + }, + }; + +-/* Platform channels for rack swicth system family */ ++/* Platform channels for rack switch system family */ + static const int mlxplat_rack_switch_channels[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + }; +@@ -2409,6 +2436,156 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = { + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + ++/* Callback performs graceful shutdown after notification about power button event */ ++static int ++mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_kind kind, ++ u8 action) ++{ ++ dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); ++ kernel_halt(); ++ return 0; ++} ++ ++static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_pwr_events_notifier = { ++ .user_handler = mlxplat_mlxcpld_l1_switch_pwr_events_handler, ++}; ++ ++/* Platform hotplug for l1 switch systems family data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_pwr_events_items_data[] = { ++ { ++ .label = "power_button", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, ++ .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_pwr_events_notifier, ++ }, ++}; ++ ++/* Callback activates latch reset flow after notification about intrusion event */ ++static int ++mlxplat_mlxcpld_l1_switch_intrusion_events_handler(void *handle, enum mlxreg_hotplug_kind kind, ++ u8 action) ++{ ++ struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); ++ u32 regval; ++ int err; ++ ++ err = regmap_read(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ®val); ++ if (err) ++ goto fail_regmap_read; ++ ++ if (action) { ++ dev_info(&mlxplat_dev->dev, "Detected intrusion - system latch is opened"); ++ err = regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ regval | MLXPLAT_CPLD_LATCH_RST_MASK); ++ } else { ++ dev_info(&mlxplat_dev->dev, "System latch is properly closed"); ++ err = regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ regval & ~MLXPLAT_CPLD_LATCH_RST_MASK); ++ } ++ ++ if (err) ++ goto fail_regmap_write; ++ ++ return 0; ++ ++fail_regmap_read: ++fail_regmap_write: ++ dev_err(&mlxplat_dev->dev, "Register access failed"); ++ return err; ++} ++ ++static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_intrusion_events_notifier = { ++ .user_handler = mlxplat_mlxcpld_l1_switch_intrusion_events_handler, ++}; ++ ++static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_health_events_items_data[] = { ++ { ++ .label = "thermal1_pdb", ++ .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, ++ .mask = MLXPLAT_CPLD_THERMAL1_PDB_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "thermal2_pdb", ++ .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, ++ .mask = MLXPLAT_CPLD_THERMAL2_PDB_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "intrusion", ++ .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, ++ .mask = MLXPLAT_CPLD_INTRUSION_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_intrusion_events_notifier, ++ }, ++ { ++ .label = "pwm_pg", ++ .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, ++ .mask = MLXPLAT_CPLD_PWM_PG_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = { ++ { ++ .data = mlxplat_mlxcpld_default_ng_fan_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = MLXPLAT_CPLD_FAN_NG_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_erot_ap_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, ++ .mask = MLXPLAT_CPLD_EROT_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_ap_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_erot_error_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, ++ .mask = MLXPLAT_CPLD_EROT_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_error_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_l1_switch_pwr_events_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, ++ .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data), ++ .inversed = 0, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_l1_switch_health_events_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, ++ .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data), ++ .inversed = 0, ++ .health = false, ++ .ind = 8, ++ }, ++}; ++ ++static ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_l1_switch_data = { ++ .items = mlxplat_mlxcpld_l1_switch_events_items, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_events_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, ++ .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, ++ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT, ++}; ++ + static struct spi_board_info rack_switch_switch_spi_board_info[] = { + { + .modalias = "spidev", +@@ -3066,6 +3243,114 @@ static struct mlxreg_core_platform_data mlxplat_qmb8700_led_data = { + .counter = ARRAY_SIZE(mlxplat_mlxcpld_qmb8700_led_data), + }; + ++/* Platform led data for chassis system */ ++static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_led_data[] = { ++ { ++ .label = "status:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ }, ++ { ++ .label = "status:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK ++ }, ++ { ++ .label = "fan1:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(0), ++ }, ++ { ++ .label = "fan1:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(0), ++ }, ++ { ++ .label = "fan2:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(1), ++ }, ++ { ++ .label = "fan2:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(1), ++ }, ++ { ++ .label = "fan3:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(2), ++ }, ++ { ++ .label = "fan3:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(2), ++ }, ++ { ++ .label = "fan4:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(3), ++ }, ++ { ++ .label = "fan4:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(3), ++ }, ++ { ++ .label = "fan5:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(4), ++ }, ++ { ++ .label = "fan5:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(4), ++ }, ++ { ++ .label = "fan6:green", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(5), ++ }, ++ { ++ .label = "fan6:orange", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .bit = BIT(5), ++ }, ++ { ++ .label = "uid:blue", ++ .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, ++ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data mlxplat_l1_switch_led_data = { ++ .data = mlxplat_mlxcpld_l1_switch_led_data, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_led_data), ++}; ++ + /* Platform register access default */ + static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { + { +@@ -3594,12 +3879,48 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(3), + .mode = 0200, + }, ++ { ++ .label = "deep_pwr_cycle", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0200, ++ }, ++ { ++ .label = "latch_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0200, ++ }, + { + .label = "jtag_enable", + .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(4), + .mode = 0644, + }, ++ { ++ .label = "dbg1", ++ .reg = MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0644, ++ }, ++ { ++ .label = "dbg2", ++ .reg = MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0644, ++ }, ++ { ++ .label = "dbg3", ++ .reg = MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0644, ++ }, ++ { ++ .label = "dbg4", ++ .reg = MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0644, ++ }, + { + .label = "asic_health", + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, +@@ -4913,11 +5234,18 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC2_EVENT_OFFSET: +@@ -4932,6 +5260,8 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET: +@@ -4960,6 +5290,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: +@@ -5010,6 +5341,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET: +@@ -5019,6 +5354,9 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_GWP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: +@@ -5040,6 +5378,9 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: +@@ -5076,6 +5417,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: +@@ -5152,6 +5494,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET: +@@ -5161,6 +5507,9 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_GWP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: +@@ -5182,6 +5531,9 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: +@@ -5212,6 +5564,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: +@@ -5407,7 +5760,6 @@ static struct resource mlxplat_mlxcpld_resources[] = { + [0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_CPLD_LPC_SYSIRQ, "mlxreg-hotplug"), + }; + +-static struct platform_device *mlxplat_dev; + static struct mlxreg_core_hotplug_platform_data *mlxplat_i2c; + static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; + static struct mlxreg_core_platform_data *mlxplat_led; +@@ -5418,6 +5770,14 @@ static struct mlxreg_core_platform_data + static const struct regmap_config *mlxplat_regmap_config; + static struct spi_board_info *mlxplat_spi; + ++/* Platform default poweroff function */ ++static void mlxplat_poweroff(void) ++{ ++ struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); ++ ++ regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, MLXPLAT_CPLD_HALT_MASK); ++} ++ + static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) + { + int i; +@@ -5740,6 +6100,29 @@ static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi) + return 1; + } + ++static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi) ++{ ++ int i; ++ ++ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; ++ mlxplat_mux_num = ARRAY_SIZE(mlxplat_rack_switch_mux_data); ++ mlxplat_mux_data = mlxplat_rack_switch_mux_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_l1_switch_data; ++ mlxplat_hotplug->deferred_nr = ++ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; ++ mlxplat_led = &mlxplat_l1_switch_led_data; ++ mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; ++ mlxplat_fan = &mlxplat_default_fan_data; ++ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) ++ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; ++ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; ++ pm_power_off = mlxplat_poweroff; ++ mlxplat_spi = rack_switch_switch_spi_board_info; ++ ++ return 1; ++} ++ + static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + { + .callback = mlxplat_dmi_default_wc_matched, +@@ -5835,6 +6218,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + DMI_MATCH(DMI_BOARD_NAME, "VMOD0015"), + }, + }, ++ { ++ .callback = mlxplat_dmi_l1_switch_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0017"), ++ }, ++ }, + { + .callback = mlxplat_dmi_msn274x_matched, + .matches = { +@@ -6167,6 +6556,8 @@ static void __exit mlxplat_exit(void) + struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); + int i; + ++ if (pm_power_off) ++ pm_power_off = NULL; + for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) + platform_device_unregister(priv->pdev_wd[i]); + if (priv->pdev_fan) +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0183-platform-mellanox-Split-initialization-procedure.patch b/platform/mellanox/non-upstream-patches/patches/0183-platform-mellanox-Split-initialization-procedure.patch new file mode 100644 index 0000000000..deb8591ae1 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0183-platform-mellanox-Split-initialization-procedure.patch @@ -0,0 +1,168 @@ +From 5a2cfa144640a047ab17de5ef12dfefbe7e2f8c3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 11 Dec 2022 10:44:43 +0200 +Subject: [PATCH backport 5.10 2/5] platform: mellanox: Split initialization + procedure + +Split mlxplat_init() into two by adding mlxplat_pre_init(). + +Motivation is to prepare 'mlx-platform' driver to support systems +equipped PCIe based programming logic device. + +Such systems are supposed to use different system resources, thus this +commit separates resources allocation related code. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 78 ++++++++++++++++++++++------- + 1 file changed, 60 insertions(+), 18 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index a2addd1b3..199f22d72 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -330,6 +330,8 @@ + * @pdev_fan - FAN platform devices + * @pdev_wd - array of watchdog platform devices + * @regmap: device register map ++ * @hotplug_resources: system hotplug resources ++ * @hotplug_resources_size: size of system hotplug resources + */ + struct mlxplat_priv { + struct platform_device *pdev_i2c; +@@ -340,6 +342,8 @@ struct mlxplat_priv { + struct platform_device *pdev_fan; + struct platform_device *pdev_wd[MLXPLAT_CPLD_WD_MAX_DEVS]; + void *regmap; ++ struct resource *hotplug_resources; ++ unsigned int hotplug_resources_size; + }; + + static struct platform_device *mlxplat_dev; +@@ -6365,20 +6369,63 @@ static int mlxplat_mlxcpld_check_wd_capability(void *regmap) + return 0; + } + ++static int mlxplat_lpc_cpld_device_init(struct resource **hotplug_resources, ++ unsigned int *hotplug_resources_size) ++{ ++ int err; ++ ++ mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, PLATFORM_DEVID_NONE, ++ mlxplat_lpc_resources, ++ ARRAY_SIZE(mlxplat_lpc_resources)); ++ if (IS_ERR(mlxplat_dev)) ++ return PTR_ERR(mlxplat_dev); ++ ++ mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev, ++ mlxplat_lpc_resources[1].start, 1); ++ if (!mlxplat_mlxcpld_regmap_ctx.base) { ++ err = -ENOMEM; ++ goto fail_devm_ioport_map; ++ } ++ ++ *hotplug_resources = mlxplat_mlxcpld_resources; ++ *hotplug_resources_size = ARRAY_SIZE(mlxplat_mlxcpld_resources); ++ ++ return 0; ++ ++fail_devm_ioport_map: ++ platform_device_unregister(mlxplat_dev); ++ return err; ++} ++ ++static void mlxplat_lpc_cpld_device_exit(void) ++{ ++ platform_device_unregister(mlxplat_dev); ++} ++ ++static int ++mlxplat_pre_init(struct resource **hotplug_resources, unsigned int *hotplug_resources_size) ++{ ++ return mlxplat_lpc_cpld_device_init(hotplug_resources, hotplug_resources_size); ++} ++ ++static void mlxplat_post_exit(void) ++{ ++ mlxplat_lpc_cpld_device_exit(); ++} ++ + static int __init mlxplat_init(void) + { ++ unsigned int hotplug_resources_size; ++ struct resource *hotplug_resources; + struct mlxplat_priv *priv; + int i, j, nr, err; + + if (!dmi_check_system(mlxplat_dmi_table)) + return -ENODEV; + +- mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1, +- mlxplat_lpc_resources, +- ARRAY_SIZE(mlxplat_lpc_resources)); +- +- if (IS_ERR(mlxplat_dev)) +- return PTR_ERR(mlxplat_dev); ++ err = mlxplat_pre_init(&hotplug_resources, &hotplug_resources_size); ++ if (err) ++ return err; + + priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv), + GFP_KERNEL); +@@ -6388,12 +6435,8 @@ static int __init mlxplat_init(void) + } + platform_set_drvdata(mlxplat_dev, priv); + +- mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev, +- mlxplat_lpc_resources[1].start, 1); +- if (!mlxplat_mlxcpld_regmap_ctx.base) { +- err = -ENOMEM; +- goto fail_alloc; +- } ++ priv->hotplug_resources = hotplug_resources; ++ priv->hotplug_resources_size = hotplug_resources_size; + + if (!mlxplat_regmap_config) + mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config; +@@ -6414,8 +6457,8 @@ static int __init mlxplat_init(void) + if (mlxplat_i2c) + mlxplat_i2c->regmap = priv->regmap; + priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld", +- nr, mlxplat_mlxcpld_resources, +- ARRAY_SIZE(mlxplat_mlxcpld_resources), ++ nr, priv->hotplug_resources, ++ priv->hotplug_resources_size, + mlxplat_i2c, sizeof(*mlxplat_i2c)); + if (IS_ERR(priv->pdev_i2c)) { + err = PTR_ERR(priv->pdev_i2c); +@@ -6439,8 +6482,8 @@ static int __init mlxplat_init(void) + priv->pdev_hotplug = + platform_device_register_resndata(&mlxplat_dev->dev, + "mlxreg-hotplug", PLATFORM_DEVID_NONE, +- mlxplat_mlxcpld_resources, +- ARRAY_SIZE(mlxplat_mlxcpld_resources), ++ priv->hotplug_resources, ++ priv->hotplug_resources_size, + mlxplat_hotplug, sizeof(*mlxplat_hotplug)); + if (IS_ERR(priv->pdev_hotplug)) { + err = PTR_ERR(priv->pdev_hotplug); +@@ -6545,7 +6588,6 @@ static int __init mlxplat_init(void) + platform_device_unregister(priv->pdev_mux[i]); + platform_device_unregister(priv->pdev_i2c); + fail_alloc: +- platform_device_unregister(mlxplat_dev); + + return err; + } +@@ -6573,7 +6615,7 @@ static void __exit mlxplat_exit(void) + platform_device_unregister(priv->pdev_mux[i]); + + platform_device_unregister(priv->pdev_i2c); +- platform_device_unregister(mlxplat_dev); ++ mlxplat_post_exit(); + } + module_exit(mlxplat_exit); + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0184-platform-mellanox-Split-logic-in-init-and-exit-flow.patch b/platform/mellanox/non-upstream-patches/patches/0184-platform-mellanox-Split-logic-in-init-and-exit-flow.patch new file mode 100644 index 0000000000..3810a2dc03 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0184-platform-mellanox-Split-logic-in-init-and-exit-flow.patch @@ -0,0 +1,455 @@ +From f00081a6e0b7af5a0b85db3121afe3cc6a62f9e7 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 11 Dec 2022 11:08:07 +0200 +Subject: [PATCH backport 5.10 072/150] platform: mellanox: Split logic in init + and exit flow + +Split logic in mlxplat_init()/mlxplat_exit() routines. +Separate initialization of I2C infrastructure and others platform +drivers. + +Motivation is to provide synchronization between I2C bus and mux +drivers and other drivers using this infrastructure. +I2C main bus and MUX busses are implemented in FPGA logic. On some new +systems the numbers allocated for these busses could be variable +depending on order of initialization of I2C native busses. Since bus +numbers are passed to some other platform drivers during initialization +flow, it is necessary to synchronize completion of I2C infrastructure +drivers and activation of rest of drivers. + +Thus initialization flow will be performed in synchronized order. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 313 ++++++++++++++++++---------- + 1 file changed, 204 insertions(+), 109 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 199f22d72..05a630135 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -321,6 +321,9 @@ + /* Default value for PWM control register for rack switch system */ + #define MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT 0xf4 + ++#define MLXPLAT_I2C_MAIN_BUS_NOTIFIED 0x01 ++#define MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED 0x02 ++ + /* mlxplat_priv - platform private data + * @pdev_i2c - i2c controller platform device + * @pdev_mux - array of mux platform devices +@@ -332,6 +335,7 @@ + * @regmap: device register map + * @hotplug_resources: system hotplug resources + * @hotplug_resources_size: size of system hotplug resources ++ * @hi2c_main_init_status: init status of I2C main bus + */ + struct mlxplat_priv { + struct platform_device *pdev_i2c; +@@ -344,9 +348,11 @@ struct mlxplat_priv { + void *regmap; + struct resource *hotplug_resources; + unsigned int hotplug_resources_size; ++ u8 i2c_main_init_status; + }; + + static struct platform_device *mlxplat_dev; ++static int mlxplat_i2c_main_complition_notify(void *handle, int id); + + /* Regions for LPC I2C controller and LPC base register space */ + static const struct resource mlxplat_lpc_resources[] = { +@@ -381,6 +387,7 @@ static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_ng_data = { + .mask = MLXPLAT_CPLD_AGGR_MASK_COMEX, + .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET, + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_I2C, ++ .completion_notify = mlxplat_i2c_main_complition_notify, + }; + + /* Platform default channels */ +@@ -6413,68 +6420,9 @@ static void mlxplat_post_exit(void) + mlxplat_lpc_cpld_device_exit(); + } + +-static int __init mlxplat_init(void) ++static int mlxplat_post_init(struct mlxplat_priv *priv) + { +- unsigned int hotplug_resources_size; +- struct resource *hotplug_resources; +- struct mlxplat_priv *priv; +- int i, j, nr, err; +- +- if (!dmi_check_system(mlxplat_dmi_table)) +- return -ENODEV; +- +- err = mlxplat_pre_init(&hotplug_resources, &hotplug_resources_size); +- if (err) +- return err; +- +- priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv), +- GFP_KERNEL); +- if (!priv) { +- err = -ENOMEM; +- goto fail_alloc; +- } +- platform_set_drvdata(mlxplat_dev, priv); +- +- priv->hotplug_resources = hotplug_resources; +- priv->hotplug_resources_size = hotplug_resources_size; +- +- if (!mlxplat_regmap_config) +- mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config; +- +- priv->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL, +- &mlxplat_mlxcpld_regmap_ctx, +- mlxplat_regmap_config); +- if (IS_ERR(priv->regmap)) { +- err = PTR_ERR(priv->regmap); +- goto fail_alloc; +- } +- +- err = mlxplat_mlxcpld_verify_bus_topology(&nr); +- if (nr < 0) +- goto fail_alloc; +- +- nr = (nr == mlxplat_max_adap_num) ? -1 : nr; +- if (mlxplat_i2c) +- mlxplat_i2c->regmap = priv->regmap; +- priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld", +- nr, priv->hotplug_resources, +- priv->hotplug_resources_size, +- mlxplat_i2c, sizeof(*mlxplat_i2c)); +- if (IS_ERR(priv->pdev_i2c)) { +- err = PTR_ERR(priv->pdev_i2c); +- goto fail_alloc; +- } +- +- for (i = 0; i < mlxplat_mux_num; i++) { +- priv->pdev_mux[i] = platform_device_register_resndata(&priv->pdev_i2c->dev, +- "i2c-mux-reg", i, NULL, 0, +- &mlxplat_mux_data[i], +- sizeof(mlxplat_mux_data[i])); +- if (IS_ERR(priv->pdev_mux[i])) { +- err = PTR_ERR(priv->pdev_mux[i]); +- goto fail_platform_mux_register; +- } +- } ++ int i = 0, err; + + /* Add hotplug driver */ + if (mlxplat_hotplug) { +@@ -6487,19 +6435,10 @@ static int __init mlxplat_init(void) + mlxplat_hotplug, sizeof(*mlxplat_hotplug)); + if (IS_ERR(priv->pdev_hotplug)) { + err = PTR_ERR(priv->pdev_hotplug); +- goto fail_platform_mux_register; ++ goto fail_platform_hotplug_register; + } + } + +- /* Set default registers. */ +- for (j = 0; j < mlxplat_regmap_config->num_reg_defaults; j++) { +- err = regmap_write(priv->regmap, +- mlxplat_regmap_config->reg_defaults[j].reg, +- mlxplat_regmap_config->reg_defaults[j].def); +- if (err) +- goto fail_platform_mux_register; +- } +- + /* Add LED driver. */ + if (mlxplat_led) { + mlxplat_led->regmap = priv->regmap; +@@ -6509,7 +6448,7 @@ static int __init mlxplat_init(void) + sizeof(*mlxplat_led)); + if (IS_ERR(priv->pdev_led)) { + err = PTR_ERR(priv->pdev_led); +- goto fail_platform_hotplug_register; ++ goto fail_platform_leds_register; + } + } + +@@ -6523,7 +6462,7 @@ static int __init mlxplat_init(void) + sizeof(*mlxplat_regs_io)); + if (IS_ERR(priv->pdev_io_regs)) { + err = PTR_ERR(priv->pdev_io_regs); +- goto fail_platform_led_register; ++ goto fail_platform_io_register; + } + } + +@@ -6536,7 +6475,7 @@ static int __init mlxplat_init(void) + sizeof(*mlxplat_fan)); + if (IS_ERR(priv->pdev_fan)) { + err = PTR_ERR(priv->pdev_fan); +- goto fail_platform_io_regs_register; ++ goto fail_platform_fan_register; + } + } + +@@ -6547,59 +6486,42 @@ static int __init mlxplat_init(void) + err = mlxplat_mlxcpld_check_wd_capability(priv->regmap); + if (err) + goto fail_platform_wd_register; +- for (j = 0; j < MLXPLAT_CPLD_WD_MAX_DEVS; j++) { +- if (mlxplat_wd_data[j]) { +- mlxplat_wd_data[j]->regmap = priv->regmap; +- priv->pdev_wd[j] = +- platform_device_register_resndata(&mlxplat_dev->dev, "mlx-wdt", j, +- NULL, 0, mlxplat_wd_data[j], +- sizeof(*mlxplat_wd_data[j])); +- if (IS_ERR(priv->pdev_wd[j])) { +- err = PTR_ERR(priv->pdev_wd[j]); ++ for (i = 0; i < MLXPLAT_CPLD_WD_MAX_DEVS; i++) { ++ if (mlxplat_wd_data[i]) { ++ mlxplat_wd_data[i]->regmap = priv->regmap; ++ priv->pdev_wd[i] = ++ platform_device_register_resndata(&mlxplat_dev->dev, "mlx-wdt", i, ++ NULL, 0, mlxplat_wd_data[i], ++ sizeof(*mlxplat_wd_data[i])); ++ if (IS_ERR(priv->pdev_wd[i])) { ++ err = PTR_ERR(priv->pdev_wd[i]); + goto fail_platform_wd_register; + } + } + } + +- /* Sync registers with hardware. */ +- regcache_mark_dirty(priv->regmap); +- err = regcache_sync(priv->regmap); +- if (err) +- goto fail_platform_wd_register; +- + return 0; + + fail_platform_wd_register: +- while (--j >= 0) +- platform_device_unregister(priv->pdev_wd[j]); +- if (mlxplat_fan) +- platform_device_unregister(priv->pdev_fan); +-fail_platform_io_regs_register: ++ while (--i >= 0) ++ platform_device_unregister(priv->pdev_wd[i]); ++fail_platform_fan_register: + if (mlxplat_regs_io) + platform_device_unregister(priv->pdev_io_regs); +-fail_platform_led_register: ++fail_platform_io_register: + if (mlxplat_led) + platform_device_unregister(priv->pdev_led); +-fail_platform_hotplug_register: ++fail_platform_leds_register: + if (mlxplat_hotplug) + platform_device_unregister(priv->pdev_hotplug); +-fail_platform_mux_register: +- while (--i >= 0) +- platform_device_unregister(priv->pdev_mux[i]); +- platform_device_unregister(priv->pdev_i2c); +-fail_alloc: +- ++fail_platform_hotplug_register: + return err; + } +-module_init(mlxplat_init); + +-static void __exit mlxplat_exit(void) ++static void mlxplat_pre_exit(struct mlxplat_priv *priv) + { +- struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); + int i; + +- if (pm_power_off) +- pm_power_off = NULL; + for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) + platform_device_unregister(priv->pdev_wd[i]); + if (priv->pdev_fan) +@@ -6610,13 +6532,186 @@ static void __exit mlxplat_exit(void) + platform_device_unregister(priv->pdev_led); + if (priv->pdev_hotplug) + platform_device_unregister(priv->pdev_hotplug); ++} ++ ++static int ++mlxplat_i2c_mux_complition_notify(void *handle, struct i2c_adapter *parent, ++ struct i2c_adapter *adapters[]) ++{ ++ struct mlxplat_priv *priv = handle; ++ ++ return mlxplat_post_init(priv); ++} + +- for (i = mlxplat_mux_num - 1; i >= 0 ; i--) ++static int mlxplat_i2c_mux_topolgy_init(struct mlxplat_priv *priv) ++{ ++ int i, err; ++ ++ if (!priv->pdev_i2c) { ++ priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_NOTIFIED; ++ return 0; ++ } ++ ++ priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED; ++ for (i = 0; i < mlxplat_mux_num; i++) { ++ priv->pdev_mux[i] = platform_device_register_resndata(&priv->pdev_i2c->dev, ++ "i2c-mux-reg", i, NULL, 0, ++ &mlxplat_mux_data[i], ++ sizeof(mlxplat_mux_data[i])); ++ if (IS_ERR(priv->pdev_mux[i])) { ++ err = PTR_ERR(priv->pdev_mux[i]); ++ goto fail_platform_mux_register; ++ } ++ } ++ ++ return mlxplat_i2c_mux_complition_notify(priv, NULL, NULL); ++ ++fail_platform_mux_register: ++ while (--i >= 0) + platform_device_unregister(priv->pdev_mux[i]); ++ return err; ++} ++ ++static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv) ++{ ++ int i; ++ ++ for (i = mlxplat_mux_num - 1; i >= 0 ; i--) { ++ if (priv->pdev_mux[i]) ++ platform_device_unregister(priv->pdev_mux[i]); ++ } + +- platform_device_unregister(priv->pdev_i2c); + mlxplat_post_exit(); + } ++ ++static int mlxplat_i2c_main_complition_notify(void *handle, int id) ++{ ++ struct mlxplat_priv *priv = handle; ++ ++ return mlxplat_i2c_mux_topolgy_init(priv); ++} ++ ++static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) ++{ ++ int nr, err; ++ ++ if (!mlxplat_i2c) ++ return 0; ++ ++ err = mlxplat_mlxcpld_verify_bus_topology(&nr); ++ if (nr < 0) ++ goto fail_mlxplat_mlxcpld_verify_bus_topology; ++ ++ nr = (nr == mlxplat_max_adap_num) ? -1 : nr; ++ mlxplat_i2c->regmap = priv->regmap; ++ mlxplat_i2c->handle = priv; ++ ++ priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld", ++ nr, priv->hotplug_resources, ++ priv->hotplug_resources_size, ++ mlxplat_i2c, sizeof(*mlxplat_i2c)); ++ if (IS_ERR(priv->pdev_i2c)) { ++ err = PTR_ERR(priv->pdev_i2c); ++ goto fail_platform_i2c_register; ++ } ++ ++ if (priv->i2c_main_init_status == MLXPLAT_I2C_MAIN_BUS_NOTIFIED) { ++ err = mlxplat_i2c_mux_topolgy_init(priv); ++ if (err) ++ goto fail_mlxplat_i2c_mux_topolgy_init; ++ } ++ ++ return 0; ++ ++fail_mlxplat_i2c_mux_topolgy_init: ++fail_platform_i2c_register: ++fail_mlxplat_mlxcpld_verify_bus_topology: ++ return err; ++} ++ ++static void mlxplat_i2c_main_exit(struct mlxplat_priv *priv) ++{ ++ mlxplat_i2c_mux_topolgy_exit(priv); ++ if (priv->pdev_i2c) ++ platform_device_unregister(priv->pdev_i2c); ++} ++ ++static int __init mlxplat_init(void) ++{ ++ unsigned int hotplug_resources_size; ++ struct resource *hotplug_resources; ++ struct mlxplat_priv *priv; ++ int i, err; ++ ++ if (!dmi_check_system(mlxplat_dmi_table)) ++ return -ENODEV; ++ ++ err = mlxplat_pre_init(&hotplug_resources, &hotplug_resources_size); ++ if (err) ++ return err; ++ ++ priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv), ++ GFP_KERNEL); ++ if (!priv) { ++ err = -ENOMEM; ++ goto fail_alloc; ++ } ++ platform_set_drvdata(mlxplat_dev, priv); ++ priv->hotplug_resources = hotplug_resources; ++ priv->hotplug_resources_size = hotplug_resources_size; ++ ++ if (!mlxplat_regmap_config) ++ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config; ++ ++ priv->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL, ++ &mlxplat_mlxcpld_regmap_ctx, ++ mlxplat_regmap_config); ++ if (IS_ERR(priv->regmap)) { ++ err = PTR_ERR(priv->regmap); ++ goto fail_alloc; ++ } ++ ++ /* Set default registers. */ ++ for (i = 0; i < mlxplat_regmap_config->num_reg_defaults; i++) { ++ err = regmap_write(priv->regmap, ++ mlxplat_regmap_config->reg_defaults[i].reg, ++ mlxplat_regmap_config->reg_defaults[i].def); ++ if (err) ++ goto fail_regmap_write; ++ } ++ ++ err = mlxplat_i2c_main_init(priv); ++ if (err) ++ goto fail_mlxplat_i2c_main_init; ++ ++ /* Sync registers with hardware. */ ++ regcache_mark_dirty(priv->regmap); ++ err = regcache_sync(priv->regmap); ++ if (err) ++ goto fail_regcache_sync; ++ ++ return 0; ++ ++fail_regcache_sync: ++ mlxplat_pre_exit(priv); ++fail_mlxplat_i2c_main_init: ++fail_regmap_write: ++fail_alloc: ++ mlxplat_post_exit(); ++ ++ return err; ++} ++module_init(mlxplat_init); ++ ++static void __exit mlxplat_exit(void) ++{ ++ struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); ++ ++ if (pm_power_off) ++ pm_power_off = NULL; ++ mlxplat_pre_exit(priv); ++ mlxplat_i2c_main_exit(priv); ++} + module_exit(mlxplat_exit); + + MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0185-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch b/platform/mellanox/non-upstream-patches/patches/0185-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch new file mode 100644 index 0000000000..6209d60352 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0185-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch @@ -0,0 +1,81 @@ +From 3a61ad447e2ec437079c86c277b80acde19e9173 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 26 Dec 2022 22:28:33 +0200 +Subject: [PATCH backport 5.10 073/150] platform: mellanox: Extend all systems + with I2C notification callback + +Motivation is to provide synchronization between I2C main bus and other +platform drivers using this notification callback. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 05a630135..1ef0bb975 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -365,6 +365,11 @@ static const struct resource mlxplat_lpc_resources[] = { + IORESOURCE_IO), + }; + ++/* Platform systems default i2c data */ ++static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_default_data = { ++ .completion_notify = mlxplat_i2c_main_complition_notify, ++}; ++ + /* Platform i2c next generation systems data */ + static struct mlxreg_core_data mlxplat_mlxcpld_i2c_ng_items_data[] = { + { +@@ -5807,6 +5812,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) + mlxplat_led = &mlxplat_default_led_data; + mlxplat_regs_io = &mlxplat_default_regs_io_data; + mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; + + return 1; + } +@@ -5829,6 +5835,7 @@ static int __init mlxplat_dmi_default_wc_matched(const struct dmi_system_id *dmi + mlxplat_led = &mlxplat_default_led_wc_data; + mlxplat_regs_io = &mlxplat_default_regs_io_data; + mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; + + return 1; + } +@@ -5876,6 +5883,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) + mlxplat_led = &mlxplat_msn21xx_led_data; + mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; + mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; + + return 1; + } +@@ -5898,6 +5906,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) + mlxplat_led = &mlxplat_default_led_data; + mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; + mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; + + return 1; + } +@@ -5920,6 +5929,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) + mlxplat_led = &mlxplat_msn21xx_led_data; + mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; + mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; + + return 1; + } +@@ -5969,6 +5979,7 @@ static int __init mlxplat_dmi_comex_matched(const struct dmi_system_id *dmi) + mlxplat_fan = &mlxplat_default_fan_data; + for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) + mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; + mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_comex; + + return 1; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0187-platform_data-mlxreg-Add-field-with-mapped-resource-.patch b/platform/mellanox/non-upstream-patches/patches/0187-platform_data-mlxreg-Add-field-with-mapped-resource-.patch new file mode 100644 index 0000000000..2677a484f7 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0187-platform_data-mlxreg-Add-field-with-mapped-resource-.patch @@ -0,0 +1,37 @@ +From e1d1afba7f7285bebb2d30fce961901ee944d201 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 9 Nov 2022 09:43:28 +0200 +Subject: [PATCH backport 5.10 01/10] platform_data/mlxreg: Add field with + mapped resource address + +Add field with PCIe remapped based address for passing it across +relevant platform drivers sharing common system resources. + +Signed-off-by: Vadim Pasternak +--- + include/linux/platform_data/mlxreg.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h +index a6bd74e29..0b9f81a6f 100644 +--- a/include/linux/platform_data/mlxreg.h ++++ b/include/linux/platform_data/mlxreg.h +@@ -216,6 +216,7 @@ struct mlxreg_core_platform_data { + * @mask_low: low aggregation interrupt common mask; + * @deferred_nr: I2C adapter number must be exist prior probing execution; + * @shift_nr: I2C adapter numbers must be incremented by this value; ++ * @addr: mapped resource address; + * @handle: handle to be passed by callback; + * @completion_notify: callback to notify when platform driver probing is done; + */ +@@ -230,6 +231,7 @@ struct mlxreg_core_hotplug_platform_data { + u32 mask_low; + int deferred_nr; + int shift_nr; ++ void __iomem *addr; + void *handle; + int (*completion_notify)(void *handle, int id); + }; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0188-i2c-mux-Add-register-map-based-mux-driver.patch b/platform/mellanox/non-upstream-patches/patches/0188-i2c-mux-Add-register-map-based-mux-driver.patch new file mode 100644 index 0000000000..7912bf1873 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0188-i2c-mux-Add-register-map-based-mux-driver.patch @@ -0,0 +1,253 @@ +From 03195e7418ec41d0a118973a392165f11ba881cf Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 9 Nov 2022 12:22:12 +0200 +Subject: [PATCH backport 5.10 026/100] i2c: mux: Add register map based mux + driver + +Add 'regmap' mux driver to allow virtual bus switching by setting a +single selector register. +The 'regmap' is supposed to be passed to driver within a platform data +by parent platform driver. + +Motivation is to support indirect access to register space where +selector register is located. +For example, Lattice FPGA LFD2NX-40 device, being connected through +PCIe bus provides SPI or LPC bus logic through PCIe-to-SPI or +PCIe-to-LPC bridging. Thus, FPGA operates a as host controller and +some slave devices can be connected to it. For example: +- CPU (PCIe) -> FPGA (PCIe-to-SPI bridge) -> CPLD or another FPGA. +- CPU (PCIe) -> FPGA (PCIe-to-LPC bridge) -> CPLD or another FPGA. +Where 1-st FPGA connected to PCIe is located on carrier board, while +2-nd programming logic device is located on some switch board and +cannot be connected to CPU PCIe root complex. + +In case mux selector register is located within the 2-nd device, SPI or +LPC transactions are sent indirectly through pre-defined protocol. + +To support such protocol reg_read()/reg_write() callbacks are provided +to 'regmap' object and these callback implements required indirect +access. + +For example, flow in reg_write() will be as following: +- Verify there is no pending transactions. +- Set address in PCIe register space. +- Set data to be written in PCIe register space. +- Activate write operation in PCIe register space. +- LPC or SPI write transaction is performed. + +Signed-off-by: Vadim Pasternak +--- + drivers/i2c/muxes/Kconfig | 12 ++ + drivers/i2c/muxes/Makefile | 1 + + drivers/i2c/muxes/i2c-mux-regmap.c | 123 +++++++++++++++++++ + include/linux/platform_data/i2c-mux-regmap.h | 34 +++++ + 4 files changed, 170 insertions(+) + create mode 100644 drivers/i2c/muxes/i2c-mux-regmap.c + create mode 100644 include/linux/platform_data/i2c-mux-regmap.h + +diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig +index 1708b1a82..48becd945 100644 +--- a/drivers/i2c/muxes/Kconfig ++++ b/drivers/i2c/muxes/Kconfig +@@ -99,6 +99,18 @@ config I2C_MUX_REG + This driver can also be built as a module. If so, the module + will be called i2c-mux-reg. + ++config I2C_MUX_REGMAP ++ tristate "Register map based I2C multiplexer" ++ depends on REGMAP ++ help ++ If you say yes to this option, support will be included for a ++ register map based I2C multiplexer. This driver provides access to ++ I2C busses connected through a MUX, which is controlled ++ by a single register through the regmap. ++ ++ This driver can also be built as a module. If so, the module ++ will be called i2c-mux-regmap. ++ + config I2C_DEMUX_PINCTRL + tristate "pinctrl-based I2C demultiplexer" + depends on PINCTRL && OF +diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile +index 6d9d865e8..092dca428 100644 +--- a/drivers/i2c/muxes/Makefile ++++ b/drivers/i2c/muxes/Makefile +@@ -14,5 +14,6 @@ obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o + obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o + obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o + obj-$(CONFIG_I2C_MUX_REG) += i2c-mux-reg.o ++obj-$(CONFIG_I2C_MUX_REGMAP) += i2c-mux-regmap.o + + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/muxes/i2c-mux-regmap.c b/drivers/i2c/muxes/i2c-mux-regmap.c +new file mode 100644 +index 000000000..e155c039a +--- /dev/null ++++ b/drivers/i2c/muxes/i2c-mux-regmap.c +@@ -0,0 +1,123 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 ++/* ++ * Regmap i2c mux driver ++ * ++ * Copyright (C) 2023 Nvidia Technologies Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* i2c_mux_regmap - mux control structure: ++ * @last_val - last selected register value or -1 if mux deselected; ++ * @pdata: platform data; ++ */ ++struct i2c_mux_regmap { ++ int last_val; ++ struct i2c_mux_regmap_platform_data pdata; ++}; ++ ++static int i2c_mux_regmap_select_chan(struct i2c_mux_core *muxc, u32 chan) ++{ ++ struct i2c_mux_regmap *mux = i2c_mux_priv(muxc); ++ int err = 0; ++ ++ /* Only select the channel if its different from the last channel */ ++ if (mux->last_val != chan) { ++ err = regmap_write(mux->pdata.regmap, mux->pdata.sel_reg_addr, chan); ++ mux->last_val = err < 0 ? -1 : chan; ++ } ++ ++ return err; ++} ++ ++static int i2c_mux_regmap_deselect(struct i2c_mux_core *muxc, u32 chan) ++{ ++ struct i2c_mux_regmap *mux = i2c_mux_priv(muxc); ++ ++ /* Deselect active channel */ ++ mux->last_val = -1; ++ ++ return regmap_write(mux->pdata.regmap, mux->pdata.sel_reg_addr, 0); ++} ++ ++/* Probe/reomove functions */ ++static int i2c_mux_regmap_probe(struct platform_device *pdev) ++{ ++ struct i2c_mux_regmap_platform_data *pdata = dev_get_platdata(&pdev->dev); ++ struct i2c_mux_regmap *mux; ++ struct i2c_adapter *parent; ++ struct i2c_mux_core *muxc; ++ int num, err; ++ ++ if (!pdata) ++ return -EINVAL; ++ ++ mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); ++ if (!mux) ++ return -ENOMEM; ++ ++ memcpy(&mux->pdata, pdata, sizeof(*pdata)); ++ parent = i2c_get_adapter(mux->pdata.parent); ++ if (!parent) ++ return -EPROBE_DEFER; ++ ++ muxc = i2c_mux_alloc(parent, &pdev->dev, pdata->num_adaps, sizeof(*mux), 0, ++ i2c_mux_regmap_select_chan, i2c_mux_regmap_deselect); ++ if (!muxc) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, muxc); ++ muxc->priv = mux; ++ mux->last_val = -1; /* force the first selection */ ++ ++ /* Create an adapter for each channel. */ ++ for (num = 0; num < pdata->num_adaps; num++) { ++ err = i2c_mux_add_adapter(muxc, 0, pdata->chan_ids[num], 0); ++ if (err) ++ goto err_i2c_mux_add_adapter; ++ } ++ ++ /* Notify caller when all channels' adapters are created. */ ++ if (pdata->completion_notify) ++ pdata->completion_notify(pdata->handle, muxc->parent, muxc->adapter); ++ ++ return 0; ++ ++err_i2c_mux_add_adapter: ++ i2c_mux_del_adapters(muxc); ++ return err; ++} ++ ++static int i2c_mux_regmap_remove(struct platform_device *pdev) ++{ ++ struct i2c_mux_core *muxc = platform_get_drvdata(pdev); ++ ++ i2c_mux_del_adapters(muxc); ++ i2c_put_adapter(muxc->parent); ++ ++ return 0; ++} ++ ++static struct platform_driver i2c_mux_regmap_driver = { ++ .driver = { ++ .name = "i2c-mux-regmap", ++ }, ++ .probe = i2c_mux_regmap_probe, ++ .remove = i2c_mux_regmap_remove, ++}; ++ ++module_platform_driver(i2c_mux_regmap_driver); ++ ++MODULE_AUTHOR("Vadim Pasternak (vadimp@nvidia.com)"); ++MODULE_DESCRIPTION("Regmap I2C multiplexer driver"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_ALIAS("platform:i2c-mux-regmap"); +diff --git a/include/linux/platform_data/i2c-mux-regmap.h b/include/linux/platform_data/i2c-mux-regmap.h +new file mode 100644 +index 000000000..a06614e5e +--- /dev/null ++++ b/include/linux/platform_data/i2c-mux-regmap.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ ++/* ++ * Regmap i2c mux driver ++ * ++ * Copyright (C) 2023 Nvidia Technologies Ltd. ++ */ ++ ++#ifndef __LINUX_PLATFORM_DATA_I2C_MUX_REGMAP_H ++#define __LINUX_PLATFORM_DATA_I2C_MUX_REGMAP_H ++ ++/** ++ * struct i2c_mux_regmap_platform_data - Platform-dependent data for i2c-mux-regmap ++ * @regmap: register map of parent device; ++ * @parent: Parent I2C bus adapter number ++ * @chan_ids - channels array ++ * @num_adaps - number of adapters ++ * @sel_reg_addr - mux select register offset in CPLD space ++ * @reg_size: register size in bytes ++ * @handle: handle to be passed by callback ++ * @completion_notify: callback to notify when all the adapters are created ++ */ ++struct i2c_mux_regmap_platform_data { ++ void *regmap; ++ int parent; ++ const unsigned int *chan_ids; ++ int num_adaps; ++ int sel_reg_addr; ++ u8 reg_size; ++ void *handle; ++ int (*completion_notify)(void *handle, struct i2c_adapter *parent, ++ struct i2c_adapter *adapters[]); ++}; ++ ++#endif /* __LINUX_PLATFORM_DATA_I2C_MUX_REGMAP_H */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0189-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch b/platform/mellanox/non-upstream-patches/patches/0189-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch new file mode 100644 index 0000000000..b5c0e006e3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0189-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch @@ -0,0 +1,29 @@ +From c4d1a7d7f51a8315f727c9210961ed93b922d440 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 7 Nov 2022 12:00:37 +0200 +Subject: [PATCH backport 5.10 03/10] i2c: mlxcpld: Allow driver to run on + ARM64 architecture + +Extend driver dependency by ARM64 architecture. + +Signed-off-by: Vadim Pasternak +--- + drivers/i2c/busses/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 7e693dcbd..c984305ee 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -1328,7 +1328,7 @@ config I2C_ICY + + config I2C_MLXCPLD + tristate "Mellanox I2C driver" +- depends on X86_64 || COMPILE_TEST ++ depends on X86_64 || ARM64 || COMPILE_TEST + help + This exposes the Mellanox platform I2C busses to the linux I2C layer + for X86 based systems. +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0190-i2c-mlxcpld-Modify-base-address-type.patch b/platform/mellanox/non-upstream-patches/patches/0190-i2c-mlxcpld-Modify-base-address-type.patch new file mode 100644 index 0000000000..36c3178e6c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0190-i2c-mlxcpld-Modify-base-address-type.patch @@ -0,0 +1,49 @@ +From d2130ff4d3aed72611f07213e9eceeb084f0fc65 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 9 Nov 2022 10:29:22 +0200 +Subject: [PATCH backport 5.10 04/10] i2c: mlxcpld: Modify base address type + +Change type of base address from 'u32' to 'u64'. + +Motivation is to support memory mapped virtual base address on ARM64 +architecture. + +Signed-off-by: Vadim Pasternak +--- + drivers/i2c/busses/i2c-mlxcpld.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c +index 72fcfb17d..57aea396c 100644 +--- a/drivers/i2c/busses/i2c-mlxcpld.c ++++ b/drivers/i2c/busses/i2c-mlxcpld.c +@@ -68,7 +68,7 @@ struct mlxcpld_i2c_curr_xfer { + + struct mlxcpld_i2c_priv { + struct i2c_adapter adap; +- u32 base_addr; ++ u64 base_addr; + struct mutex lock; + struct mlxcpld_i2c_curr_xfer xfer; + struct device *dev; +@@ -99,7 +99,7 @@ static void mlxcpld_i2c_lpc_read_buf(u8 *data, u8 len, u32 addr) + static void mlxcpld_i2c_read_comm(struct mlxcpld_i2c_priv *priv, u8 offs, + u8 *data, u8 datalen) + { +- u32 addr = priv->base_addr + offs; ++ u64 addr = priv->base_addr + offs; + + switch (datalen) { + case 1: +@@ -124,7 +124,7 @@ static void mlxcpld_i2c_read_comm(struct mlxcpld_i2c_priv *priv, u8 offs, + static void mlxcpld_i2c_write_comm(struct mlxcpld_i2c_priv *priv, u8 offs, + u8 *data, u8 datalen) + { +- u32 addr = priv->base_addr + offs; ++ u64 addr = priv->base_addr + offs; + + switch (datalen) { + case 1: +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0191-i2c-mlxcpld-Allow-to-configure-base-address-of-regis.patch b/platform/mellanox/non-upstream-patches/patches/0191-i2c-mlxcpld-Allow-to-configure-base-address-of-regis.patch new file mode 100644 index 0000000000..245bcaa4f1 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0191-i2c-mlxcpld-Allow-to-configure-base-address-of-regis.patch @@ -0,0 +1,34 @@ +From 0fcfc9b2eb7f071f3aa64845d262f1e8e4f741e7 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 9 Nov 2022 10:35:58 +0200 +Subject: [PATCH backport 5.10 05/10] i2c: mlxcpld: Allow to configure base + address of register space + +Allow to use configured base address. + +Currently driver uses constant base address of register space. +On new systems this base address could be different, thus it could be +passed to the driver through platform data. + +Signed-off-by: Vadim Pasternak +--- + drivers/i2c/busses/i2c-mlxcpld.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c +index 57aea396c..cd5401ce4 100644 +--- a/drivers/i2c/busses/i2c-mlxcpld.c ++++ b/drivers/i2c/busses/i2c-mlxcpld.c +@@ -538,6 +538,9 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) + err = mlxcpld_i2c_set_frequency(priv, pdata); + if (err) + goto mlxcpld_i2_probe_failed; ++ ++ if (pdata->addr) ++ priv->base_addr = (*(u64 __force *)pdata->addr); + } + + /* Register with i2c layer */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0192-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch b/platform/mellanox/non-upstream-patches/patches/0192-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch new file mode 100644 index 0000000000..282ef93129 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0192-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch @@ -0,0 +1,57 @@ +From 22447625fff0e742b3dc9c2f78bbaac29b1f1031 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 27 Nov 2022 10:43:23 +0200 +Subject: [PATCH backport 5.10 06/10] i2c: mlxcpld: Add support for extended + transaction length for i2c-mlxcpld + +Add support for extended length of read and write transactions. +New FPGA logic allows to increase size of the read and write +transactions length. This feature is verified through capability +register 'CPBLTY_REG'. Two bits 5 and 6 of the register are used for +length capability detection. Value '10' indicates support of extended +transaction length - 128 bytes for read transactions and 132 for write +transactions. + +Signed-off-by: Vadim Pasternak +--- + drivers/i2c/busses/i2c-mlxcpld.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c +index cd5401ce4..0e1807be7 100644 +--- a/drivers/i2c/busses/i2c-mlxcpld.c ++++ b/drivers/i2c/busses/i2c-mlxcpld.c +@@ -22,6 +22,7 @@ + #define MLXCPLD_I2C_BUS_NUM 1 + #define MLXCPLD_I2C_DATA_REG_SZ 36 + #define MLXCPLD_I2C_DATA_SZ_BIT BIT(5) ++#define MLXCPLD_I2C_DATA_EXT2_SZ_BIT BIT(6) + #define MLXCPLD_I2C_DATA_SZ_MASK GENMASK(6, 5) + #define MLXCPLD_I2C_SMBUS_BLK_BIT BIT(7) + #define MLXCPLD_I2C_MAX_ADDR_LEN 4 +@@ -466,6 +467,13 @@ static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = { + .max_comb_1st_msg_len = 4, + }; + ++static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext2 = { ++ .flags = I2C_AQ_COMB_WRITE_THEN_READ, ++ .max_read_len = (MLXCPLD_I2C_DATA_REG_SZ - 4) * 4, ++ .max_write_len = (MLXCPLD_I2C_DATA_REG_SZ - 4) * 4 + MLXCPLD_I2C_MAX_ADDR_LEN, ++ .max_comb_1st_msg_len = 4, ++}; ++ + static struct i2c_adapter mlxcpld_i2c_adapter = { + .owner = THIS_MODULE, + .name = "i2c-mlxcpld", +@@ -550,6 +558,8 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) + /* Check support for extended transaction length */ + if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT) + mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext; ++ else if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_EXT2_SZ_BIT) ++ mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext2; + /* Check support for smbus block transaction */ + if (val & MLXCPLD_I2C_SMBUS_BLK_BIT) + priv->smbus_block = true; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0193-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch b/platform/mellanox/non-upstream-patches/patches/0193-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch new file mode 100644 index 0000000000..79a4cafb68 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0193-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch @@ -0,0 +1,99 @@ +From e1d377039ba9a364f4e7f9816f5f0b7a3b165b43 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 18 Jan 2023 15:08:46 +0200 +Subject: [PATCH backport 5.10 07/10] platform: mellanox: mlx-platform: Add mux + selection register to regmap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extend writeable, readable, volatile registers of the 'regmap' object +with for I2C mux selector registers. + +The motivation is to pass this object extended with selector registers +to I2C mux driver working over ‘regmap’. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index e8c656d6e..03c744f37 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -140,6 +140,10 @@ + #define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2 + #define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3 + #define MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET 0xd9 ++#define MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET 0xdb ++#define MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET 0xda ++#define MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET 0xdc ++#define MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET 0xdd + #define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde + #define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf + #define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0 +@@ -173,23 +177,19 @@ + #define MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET 0xfc + #define MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET 0xfd + #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 +-#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb +-#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda +-#define MLXPLAT_CPLD_LPC_I2C_CH3_OFF 0xdc +-#define MLXPLAT_CPLD_LPC_I2C_CH4_OFF 0xdd + + #define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL + #define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ +- MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \ ++ MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET) | \ + MLXPLAT_CPLD_LPC_PIO_OFFSET) + #define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ +- MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \ ++ MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET) | \ + MLXPLAT_CPLD_LPC_PIO_OFFSET) + #define MLXPLAT_CPLD_LPC_REG3 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ +- MLXPLAT_CPLD_LPC_I2C_CH3_OFF) | \ ++ MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET) | \ + MLXPLAT_CPLD_LPC_PIO_OFFSET) + #define MLXPLAT_CPLD_LPC_REG4 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ +- MLXPLAT_CPLD_LPC_I2C_CH4_OFF) | \ ++ MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET) | \ + MLXPLAT_CPLD_LPC_PIO_OFFSET) + + /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */ +@@ -5307,6 +5307,10 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: +@@ -5434,6 +5438,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: +@@ -5581,6 +5589,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0194-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch b/platform/mellanox/non-upstream-patches/patches/0194-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch new file mode 100644 index 0000000000..154f02d705 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0194-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch @@ -0,0 +1,35 @@ +From deb8517499160d77e94b2969a98b3c01bed1a649 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 18 Jan 2023 15:25:37 +0200 +Subject: [PATCH backport 5.10 082/150] platform: mellanox: mlx-platform: Move + bus shift assignment out of the loop + +Move assignment of bus shift setting out of the loop to avoid redundant +operation. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index de8fd0886..9d4cab937 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -6371,10 +6371,11 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr) + shift = *nr - mlxplat_mux_data[i].parent; + mlxplat_mux_data[i].parent = *nr; + mlxplat_mux_data[i].base_nr += shift; +- if (shift > 0) +- mlxplat_hotplug->shift_nr = shift; + } + ++ if (shift > 0) ++ mlxplat_hotplug->shift_nr = shift; ++ + return 0; + } + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0195-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch b/platform/mellanox/non-upstream-patches/patches/0195-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch new file mode 100644 index 0000000000..fa24430325 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0195-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch @@ -0,0 +1,158 @@ +From d1fbdc9c5bd0939362ebdb4d76a701cb938f3837 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 18 Jan 2023 19:12:12 +0200 +Subject: [PATCH backport 5.10 083/150] platform/mellanox: Add support for + dynamic I2C channels infrastructure + +Allow to support platform configuration for dynamically allocated I2C +channels. +Motivation is to support I2C channels allocated in a non-continuous +way. + +Currently hotplug platform driver data structure contains static mux +channels for I2C hotplug devices. These channels numbers can be updated +dynamically and returned by mux driver's callback through the adapters +array. +Thus, hotplug mux channels will be aligned according to the dynamic +adapters data. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 69 ++++++++++++++++++++++++----- + 1 file changed, 59 insertions(+), 10 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 9d4cab937..773d110c9 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -336,6 +337,7 @@ + * @hotplug_resources: system hotplug resources + * @hotplug_resources_size: size of system hotplug resources + * @hi2c_main_init_status: init status of I2C main bus ++ * @mux_added: number of added mux segments + */ + struct mlxplat_priv { + struct platform_device *pdev_i2c; +@@ -349,6 +351,7 @@ struct mlxplat_priv { + struct resource *hotplug_resources; + unsigned int hotplug_resources_size; + u8 i2c_main_init_status; ++ int mux_added; + }; + + static struct platform_device *mlxplat_dev; +@@ -436,7 +439,9 @@ static struct i2c_mux_reg_platform_data mlxplat_default_mux_data[] = { + /* Platform mux configuration variables */ + static int mlxplat_max_adap_num; + static int mlxplat_mux_num; ++static int mlxplat_mux_hotplug_num; + static struct i2c_mux_reg_platform_data *mlxplat_mux_data; ++static struct i2c_mux_regmap_platform_data *mlxplat_mux_regmap_data; + + /* Platform extended mux data */ + static struct i2c_mux_reg_platform_data mlxplat_extended_mux_data[] = { +@@ -6368,12 +6373,17 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr) + /* Shift adapter ids, since expected parent adapter is not free. */ + *nr = i; + for (i = 0; i < mlxplat_mux_num; i++) { +- shift = *nr - mlxplat_mux_data[i].parent; +- mlxplat_mux_data[i].parent = *nr; +- mlxplat_mux_data[i].base_nr += shift; ++ if (mlxplat_mux_data) { ++ shift = *nr - mlxplat_mux_data[i].parent; ++ mlxplat_mux_data[i].parent = *nr; ++ mlxplat_mux_data[i].base_nr += shift; ++ } else if (mlxplat_mux_regmap_data) { ++ mlxplat_mux_regmap_data[i].parent = *nr; ++ } + } + +- if (shift > 0) ++ /* Shift bus only if mux provided by 'mlxplat_mux_data'. */ ++ if (shift > 0 && mlxplat_mux_data) + mlxplat_hotplug->shift_nr = shift; + + return 0; +@@ -6563,8 +6573,31 @@ mlxplat_i2c_mux_complition_notify(void *handle, struct i2c_adapter *parent, + struct i2c_adapter *adapters[]) + { + struct mlxplat_priv *priv = handle; ++ struct mlxreg_core_item *item; ++ int i, j; ++ ++ /* ++ * Hotplug platform driver data structure contains static mux channels for I2C hotplug ++ * devices. These channels numbers can be updated dynamically and returned by mux callback ++ * through the adapters array. Update mux channels according to the dynamic adapters data. ++ */ ++ if (priv->mux_added == mlxplat_mux_hotplug_num) { ++ item = mlxplat_hotplug->items; ++ for (i = 0; i < mlxplat_hotplug->counter; i++, item++) { ++ struct mlxreg_core_data *data = item->data; ++ ++ for (j = 0; j < item->count; j++, data++) { ++ if (data->hpdev.nr != MLXPLAT_CPLD_NR_NONE) ++ data->hpdev.nr = adapters[data->hpdev.nr - 2]->nr; ++ } ++ } ++ } + +- return mlxplat_post_init(priv); ++ /* Start post initialization only after last nux segment is added */ ++ if (++priv->mux_added == mlxplat_mux_num) ++ return mlxplat_post_init(priv); ++ ++ return 0; + } + + static int mlxplat_i2c_mux_topolgy_init(struct mlxplat_priv *priv) +@@ -6578,17 +6611,33 @@ static int mlxplat_i2c_mux_topolgy_init(struct mlxplat_priv *priv) + + priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED; + for (i = 0; i < mlxplat_mux_num; i++) { +- priv->pdev_mux[i] = platform_device_register_resndata(&priv->pdev_i2c->dev, +- "i2c-mux-reg", i, NULL, 0, +- &mlxplat_mux_data[i], +- sizeof(mlxplat_mux_data[i])); ++ if (mlxplat_mux_data) { ++ priv->pdev_mux[i] = ++ platform_device_register_resndata(&priv->pdev_i2c->dev, ++ "i2c-mux-reg", i, NULL, 0, ++ &mlxplat_mux_data[i], ++ sizeof(mlxplat_mux_data[i])); ++ } else { ++ mlxplat_mux_regmap_data[i].handle = priv; ++ mlxplat_mux_regmap_data[i].regmap = priv->regmap; ++ mlxplat_mux_regmap_data[i].completion_notify = ++ mlxplat_i2c_mux_complition_notify; ++ priv->pdev_mux[i] = ++ platform_device_register_resndata(&priv->pdev_i2c->dev, ++ "i2c-mux-regmap", i, NULL, 0, ++ &mlxplat_mux_regmap_data[i], ++ sizeof(mlxplat_mux_regmap_data[i])); ++ } + if (IS_ERR(priv->pdev_mux[i])) { + err = PTR_ERR(priv->pdev_mux[i]); + goto fail_platform_mux_register; + } + } + +- return mlxplat_i2c_mux_complition_notify(priv, NULL, NULL); ++ if (mlxplat_mux_regmap_data && mlxplat_mux_regmap_data->completion_notify) ++ return 0; ++ ++ return mlxplat_post_init(priv); + + fail_platform_mux_register: + while (--i >= 0) +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0196-platform-mellanox-Relocate-mlx-platform-driver.patch b/platform/mellanox/non-upstream-patches/patches/0196-platform-mellanox-Relocate-mlx-platform-driver.patch new file mode 100644 index 0000000000..473be771db --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0196-platform-mellanox-Relocate-mlx-platform-driver.patch @@ -0,0 +1,99 @@ +From 723dacff3d93f270a52195c895e2ddf233b146d7 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 7 Nov 2022 11:52:34 +0200 +Subject: [PATCH backport 5.10 084/150] platform: mellanox: Relocate + mlx-platform driver + +Move 'mlx-platform' driver 'x86' to 'mellanox' folder. + +Motivation to allow running it on systems with ARM architecture. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/Kconfig | 12 ++++++++++++ + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/{x86 => mellanox}/mlx-platform.c | 0 + drivers/platform/x86/Kconfig | 12 ------------ + drivers/platform/x86/Makefile | 1 - + 5 files changed, 13 insertions(+), 13 deletions(-) + rename drivers/platform/{x86 => mellanox}/mlx-platform.c (100%) + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index 75e2bee17..ff8267329 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -14,6 +14,19 @@ menuconfig MELLANOX_PLATFORM + + if MELLANOX_PLATFORM + ++config MLX_PLATFORM ++ tristate "Mellanox Technologies platform support" ++ depends on I2C ++ select REGMAP ++ help ++ This option enables system support for the Mellanox Technologies ++ platform. The Mellanox systems provide data center networking ++ solutions based on Virtual Protocol Interconnect (VPI) technology ++ enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE ++ connection. ++ ++ If you have a Mellanox system, say Y or M here. ++ + config MLXREG_HOTPLUG + tristate "Mellanox platform hotplug driver support" + depends on REGMAP +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index 6af37ee88..23919e56a 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -3,6 +3,7 @@ + # Makefile for linux/drivers/platform/mellanox + # Mellanox Platform-Specific Drivers + # ++obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o + obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o + obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +similarity index 100% +rename from drivers/platform/x86/mlx-platform.c +rename to drivers/platform/mellanox/mlx-platform.c +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index a1858689d..4270d4c17 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -1193,19 +1193,6 @@ config I2C_MULTI_INSTANTIATE + To compile this driver as a module, choose M here: the module + will be called i2c-multi-instantiate. + +-config MLX_PLATFORM +- tristate "Mellanox Technologies platform support" +- depends on I2C +- select REGMAP +- help +- This option enables system support for the Mellanox Technologies +- platform. The Mellanox systems provide data center networking +- solutions based on Virtual Protocol Interconnect (VPI) technology +- enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE +- connection. +- +- If you have a Mellanox system, say Y or M here. +- + config TOUCHSCREEN_DMI + bool "DMI based touchscreen configuration info" + depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD +diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile +index 5f823f7ef..1db86675f 100644 +--- a/drivers/platform/x86/Makefile ++++ b/drivers/platform/x86/Makefile +@@ -122,7 +122,6 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o + + # Platform drivers + obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o +-obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o + obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o + + # Intel uncore drivers +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0197-platform-mellanox-Add-initial-support-for-PCIe-based.patch b/platform/mellanox/non-upstream-patches/patches/0197-platform-mellanox-Add-initial-support-for-PCIe-based.patch new file mode 100644 index 0000000000..ae18a952d7 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0197-platform-mellanox-Add-initial-support-for-PCIe-based.patch @@ -0,0 +1,186 @@ +From e831f971fd9895b74c0966b3cf3cd2e18c2f8fca Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 10 Nov 2022 08:53:49 +0200 +Subject: [PATCH backport 5.10 085/150] platform: mellanox: Add initial support + for PCIe based programming logic device + +Extend driver to support logic implemented by FPGA device connected +through PCIe bus. + +The motivation two support new generation of Nvidia COME module, based +on ARM64 architecture, and equipped with Lattice LFD2NX-40 FPGA device. + +In order to support new Nvidia COME module FPGA device driver +initialization flow is modified. In case FPGA device is detected, +system resources are to be mapped to this device, otherwise system +resources are to be mapped same as it has been done before for Lattice +LPC based CPLD. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlx-platform.c | 106 ++++++++++++++++++++++- + 1 file changed, 105 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 773d110c9..f3df56c41 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -315,6 +316,7 @@ + #define MLXPLAT_CPLD_WD_MAX_DEVS 2 + + #define MLXPLAT_CPLD_LPC_SYSIRQ 17 ++#define MLXPLAT_FPGA_PCIE_SYSIRQ 17 + + /* Minimum power required for turning on Ethernet modular system (WATT) */ + #define MLXPLAT_CPLD_ETH_MODULAR_PWR_MIN 50 +@@ -325,6 +327,11 @@ + #define MLXPLAT_I2C_MAIN_BUS_NOTIFIED 0x01 + #define MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED 0x02 + ++/* Lattice FPGA PCI configuration */ ++#define PCI_VENDOR_ID_LATTICE 0x1204 ++#define PCI_DEVICE_ID_LATTICE_LFD2NX40 0x9c1d ++#define MLXPLAT_FPGA_PCI_BAR0_SIZE 0x4000 ++ + /* mlxplat_priv - platform private data + * @pdev_i2c - i2c controller platform device + * @pdev_mux - array of mux platform devices +@@ -5793,6 +5800,11 @@ static struct resource mlxplat_mlxcpld_resources[] = { + [0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_CPLD_LPC_SYSIRQ, "mlxreg-hotplug"), + }; + ++static struct resource mlxplat_mlxfpga_resources[] = { ++ [0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_FPGA_PCIE_SYSIRQ, "mlxreg-hotplug"), ++}; ++ ++static struct platform_device *mlxplat_dev; + static struct mlxreg_core_hotplug_platform_data *mlxplat_i2c; + static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; + static struct mlxreg_core_platform_data *mlxplat_led; +@@ -5802,6 +5814,7 @@ static struct mlxreg_core_platform_data + *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS]; + static const struct regmap_config *mlxplat_regmap_config; + static struct spi_board_info *mlxplat_spi; ++static struct pci_dev *fpga_dev; + + /* Platform default poweroff function */ + static void mlxplat_poweroff(void) +@@ -6443,15 +6456,106 @@ static void mlxplat_lpc_cpld_device_exit(void) + platform_device_unregister(mlxplat_dev); + } + ++static int ++mlxplat_pci_fpga_device_init(struct resource **hotplug_resources, ++ unsigned int *hotplug_resources_size, struct pci_dev **fpga_dev) ++{ ++ struct pci_dev *pci_dev; ++ int err; ++ ++ pci_dev = pci_get_device(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_LATTICE_LFD2NX40, NULL); ++ if (!pci_dev) ++ return -ENODEV; ++ ++ err = pci_enable_device(pci_dev); ++ if (err) { ++ dev_err(&mlxplat_dev->dev, "pci_enable_device failed\n"); ++ goto fail_pci_enable_device; ++ } ++ ++ err = pci_request_regions(pci_dev, "mlx-patform"); ++ if (err) { ++ dev_err(&mlxplat_dev->dev, "pci_request_regions failed\n"); ++ goto fail_pci_request_regions; ++ } ++ ++ err = dma_set_mask_and_coherent(&mlxplat_dev->dev, DMA_BIT_MASK(64)); ++ if (err) { ++ err = dma_set_mask(&mlxplat_dev->dev, DMA_BIT_MASK(32)); ++ if (err) { ++ dev_err(&mlxplat_dev->dev, "dma_set_mask failed\n"); ++ goto fail_pci_set_dma_mask; ++ } ++ } ++ ++ if (pci_resource_len(pci_dev, 0) < MLXPLAT_FPGA_PCI_BAR0_SIZE) { ++ dev_err(&mlxplat_dev->dev, "invalid PCI region size\n"); ++ err = -EINVAL; ++ goto fail_pci_resource_len_check; ++ } ++ ++ mlxplat_mlxcpld_regmap_ctx.base = devm_ioremap(&mlxplat_dev->dev, ++ pci_resource_start(pci_dev, 0), ++ pci_resource_len(pci_dev, 0)); ++ if (!mlxplat_mlxcpld_regmap_ctx.base) { ++ dev_err(&mlxplat_dev->dev, "ioremap failed\n"); ++ err = -EIO; ++ goto fail_ioremap; ++ } ++ pci_set_master(pci_dev); ++ ++ mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, PLATFORM_DEVID_NONE, ++ NULL, 0); ++ if (IS_ERR(mlxplat_dev)) { ++ err = PTR_ERR(mlxplat_dev); ++ goto fail_platform_device_register_simple; ++ } ++ ++ *hotplug_resources = mlxplat_mlxfpga_resources; ++ *hotplug_resources_size = ARRAY_SIZE(mlxplat_mlxfpga_resources); ++ *fpga_dev = pci_dev; ++ ++ return 0; ++ ++fail_platform_device_register_simple: ++fail_ioremap: ++fail_pci_resource_len_check: ++fail_pci_set_dma_mask: ++ pci_release_regions(pci_dev); ++fail_pci_request_regions: ++ pci_disable_device(pci_dev); ++fail_pci_enable_device: ++ return err; ++} ++ ++static void mlxplat_pci_fpga_device_exit(void) ++{ ++ platform_device_unregister(mlxplat_dev); ++ iounmap(mlxplat_mlxcpld_regmap_ctx.base); ++ pci_release_regions(fpga_dev); ++ pci_disable_device(fpga_dev); ++} ++ + static int + mlxplat_pre_init(struct resource **hotplug_resources, unsigned int *hotplug_resources_size) + { ++ int err; ++ ++ err = mlxplat_pci_fpga_device_init(hotplug_resources, hotplug_resources_size, &fpga_dev); ++ if (!err) ++ return 0; ++ else if (err != -ENODEV) ++ return err; ++ + return mlxplat_lpc_cpld_device_init(hotplug_resources, hotplug_resources_size); + } + + static void mlxplat_post_exit(void) + { +- mlxplat_lpc_cpld_device_exit(); ++ if (fpga_dev) ++ mlxplat_pci_fpga_device_exit(); ++ else ++ mlxplat_lpc_cpld_device_exit(); + } + + static int mlxplat_post_init(struct mlxplat_priv *priv) +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0198-platform-mellanox-Introduce-support-for-switches-bas.patch b/platform/mellanox/non-upstream-patches/patches/0198-platform-mellanox-Introduce-support-for-switches-bas.patch new file mode 100644 index 0000000000..1c24c54d6f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0198-platform-mellanox-Introduce-support-for-switches-bas.patch @@ -0,0 +1,253 @@ +From bcdfc7d1d106889fa9af3404f252fb1260f5a0fd Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 15 Nov 2022 11:51:47 +0200 +Subject: [PATCH backport 5.10 086/150] platform: mellanox: Introduce support + for switches based on BlueField-3/ARM64 COMe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for Nvidia MQM97xx family switches providing a +high-performance solution by delivering high bandwidth with low latency +to Enterprise Data Centers. + +These switches are based on previous generation of MQM97xx switches, +excepting CFL based COMe module is replaced by new BlueField®-3 COMe +module. + +Switches of this class are equipped with: +- Nvidia Quantum™-2 ASIC, providing up to 64x400GB/s (IB) full + bidirectional bandwidth per port using PAM-4 modulation. +- Com-Express type 7 module, based on Nvidia NVIDIA® BlueField®-3 + processing unit and equipped with LATTICE LFD2NX40 Certus™-NX FPGA + secured device with fail safe + mechanism, connected by PCIe bus. +- Switch board with two Lattice LCMXO3D-9400HC secured with fail safe + mechanism, connected by PCEi-to-LPC bridge. +- Fan board to supporting 7 fans. +- 2x power extender boards. +- 7x FRU fans. +- 2x 2000W AC/DC PSU (FRU). + +New switches platform configuration is based on the new VMOD0016 +class. Configuration is extended to support new register map with +callbacks supporting indirect addressing for PCIe-to-LPC bridge. +This bridge provides interface between FPAG at COMe board (directly +connected to CPU PCIe root complex) to CPLDs on switch board (which +cannot be connected directly to PCIe root complex). + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlx-platform.c | 147 ++++++++++++++++++++++- + 1 file changed, 146 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index f3df56c41..b1c8632d6 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -270,6 +270,7 @@ + /* Maximum number of possible physical buses equipped on system */ + #define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16 + #define MLXPLAT_CPLD_MAX_PHYS_EXT_ADAPTER_NUM 24 ++#define MLXPLAT_CPLD_DEFAULT_MUX_HOTPLUG_VECTOR 0 + + /* Number of channels in group */ + #define MLXPLAT_CPLD_GRP_CHNL_NUM 8 +@@ -331,6 +332,17 @@ + #define PCI_VENDOR_ID_LATTICE 0x1204 + #define PCI_DEVICE_ID_LATTICE_LFD2NX40 0x9c1d + #define MLXPLAT_FPGA_PCI_BAR0_SIZE 0x4000 ++#define MLXPLAT_FPGA_PCI_BASE_OFFSET 0x00000000 ++#define MLXPLAT_FPGA_PCI_ADDR_OFFSET MLXPLAT_FPGA_PCI_BASE_OFFSET ++#define MLXPLAT_FPGA_PCI_DATA_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x02) ++#define MLXPLAT_FPGA_PCI_CTRL_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x04) ++#define MLXPLAT_FPGA_PCI_STAT_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x06) ++#define MLXPLAT_FPGA_PCI_I2C_LPC_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x400) ++ ++#define MLXPLAT_FPGA_PCI_CTRL_READ BIT(0) ++#define MLXPLAT_FPGA_PCI_CTRL_WRITE BIT(1) ++#define MLXPLAT_FPGA_PCI_COMPLETED BIT(0) ++#define MLXPLAT_FPGA_PCI_TO 50 /* usec */ + + /* mlxplat_priv - platform private data + * @pdev_i2c - i2c controller platform device +@@ -443,6 +455,28 @@ static struct i2c_mux_reg_platform_data mlxplat_default_mux_data[] = { + + }; + ++/* Default channels vector for regmap mux. */ ++static int mlxplat_default_regmap_mux_chan[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; ++ ++/* Platform regmap mux data */ ++static struct i2c_mux_regmap_platform_data mlxplat_default_regmap_mux_data[] = { ++ { ++ .parent = 1, ++ .chan_ids = mlxplat_default_regmap_mux_chan, ++ .num_adaps = ARRAY_SIZE(mlxplat_default_regmap_mux_chan), ++ .sel_reg_addr = MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET, ++ .reg_size = 1, ++ }, ++ { ++ .parent = 1, ++ .chan_ids = mlxplat_default_regmap_mux_chan, ++ .num_adaps = ARRAY_SIZE(mlxplat_default_regmap_mux_chan), ++ .sel_reg_addr = MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET, ++ .reg_size = 1, ++ }, ++ ++}; ++ + /* Platform mux configuration variables */ + static int mlxplat_max_adap_num; + static int mlxplat_mux_num; +@@ -5796,6 +5830,84 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = { + .reg_write = mlxplat_mlxcpld_reg_write, + }; + ++/* Wait completion routine for indirect access for register map */ ++static int mlxplat_fpga_completion_wait(struct mlxplat_mlxcpld_regmap_context *ctx) ++{ ++ unsigned long end; ++ u16 status; ++ ++ end = jiffies + msecs_to_jiffies(MLXPLAT_FPGA_PCI_TO); ++ do { ++ status = ioread16(ctx->base + MLXPLAT_FPGA_PCI_STAT_OFFSET); ++ if (status & MLXPLAT_FPGA_PCI_COMPLETED) ++ return 0; ++ cond_resched(); ++ } while (time_before(jiffies, end)); ++ ++ return -EIO; ++} ++ ++/* Read callback for indirect register map access */ ++static int mlxplat_fpga_reg_read(void *context, unsigned int reg, unsigned int *val) ++{ ++ struct mlxplat_mlxcpld_regmap_context *ctx = context; ++ int err; ++ ++ /* Verify there is no pending transactions */ ++ err = mlxplat_fpga_completion_wait(ctx); ++ if (err) ++ return err; ++ ++ /* Set address in register space */ ++ iowrite16(reg, ctx->base + MLXPLAT_FPGA_PCI_ADDR_OFFSET); ++ /* Activate read operation */ ++ iowrite16(MLXPLAT_FPGA_PCI_CTRL_READ, ctx->base + MLXPLAT_FPGA_PCI_CTRL_OFFSET); ++ /* Verify transaction completion */ ++ err = mlxplat_fpga_completion_wait(ctx); ++ if (err) ++ return err; ++ ++ /* Read data */ ++ *val = ioread16(ctx->base + MLXPLAT_FPGA_PCI_DATA_OFFSET); ++ ++ return 0; ++} ++ ++/* Write callback for indirect register map access */ ++static int mlxplat_fpga_reg_write(void *context, unsigned int reg, unsigned int val) ++{ ++ struct mlxplat_mlxcpld_regmap_context *ctx = context; ++ int err; ++ ++ /* Verify there is no pending transactions */ ++ err = mlxplat_fpga_completion_wait(ctx); ++ if (err) ++ return err; ++ ++ /* Set address in register space */ ++ iowrite16(reg, ctx->base + MLXPLAT_FPGA_PCI_ADDR_OFFSET); ++ /* Set data to be written */ ++ iowrite16(val, ctx->base + MLXPLAT_FPGA_PCI_DATA_OFFSET); ++ /* Activate write operation */ ++ iowrite16(MLXPLAT_FPGA_PCI_CTRL_WRITE, ctx->base + MLXPLAT_FPGA_PCI_CTRL_OFFSET); ++ ++ return 0; ++} ++ ++static const struct regmap_config mlxplat_fpga_regmap_config_bf3_comex_default = { ++ .reg_bits = 16, ++ .val_bits = 8, ++ .max_register = 512, ++ .cache_type = REGCACHE_FLAT, ++ .writeable_reg = mlxplat_mlxcpld_writeable_reg, ++ .readable_reg = mlxplat_mlxcpld_readable_reg, ++ .volatile_reg = mlxplat_mlxcpld_volatile_reg, ++ .reg_defaults = mlxplat_mlxcpld_regmap_ng400, ++ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_ng400), ++ .reg_read = mlxplat_fpga_reg_read, ++ .reg_write = mlxplat_fpga_reg_write, ++}; ++ + static struct resource mlxplat_mlxcpld_resources[] = { + [0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_CPLD_LPC_SYSIRQ, "mlxreg-hotplug"), + }; +@@ -6175,6 +6287,29 @@ static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi) + return 1; + } + ++static int __init mlxplat_dmi_bf3_comex_default_matched(const struct dmi_system_id *dmi) ++{ ++ int i; ++ ++ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; ++ mlxplat_mux_hotplug_num = MLXPLAT_CPLD_DEFAULT_MUX_HOTPLUG_VECTOR; ++ mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_regmap_mux_data); ++ mlxplat_mux_regmap_data = mlxplat_default_regmap_mux_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_ext_data; ++ mlxplat_hotplug->deferred_nr = ++ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; ++ mlxplat_led = &mlxplat_default_ng_led_data; ++ mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; ++ mlxplat_fan = &mlxplat_default_fan_data; ++ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) ++ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; ++ mlxplat_regmap_config = &mlxplat_fpga_regmap_config_bf3_comex_default; ++ pm_power_off = mlxplat_poweroff; ++ ++ return 1; ++} ++ + static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + { + .callback = mlxplat_dmi_default_wc_matched, +@@ -6270,6 +6405,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + DMI_MATCH(DMI_BOARD_NAME, "VMOD0015"), + }, + }, ++ { ++ .callback = mlxplat_dmi_bf3_comex_default_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0016"), ++ }, ++ }, + { + .callback = mlxplat_dmi_l1_switch_matched, + .matches = { +@@ -6502,6 +6643,11 @@ mlxplat_pci_fpga_device_init(struct resource **hotplug_resources, + err = -EIO; + goto fail_ioremap; + } ++ ++ /* Set mapped base address of I2C-LPC bridge over PCIe */ ++ mlxplat_i2c->addr = mlxplat_mlxcpld_regmap_ctx.base + ++ MLXPLAT_FPGA_PCI_I2C_LPC_OFFSET; ++ + pci_set_master(pci_dev); + + mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, PLATFORM_DEVID_NONE, +@@ -6782,7 +6928,6 @@ static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) + nr = (nr == mlxplat_max_adap_num) ? -1 : nr; + mlxplat_i2c->regmap = priv->regmap; + mlxplat_i2c->handle = priv; +- + priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld", + nr, priv->hotplug_resources, + priv->hotplug_resources_size, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0199-platform-mellanox-mlx-platform-Add-reset-and-extend-.patch b/platform/mellanox/non-upstream-patches/patches/0199-platform-mellanox-mlx-platform-Add-reset-and-extend-.patch new file mode 100644 index 0000000000..f9079db493 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0199-platform-mellanox-mlx-platform-Add-reset-and-extend-.patch @@ -0,0 +1,138 @@ +From a556177a2359c784e063f0914049ffd7f8d8852d Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Tue, 22 Nov 2022 21:20:49 +0200 +Subject: [PATCH backport 5.10 087/150] platform: mellanox: mlx-platform: Add + reset and extend poweroff callbacks + +On ARM based systems reset and poweroff flow should include special +actions against CPLD device for performing graceful operations. +For reset it is necessary to toggle special PLATFORM_RESET# signal, for +poweroff special HALT# signal. + +In order to support such flows relevant actions are provided. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlx-platform.c | 35 ++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index b1c8632d6..849fdf5de 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -43,6 +43,7 @@ + #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d + #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e + #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f ++#define MLXPLAT_CPLD_LPC_REG_PG_RST_OFFSET 0x19 + #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 + #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 + #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 +@@ -263,6 +264,7 @@ + #define MLXPLAT_CPLD_LPC_LC_MASK GENMASK(7, 0) + + #define MLXPLAT_CPLD_HALT_MASK BIT(3) ++#define MLXPLAT_CPLD_RESET_MASK 0xfe + + /* Default I2C parent bus number */ + #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 +@@ -483,6 +485,7 @@ static int mlxplat_mux_num; + static int mlxplat_mux_hotplug_num; + static struct i2c_mux_reg_platform_data *mlxplat_mux_data; + static struct i2c_mux_regmap_platform_data *mlxplat_mux_regmap_data; ++static struct notifier_block *mlxplat_reboot_nb; + + /* Platform extended mux data */ + static struct i2c_mux_reg_platform_data mlxplat_extended_mux_data[] = { +@@ -5280,6 +5283,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + switch (reg) { + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PG_RST_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: +@@ -5387,6 +5391,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PG_RST_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: +@@ -5546,6 +5551,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PG_RST_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: +@@ -5928,12 +5934,31 @@ static const struct regmap_config *mlxplat_regmap_config; + static struct spi_board_info *mlxplat_spi; + static struct pci_dev *fpga_dev; + ++/* Platform default reset function */ ++static int mlxplat_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) ++{ ++ struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); ++ ++ if (action == SYS_RESTART) ++ regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_PG_RST_OFFSET, ++ MLXPLAT_CPLD_RESET_MASK); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block mlxplat_reboot_default_nb = { ++ .notifier_call = mlxplat_reboot_notifier, ++}; ++ + /* Platform default poweroff function */ + static void mlxplat_poweroff(void) + { + struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); + ++ if (mlxplat_reboot_nb) ++ unregister_reboot_notifier(mlxplat_reboot_nb); + regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, MLXPLAT_CPLD_HALT_MASK); ++ kernel_halt(); + } + + static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) +@@ -6305,6 +6330,7 @@ static int __init mlxplat_dmi_bf3_comex_default_matched(const struct dmi_system_ + mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; + mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; + mlxplat_regmap_config = &mlxplat_fpga_regmap_config_bf3_comex_default; ++ mlxplat_reboot_nb = &mlxplat_reboot_default_nb; + pm_power_off = mlxplat_poweroff; + + return 1; +@@ -7012,8 +7038,15 @@ static int __init mlxplat_init(void) + if (err) + goto fail_regcache_sync; + ++ if (mlxplat_reboot_nb) { ++ err = register_reboot_notifier(mlxplat_reboot_nb); ++ if (err) ++ goto fail_register_reboot_notifier; ++ } ++ + return 0; + ++fail_register_reboot_notifier: + fail_regcache_sync: + mlxplat_pre_exit(priv); + fail_mlxplat_i2c_main_init: +@@ -7031,6 +7064,8 @@ static void __exit mlxplat_exit(void) + + if (pm_power_off) + pm_power_off = NULL; ++ if (mlxplat_reboot_nb) ++ unregister_reboot_notifier(mlxplat_reboot_nb); + mlxplat_pre_exit(priv); + mlxplat_i2c_main_exit(priv); + } +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0200-dt-bindings-i2c-mellanox-i2c-mlxbf-convert-txt-to-YA.patch b/platform/mellanox/non-upstream-patches/patches/0200-dt-bindings-i2c-mellanox-i2c-mlxbf-convert-txt-to-YA.patch new file mode 100644 index 0000000000..48fb3ea220 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0200-dt-bindings-i2c-mellanox-i2c-mlxbf-convert-txt-to-YA.patch @@ -0,0 +1,169 @@ +From d10a96f08067a214b2de469b406155d6604930f2 Mon Sep 17 00:00:00 2001 +From: Khalil Blaiech +Date: Fri, 20 Nov 2020 18:06:06 -0500 +Subject: [PATCH backport 5.10 01/63] dt-bindings: i2c: mellanox,i2c-mlxbf: + convert txt to YAML schema + +Write the devicetree binding text file associated with +the Mellanox BlueField I2C controller in schema file, +JSON compatible subset of YAML. Besides, add an entry +within MAINTAINERS file. + +Signed-off-by: Khalil Blaiech +Reviewed-by: Rob Herring +Signed-off-by: Wolfram Sang +--- + .../bindings/i2c/mellanox,i2c-mlxbf.txt | 42 ---------- + .../bindings/i2c/mellanox,i2c-mlxbf.yaml | 78 +++++++++++++++++++ + MAINTAINERS | 1 + + 3 files changed, 79 insertions(+), 42 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt + create mode 100644 Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml + +diff --git a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt +deleted file mode 100644 +index 566ea861a..000000000 +--- a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt ++++ /dev/null +@@ -1,42 +0,0 @@ +-Device tree configuration for the Mellanox I2C SMBus on BlueField SoCs +- +-Required Properties: +- +-- compatible : should be "mellanox,i2c-mlxbf1" or "mellanox,i2c-mlxbf2". +- +-- reg : address offset and length of the device registers. The +- registers consist of the following set of resources: +- 1) Smbus block registers. +- 2) Cause master registers. +- 3) Cause slave registers. +- 4) Cause coalesce registers (if compatible isn't set +- to "mellanox,i2c-mlxbf1"). +- +-- interrupts : interrupt number. +- +-Optional Properties: +- +-- clock-frequency : bus frequency used to configure timing registers; +- allowed values are 100000, 400000 and 1000000; +- those are expressed in Hz. Default is 100000. +- +-Example: +- +-i2c@2804000 { +- compatible = "mellanox,i2c-mlxbf1"; +- reg = <0x02804000 0x800>, +- <0x02801200 0x020>, +- <0x02801260 0x020>; +- interrupts = <57>; +- clock-frequency = <100000>; +-}; +- +-i2c@2808800 { +- compatible = "mellanox,i2c-mlxbf2"; +- reg = <0x02808800 0x600>, +- <0x02808e00 0x020>, +- <0x02808e20 0x020>, +- <0x02808e40 0x010>; +- interrupts = <57>; +- clock-frequency = <400000>; +-}; +diff --git a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml +new file mode 100644 +index 000000000..d2b401d06 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml +@@ -0,0 +1,78 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/i2c/mellanox,i2c-mlxbf.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Mellanox I2C SMBus on BlueField SoCs ++ ++maintainers: ++ - Khalil Blaiech ++ ++allOf: ++ - $ref: /schemas/i2c/i2c-controller.yaml# ++ ++properties: ++ compatible: ++ enum: ++ - mellanox,i2c-mlxbf1 ++ - mellanox,i2c-mlxbf2 ++ ++ reg: ++ minItems: 3 ++ maxItems: 4 ++ items: ++ - description: Smbus block registers ++ - description: Cause master registers ++ - description: Cause slave registers ++ - description: Cause coalesce registers ++ ++ interrupts: ++ maxItems: 1 ++ ++ clock-frequency: ++ enum: [ 100000, 400000, 1000000 ] ++ description: ++ bus frequency used to configure timing registers; ++ The frequency is expressed in Hz. Default is 100000. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ ++unevaluatedProperties: false ++ ++if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - mellanox,i2c-mlxbf1 ++ ++then: ++ properties: ++ reg: ++ maxItems: 3 ++ ++examples: ++ - | ++ i2c@2804000 { ++ compatible = "mellanox,i2c-mlxbf1"; ++ reg = <0x02804000 0x800>, ++ <0x02801200 0x020>, ++ <0x02801260 0x020>; ++ interrupts = <57>; ++ clock-frequency = <100000>; ++ }; ++ ++ - | ++ i2c@2808800 { ++ compatible = "mellanox,i2c-mlxbf2"; ++ reg = <0x02808800 0x600>, ++ <0x02808e00 0x020>, ++ <0x02808e20 0x020>, ++ <0x02808e40 0x010>; ++ interrupts = <57>; ++ clock-frequency = <400000>; ++ }; +diff --git a/MAINTAINERS b/MAINTAINERS +index 4fef10dd2..7db3e06ec 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -11177,6 +11177,7 @@ MELLANOX BLUEFIELD I2C DRIVER + M: Khalil Blaiech + L: linux-i2c@vger.kernel.org + S: Supported ++F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml + F: drivers/i2c/busses/i2c-mlxbf.c + + MELLANOX ETHERNET DRIVER (mlx4_en) +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0203-i2c-mlxbf-remove-IRQF_ONESHOT.patch b/platform/mellanox/non-upstream-patches/patches/0203-i2c-mlxbf-remove-IRQF_ONESHOT.patch new file mode 100644 index 0000000000..369776a08a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0203-i2c-mlxbf-remove-IRQF_ONESHOT.patch @@ -0,0 +1,37 @@ +From 9cd9614ce49f3c793efcc47dbbbfa90d793ed543 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Thu, 8 Sep 2022 13:35:37 -0400 +Subject: [PATCH backport 5.10 04/63] i2c: mlxbf: remove IRQF_ONESHOT + +BugLink: https://bugs.launchpad.net/bugs/1991551 + +IRQF_ONESHOT is not needed so remove it. + +Reviewed-by: Khalil Blaiech +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Wolfram Sang +(cherry picked from commit 92be2c122e495f0249090c0048f4fd05fe1efa9e) +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/i2c/busses/i2c-mlxbf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c +index d78fb24d5..066bfeb8a 100644 +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -2382,7 +2382,7 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) + if (irq < 0) + return irq; + ret = devm_request_irq(dev, irq, mlxbf_smbus_irq, +- IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED, ++ IRQF_SHARED | IRQF_PROBE_SHARED, + dev_name(dev), priv); + if (ret < 0) { + dev_err(dev, "Cannot get irq %d\n", irq); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0206-i2c-mlxbf-add-multi-slave-functionality.patch b/platform/mellanox/non-upstream-patches/patches/0206-i2c-mlxbf-add-multi-slave-functionality.patch new file mode 100644 index 0000000000..a940755c97 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0206-i2c-mlxbf-add-multi-slave-functionality.patch @@ -0,0 +1,549 @@ +From 19c72b4450f4f76cec6030c2eabb87507a90f316 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Mon, 26 Sep 2022 15:45:05 -0400 +Subject: [PATCH backport 5.10 07/63] i2c: mlxbf: add multi slave functionality + +BugLink: https://bugs.launchpad.net/bugs/1991551 + +Support the multi slave functionality which enables the BlueField +to be registered at up to 16 i2c slave addresses. + +Reviewed-by: Khalil Blaiech +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Wolfram Sang +(cherry picked from commit bdc4af281b70b7fe2881fd08f1aa1b15f2b6adf0) +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/i2c/busses/i2c-mlxbf.c | 320 +++++++++++++++------------------ + 1 file changed, 149 insertions(+), 171 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c +index 30b798e92..32dbe1dab 100644 +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -304,9 +304,6 @@ static u64 mlxbf_i2c_corepll_frequency; + #define MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT 7 + #define MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK GENMASK(6, 0) + +-#define MLXBF_I2C_SLAVE_ADDR_ENABLED(addr) \ +- ((addr) & (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT)) +- + /* + * Timeout is given in microsends. Note also that timeout handling is not + * exact. +@@ -432,7 +429,7 @@ struct mlxbf_i2c_priv { + u64 frequency; /* Core frequency in Hz. */ + int bus; /* Physical bus identifier. */ + int irq; +- struct i2c_client *slave; ++ struct i2c_client *slave[MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT]; + }; + + static struct mlxbf_i2c_resource mlxbf_i2c_coalesce_res[] = { +@@ -1549,25 +1546,23 @@ static int mlxbf_i2c_calculate_corepll_freq(struct platform_device *pdev, + return 0; + } + +-static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr) ++static int mlxbf_i2c_slave_enable(struct mlxbf_i2c_priv *priv, ++ struct i2c_client *slave) + { +- u32 slave_reg, slave_reg_tmp, slave_reg_avail, slave_addr_mask; +- u8 reg, reg_cnt, byte, addr_tmp, reg_avail, byte_avail; +- bool avail, disabled; +- +- disabled = false; +- avail = false; ++ u8 reg, reg_cnt, byte, addr_tmp; ++ u32 slave_reg, slave_reg_tmp; + + if (!priv) + return -EPERM; + + reg_cnt = MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT >> 2; +- slave_addr_mask = MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK; + + /* + * Read the slave registers. There are 4 * 32-bit slave registers. +- * Each slave register can hold up to 4 * 8-bit slave configuration +- * (7-bit address, 1 status bit (1 if enabled, 0 if not)). ++ * Each slave register can hold up to 4 * 8-bit slave configuration: ++ * 1) A 7-bit address ++ * 2) And a status bit (1 if enabled, 0 if not). ++ * Look for the next available slave register slot. + */ + for (reg = 0; reg < reg_cnt; reg++) { + slave_reg = readl(priv->smbus->io + +@@ -1582,121 +1577,87 @@ static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr) + addr_tmp = slave_reg_tmp & GENMASK(7, 0); + + /* +- * Mark the first available slave address slot, i.e. its +- * enabled bit should be unset. This slot might be used +- * later on to register our slave. +- */ +- if (!avail && !MLXBF_I2C_SLAVE_ADDR_ENABLED(addr_tmp)) { +- avail = true; +- reg_avail = reg; +- byte_avail = byte; +- slave_reg_avail = slave_reg; +- } +- +- /* +- * Parse slave address bytes and check whether the +- * slave address already exists and it's enabled, +- * i.e. most significant bit is set. ++ * If an enable bit is not set in the ++ * MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG register, then the ++ * slave address slot associated with that bit is ++ * free. So set the enable bit and write the ++ * slave address bits. + */ +- if ((addr_tmp & slave_addr_mask) == addr) { +- if (MLXBF_I2C_SLAVE_ADDR_ENABLED(addr_tmp)) +- return 0; +- disabled = true; +- break; ++ if (!(addr_tmp & MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT)) { ++ slave_reg &= ~(MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK << (byte * 8)); ++ slave_reg |= (slave->addr << (byte * 8)); ++ slave_reg |= MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT << (byte * 8); ++ writel(slave_reg, priv->smbus->io + ++ MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + ++ (reg * 0x4)); ++ ++ /* ++ * Set the slave at the corresponding index. ++ */ ++ priv->slave[(reg * 4) + byte] = slave; ++ ++ return 0; + } + + /* Parse next byte. */ + slave_reg_tmp >>= 8; + } +- +- /* Exit the loop if the slave address is found. */ +- if (disabled) +- break; + } + +- if (!avail && !disabled) +- return -EINVAL; /* No room for a new slave address. */ +- +- if (avail && !disabled) { +- reg = reg_avail; +- byte = byte_avail; +- /* Set the slave address. */ +- slave_reg_avail &= ~(slave_addr_mask << (byte * 8)); +- slave_reg_avail |= addr << (byte * 8); +- slave_reg = slave_reg_avail; +- } +- +- /* Enable the slave address and update the register. */ +- slave_reg |= (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT) << (byte * 8); +- writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + +- reg * 0x4); +- +- return 0; ++ return -EBUSY; + } + +-static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv) ++static int mlxbf_i2c_slave_disable(struct mlxbf_i2c_priv *priv, u8 addr) + { +- u32 slave_reg, slave_reg_tmp, slave_addr_mask; +- u8 addr, addr_tmp, reg, reg_cnt, slave_byte; +- struct i2c_client *client = priv->slave; +- bool exist; ++ u8 addr_tmp, reg, reg_cnt, byte; ++ u32 slave_reg, slave_reg_tmp; + +- exist = false; +- +- addr = client->addr; + reg_cnt = MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT >> 2; +- slave_addr_mask = MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK; + + /* + * Read the slave registers. There are 4 * 32-bit slave registers. +- * Each slave register can hold up to 4 * 8-bit slave configuration +- * (7-bit address, 1 status bit (1 if enabled, 0 if not)). ++ * Each slave register can hold up to 4 * 8-bit slave configuration: ++ * 1) A 7-bit address ++ * 2) And a status bit (1 if enabled, 0 if not). ++ * Check if addr is present in the registers. + */ + for (reg = 0; reg < reg_cnt; reg++) { + slave_reg = readl(priv->smbus->io + + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4); + + /* Check whether the address slots are empty. */ +- if (slave_reg == 0) ++ if (!slave_reg) + continue; + + /* +- * Each register holds 4 slave addresses. So, we have to keep +- * the byte order consistent with the value read in order to +- * update the register correctly, if needed. ++ * Check if addr matches any of the 4 slave addresses ++ * in the register. + */ + slave_reg_tmp = slave_reg; +- slave_byte = 0; +- while (slave_reg_tmp != 0) { +- addr_tmp = slave_reg_tmp & slave_addr_mask; ++ for (byte = 0; byte < 4; byte++) { ++ addr_tmp = slave_reg_tmp & MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK; + /* + * Parse slave address bytes and check whether the + * slave address already exists. + */ + if (addr_tmp == addr) { +- exist = true; +- break; ++ /* Clear the slave address slot. */ ++ slave_reg &= ~(GENMASK(7, 0) << (byte * 8)); ++ writel(slave_reg, priv->smbus->io + ++ MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + ++ (reg * 0x4)); ++ /* Free slave at the corresponding index */ ++ priv->slave[(reg * 4) + byte] = NULL; ++ ++ return 0; + } + + /* Parse next byte. */ + slave_reg_tmp >>= 8; +- slave_byte += 1; + } +- +- /* Exit the loop if the slave address is found. */ +- if (exist) +- break; + } + +- if (!exist) +- return 0; /* Slave is not registered, nothing to do. */ +- +- /* Cleanup the slave address slot. */ +- slave_reg &= ~(GENMASK(7, 0) << (slave_byte * 8)); +- writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + +- reg * 0x4); +- +- return 0; ++ return -ENXIO; + } + + static int mlxbf_i2c_init_coalesce(struct platform_device *pdev, +@@ -1858,72 +1819,81 @@ static bool mlxbf_smbus_slave_wait_for_idle(struct mlxbf_i2c_priv *priv, + return false; + } + +-/* Send byte to 'external' smbus master. */ +-static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) ++static struct i2c_client *mlxbf_i2c_get_slave_from_addr( ++ struct mlxbf_i2c_priv *priv, u8 addr) + { +- u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 }; +- u8 write_size, pec_en, addr, byte, value, byte_cnt, desc_size; +- struct i2c_client *slave = priv->slave; +- u32 control32, data32; +- int ret; ++ int i; + +- if (!slave) +- return -EINVAL; ++ for (i = 0; i < MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT; i++) { ++ if (!priv->slave[i]) ++ continue; + +- addr = 0; +- byte = 0; +- desc_size = MLXBF_I2C_SLAVE_DATA_DESC_SIZE; ++ if (priv->slave[i]->addr == addr) ++ return priv->slave[i]; ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Send byte to 'external' smbus master. This function is executed when ++ * an external smbus master wants to read data from the BlueField. ++ */ ++static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) ++{ ++ u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 }; ++ u8 write_size, pec_en, addr, value, byte_cnt; ++ struct i2c_client *slave; ++ u32 control32, data32; ++ int ret = 0; + + /* +- * Read bytes received from the external master. These bytes should +- * be located in the first data descriptor register of the slave GW. +- * These bytes are the slave address byte and the internal register +- * address, if supplied. ++ * Read the first byte received from the external master to ++ * determine the slave address. This byte is located in the ++ * first data descriptor register of the slave GW. + */ +- if (recv_bytes > 0) { +- data32 = ioread32be(priv->smbus->io + +- MLXBF_I2C_SLAVE_DATA_DESC_ADDR); +- +- /* Parse the received bytes. */ +- switch (recv_bytes) { +- case 2: +- byte = (data32 >> 8) & GENMASK(7, 0); +- fallthrough; +- case 1: +- addr = (data32 & GENMASK(7, 0)) >> 1; +- } ++ data32 = ioread32be(priv->smbus->io + ++ MLXBF_I2C_SLAVE_DATA_DESC_ADDR); ++ addr = (data32 & GENMASK(7, 0)) >> 1; + +- /* Check whether it's our slave address. */ +- if (slave->addr != addr) +- return -EINVAL; ++ /* ++ * Check if the slave address received in the data descriptor register ++ * matches any of the slave addresses registered. If there is a match, ++ * set the slave. ++ */ ++ slave = mlxbf_i2c_get_slave_from_addr(priv, addr); ++ if (!slave) { ++ ret = -ENXIO; ++ goto clear_csr; + } + + /* +- * I2C read transactions may start by a WRITE followed by a READ. +- * Indeed, most slave devices would expect the internal address +- * following the slave address byte. So, write that byte first, +- * and then, send the requested data bytes to the master. ++ * An I2C read can consist of a WRITE bit transaction followed by ++ * a READ bit transaction. Indeed, slave devices often expect ++ * the slave address to be followed by the internal address. ++ * So, write the internal address byte first, and then, send the ++ * requested data to the master. + */ + if (recv_bytes > 1) { + i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); +- value = byte; ++ value = (data32 >> 8) & GENMASK(7, 0); + ret = i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, + &value); + i2c_slave_event(slave, I2C_SLAVE_STOP, &value); + + if (ret < 0) +- return ret; ++ goto clear_csr; + } + + /* +- * Now, send data to the master; currently, the driver supports +- * READ_BYTE, READ_WORD and BLOCK READ protocols. Note that the +- * hardware can send up to 128 bytes per transfer. That is the +- * size of its data registers. ++ * Send data to the master. Currently, the driver supports ++ * READ_BYTE, READ_WORD and BLOCK READ protocols. The ++ * hardware can send up to 128 bytes per transfer which is ++ * the total size of the data registers. + */ + i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value); + +- for (byte_cnt = 0; byte_cnt < desc_size; byte_cnt++) { ++ for (byte_cnt = 0; byte_cnt < MLXBF_I2C_SLAVE_DATA_DESC_SIZE; byte_cnt++) { + data_desc[byte_cnt] = value; + i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value); + } +@@ -1931,8 +1901,6 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + /* Send a stop condition to the backend. */ + i2c_slave_event(slave, I2C_SLAVE_STOP, &value); + +- /* Handle the actual transfer. */ +- + /* Set the number of bytes to write to master. */ + write_size = (byte_cnt - 1) & 0x7f; + +@@ -1955,38 +1923,44 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + */ + mlxbf_smbus_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT); + ++clear_csr: + /* Release the Slave GW. */ + writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); + writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC); + writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY); + +- return 0; ++ return ret; + } + +-/* Receive bytes from 'external' smbus master. */ +-static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes) ++/* ++ * Receive bytes from 'external' smbus master. This function is executed when ++ * an external smbus master wants to write data to the BlueField. ++ */ ++static int mlxbf_i2c_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + { + u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 }; +- struct i2c_client *slave = priv->slave; ++ struct i2c_client *slave; + u8 value, byte, addr; + int ret = 0; + +- if (!slave) +- return -EINVAL; +- + /* Read data from Slave GW data descriptor. */ + mlxbf_i2c_smbus_read_data(priv, data_desc, recv_bytes, + MLXBF_I2C_SLAVE_DATA_DESC_ADDR); +- +- /* Check whether its our slave address. */ + addr = data_desc[0] >> 1; +- if (slave->addr != addr) +- return -EINVAL; + + /* +- * Notify the slave backend; another I2C master wants to write data +- * to us. This event is sent once the slave address and the write bit +- * is detected. ++ * Check if the slave address received in the data descriptor register ++ * matches any of the slave addresses registered. ++ */ ++ slave = mlxbf_i2c_get_slave_from_addr(priv, addr); ++ if (!slave) { ++ ret = -EINVAL; ++ goto clear_csr; ++ } ++ ++ /* ++ * Notify the slave backend that an smbus master wants to write data ++ * to the BlueField. + */ + i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); + +@@ -1999,9 +1973,13 @@ static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + break; + } + +- /* Send a stop condition to the backend. */ ++ /* ++ * Send a stop event to the slave backend, to signal ++ * the end of the write transactions. ++ */ + i2c_slave_event(slave, I2C_SLAVE_STOP, &value); + ++clear_csr: + /* Release the Slave GW. */ + writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); + writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC); +@@ -2010,7 +1988,7 @@ static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + return ret; + } + +-static irqreturn_t mlxbf_smbus_irq(int irq, void *ptr) ++static irqreturn_t mlxbf_i2c_irq(int irq, void *ptr) + { + struct mlxbf_i2c_priv *priv = ptr; + bool read, write, irq_is_set; +@@ -2058,9 +2036,9 @@ static irqreturn_t mlxbf_smbus_irq(int irq, void *ptr) + MLXBF_I2C_SLAVE_DATA_DESC_SIZE : recv_bytes; + + if (read) +- mlxbf_smbus_irq_send(priv, recv_bytes); ++ mlxbf_i2c_irq_send(priv, recv_bytes); + else +- mlxbf_smbus_irq_recv(priv, recv_bytes); ++ mlxbf_i2c_irq_recv(priv, recv_bytes); + + return IRQ_HANDLED; + } +@@ -2155,23 +2133,21 @@ static s32 mlxbf_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, + static int mlxbf_i2c_reg_slave(struct i2c_client *slave) + { + struct mlxbf_i2c_priv *priv = i2c_get_adapdata(slave->adapter); ++ struct device *dev = &slave->dev; + int ret; + +- if (priv->slave) +- return -EBUSY; +- + /* + * Do not support ten bit chip address and do not use Packet Error + * Checking (PEC). + */ +- if (slave->flags & (I2C_CLIENT_TEN | I2C_CLIENT_PEC)) ++ if (slave->flags & (I2C_CLIENT_TEN | I2C_CLIENT_PEC)) { ++ dev_err(dev, "SMBus PEC and 10 bit address not supported\n"); + return -EAFNOSUPPORT; ++ } + +- ret = mlxbf_slave_enable(priv, slave->addr); +- if (ret < 0) +- return ret; +- +- priv->slave = slave; ++ ret = mlxbf_i2c_slave_enable(priv, slave); ++ if (ret) ++ dev_err(dev, "Surpassed max number of registered slaves allowed\n"); + + return 0; + } +@@ -2179,18 +2155,19 @@ static int mlxbf_i2c_reg_slave(struct i2c_client *slave) + static int mlxbf_i2c_unreg_slave(struct i2c_client *slave) + { + struct mlxbf_i2c_priv *priv = i2c_get_adapdata(slave->adapter); ++ struct device *dev = &slave->dev; + int ret; + +- WARN_ON(!priv->slave); +- +- /* Unregister slave, i.e. disable the slave address in hardware. */ +- ret = mlxbf_slave_disable(priv); +- if (ret < 0) +- return ret; +- +- priv->slave = NULL; ++ /* ++ * Unregister slave by: ++ * 1) Disabling the slave address in hardware ++ * 2) Freeing priv->slave at the corresponding index ++ */ ++ ret = mlxbf_i2c_slave_disable(priv, slave->addr); ++ if (ret) ++ dev_err(dev, "Unable to find slave 0x%x\n", slave->addr); + +- return 0; ++ return ret; + } + + static u32 mlxbf_i2c_functionality(struct i2c_adapter *adap) +@@ -2398,7 +2375,7 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; +- ret = devm_request_irq(dev, irq, mlxbf_smbus_irq, ++ ret = devm_request_irq(dev, irq, mlxbf_i2c_irq, + IRQF_SHARED | IRQF_PROBE_SHARED, + dev_name(dev), priv); + if (ret < 0) { +@@ -2493,4 +2470,5 @@ module_exit(mlxbf_i2c_exit); + + MODULE_DESCRIPTION("Mellanox BlueField I2C bus driver"); + MODULE_AUTHOR("Khalil Blaiech "); ++MODULE_AUTHOR("Asmaa Mnebhi "); + MODULE_LICENSE("GPL v2"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0207-i2c-mlxbf-support-BlueField-3-SoC.patch b/platform/mellanox/non-upstream-patches/patches/0207-i2c-mlxbf-support-BlueField-3-SoC.patch new file mode 100644 index 0000000000..e316002656 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0207-i2c-mlxbf-support-BlueField-3-SoC.patch @@ -0,0 +1,967 @@ +From 047991847c5ab4bc9763bb111f05bde863dac8b3 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Tue, 27 Sep 2022 16:39:23 -0400 +Subject: [PATCH backport 5.10 08/63] i2c: mlxbf: support BlueField-3 SoC + +BugLink: https://bugs.launchpad.net/bugs/1991551 + +BlueField-3 SoC has the same I2C IP logic as previous +BlueField-1 and 2 SoCs but it has different registers' addresses. +This is an effort to keep this driver generic across all +BlueField generations. +This patch breaks down the "smbus" resource into 3 separate +resources to enable us to use common registers' offsets for all +BlueField SoCs: +struct mlxbf_i2c_resource *timer; +struct mlxbf_i2c_resource *mst; +struct mlxbf_i2c_resource *slv; + +Of course, all offsets had to be adjusted accordingly, and we took +this chance to reorganize the macros depending on the register block +they target. + +There are only 2 registers' offsets that do not fit within this +schema so their offsets are passed as SoC-specific parameters: +smbus_master_rs_bytes_off +smbus_master_fsm_off + +Reviewed-by: Khalil Blaiech +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Wolfram Sang +(cherry picked from commit 19e13e1330c63506452eed80f473f344e6779b94) +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + MAINTAINERS | 1 + + drivers/i2c/busses/i2c-mlxbf.c | 461 ++++++++++++++++++++------------- + 2 files changed, 285 insertions(+), 177 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 7db3e06ec..f6a974ade 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -11175,6 +11175,7 @@ F: drivers/input/touchscreen/melfas_mip4.c + + MELLANOX BLUEFIELD I2C DRIVER + M: Khalil Blaiech ++M: Asmaa Mnebhi + L: linux-i2c@vger.kernel.org + S: Supported + F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml +diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c +index 32dbe1dab..75d8d00d1 100644 +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -32,8 +32,6 @@ + (MLXBF_I2C_FUNC_SMBUS_DEFAULT | MLXBF_I2C_FUNC_SMBUS_BLOCK | \ + I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SLAVE) + +-#define MLXBF_I2C_SMBUS_MAX 3 +- + /* Shared resources info in BlueField platforms. */ + + #define MLXBF_I2C_COALESCE_TYU_ADDR 0x02801300 +@@ -48,6 +46,9 @@ + #define MLXBF_I2C_COREPLL_YU_ADDR 0x02800c30 + #define MLXBF_I2C_COREPLL_YU_SIZE 0x00c + ++#define MLXBF_I2C_COREPLL_RSH_YU_ADDR 0x13409824 ++#define MLXBF_I2C_COREPLL_RSH_YU_SIZE 0x00c ++ + #define MLXBF_I2C_SHARED_RES_MAX 3 + + /* +@@ -131,14 +132,10 @@ + /* Slave busy bit reset. */ + #define MLXBF_I2C_CAUSE_S_GW_BUSY_FALL BIT(18) + +-#define MLXBF_I2C_CAUSE_SLAVE_ARBITER_BITS_MASK GENMASK(20, 0) +- + /* Cause coalesce registers. */ + #define MLXBF_I2C_CAUSE_COALESCE_0 0x00 +-#define MLXBF_I2C_CAUSE_COALESCE_1 0x04 +-#define MLXBF_I2C_CAUSE_COALESCE_2 0x08 + +-#define MLXBF_I2C_CAUSE_TYU_SLAVE_BIT MLXBF_I2C_SMBUS_MAX ++#define MLXBF_I2C_CAUSE_TYU_SLAVE_BIT 3 + #define MLXBF_I2C_CAUSE_YU_SLAVE_BIT 1 + + /* Functional enable register. */ +@@ -165,21 +162,6 @@ + #define MLXBF_I2C_GPIO_SMBUS_GW_ASSERT_PINS(num, val) \ + ((val) | (0x3 << MLXBF_I2C_GPIO_SMBUS_GW_PINS(num))) + +-/* SMBus timing parameters. */ +-#define MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH 0x00 +-#define MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE 0x04 +-#define MLXBF_I2C_SMBUS_TIMER_THOLD 0x08 +-#define MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP 0x0c +-#define MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA 0x10 +-#define MLXBF_I2C_SMBUS_THIGH_MAX_TBUF 0x14 +-#define MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT 0x18 +- +-enum { +- MLXBF_I2C_TIMING_100KHZ = 100000, +- MLXBF_I2C_TIMING_400KHZ = 400000, +- MLXBF_I2C_TIMING_1000KHZ = 1000000, +-}; +- + /* + * Defines SMBus operating frequency and core clock frequency. + * According to ADB files, default values are compliant to 100KHz SMBus +@@ -198,26 +180,37 @@ enum { + #define MLXBF_I2C_COREPLL_CORE_OD_YU_MASK GENMASK(3, 0) + #define MLXBF_I2C_COREPLL_CORE_R_YU_MASK GENMASK(31, 26) + ++/* SMBus timing parameters. */ ++#define MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH 0x00 ++#define MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE 0x04 ++#define MLXBF_I2C_SMBUS_TIMER_THOLD 0x08 ++#define MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP 0x0c ++#define MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA 0x10 ++#define MLXBF_I2C_SMBUS_THIGH_MAX_TBUF 0x14 ++#define MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT 0x18 + +-/* Core PLL frequency. */ +-static u64 mlxbf_i2c_corepll_frequency; ++#define MLXBF_I2C_SHIFT_0 0 ++#define MLXBF_I2C_SHIFT_8 8 ++#define MLXBF_I2C_SHIFT_16 16 ++#define MLXBF_I2C_SHIFT_24 24 ++ ++#define MLXBF_I2C_MASK_8 GENMASK(7, 0) ++#define MLXBF_I2C_MASK_16 GENMASK(15, 0) ++ ++#define MLXBF_I2C_MST_ADDR_OFFSET 0x200 + + /* SMBus Master GW. */ +-#define MLXBF_I2C_SMBUS_MASTER_GW 0x200 ++#define MLXBF_I2C_SMBUS_MASTER_GW 0x0 + /* Number of bytes received and sent. */ +-#define MLXBF_I2C_SMBUS_RS_BYTES 0x300 ++#define MLXBF_I2C_YU_SMBUS_RS_BYTES 0x100 ++#define MLXBF_I2C_RSH_YU_SMBUS_RS_BYTES 0x10c + /* Packet error check (PEC) value. */ +-#define MLXBF_I2C_SMBUS_MASTER_PEC 0x304 ++#define MLXBF_I2C_SMBUS_MASTER_PEC 0x104 + /* Status bits (ACK/NACK/FW Timeout). */ +-#define MLXBF_I2C_SMBUS_MASTER_STATUS 0x308 ++#define MLXBF_I2C_SMBUS_MASTER_STATUS 0x108 + /* SMbus Master Finite State Machine. */ +-#define MLXBF_I2C_SMBUS_MASTER_FSM 0x310 +- +-/* +- * When enabled, the master will issue a stop condition in case of +- * timeout while waiting for FW response. +- */ +-#define MLXBF_I2C_SMBUS_EN_FW_TIMEOUT 0x31c ++#define MLXBF_I2C_YU_SMBUS_MASTER_FSM 0x110 ++#define MLXBF_I2C_RSH_YU_SMBUS_MASTER_FSM 0x100 + + /* SMBus master GW control bits offset in MLXBF_I2C_SMBUS_MASTER_GW[31:3]. */ + #define MLXBF_I2C_MASTER_LOCK_BIT BIT(31) /* Lock bit. */ +@@ -237,14 +230,14 @@ static u64 mlxbf_i2c_corepll_frequency; + #define MLXBF_I2C_MASTER_ENABLE_READ \ + (MLXBF_I2C_MASTER_ENABLE | MLXBF_I2C_MASTER_CTL_READ_BIT) + +-#define MLXBF_I2C_MASTER_SLV_ADDR_SHIFT 12 /* Slave address shift. */ +-#define MLXBF_I2C_MASTER_WRITE_SHIFT 21 /* Control write bytes shift. */ +-#define MLXBF_I2C_MASTER_SEND_PEC_SHIFT 20 /* Send PEC byte shift. */ +-#define MLXBF_I2C_MASTER_PARSE_EXP_SHIFT 11 /* Parse expected bytes shift. */ +-#define MLXBF_I2C_MASTER_READ_SHIFT 4 /* Control read bytes shift. */ ++#define MLXBF_I2C_MASTER_WRITE_SHIFT 21 /* Control write bytes */ ++#define MLXBF_I2C_MASTER_SEND_PEC_SHIFT 20 /* Send PEC byte when set to 1 */ ++#define MLXBF_I2C_MASTER_PARSE_EXP_SHIFT 11 /* Control parse expected bytes */ ++#define MLXBF_I2C_MASTER_SLV_ADDR_SHIFT 12 /* Slave address */ ++#define MLXBF_I2C_MASTER_READ_SHIFT 4 /* Control read bytes */ + + /* SMBus master GW Data descriptor. */ +-#define MLXBF_I2C_MASTER_DATA_DESC_ADDR 0x280 ++#define MLXBF_I2C_MASTER_DATA_DESC_ADDR 0x80 + #define MLXBF_I2C_MASTER_DATA_DESC_SIZE 0x80 /* Size in bytes. */ + + /* Maximum bytes to read/write per SMBus transaction. */ +@@ -270,19 +263,21 @@ static u64 mlxbf_i2c_corepll_frequency; + #define MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK BIT(31) + #define MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK BIT(15) + ++#define MLXBF_I2C_SLV_ADDR_OFFSET 0x400 ++ + /* SMBus slave GW. */ +-#define MLXBF_I2C_SMBUS_SLAVE_GW 0x400 ++#define MLXBF_I2C_SMBUS_SLAVE_GW 0x0 + /* Number of bytes received and sent from/to master. */ +-#define MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES 0x500 ++#define MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES 0x100 + /* Packet error check (PEC) value. */ +-#define MLXBF_I2C_SMBUS_SLAVE_PEC 0x504 ++#define MLXBF_I2C_SMBUS_SLAVE_PEC 0x104 + /* SMBus slave Finite State Machine (FSM). */ +-#define MLXBF_I2C_SMBUS_SLAVE_FSM 0x510 ++#define MLXBF_I2C_SMBUS_SLAVE_FSM 0x110 + /* + * Should be set when all raised causes handled, and cleared by HW on + * every new cause. + */ +-#define MLXBF_I2C_SMBUS_SLAVE_READY 0x52c ++#define MLXBF_I2C_SMBUS_SLAVE_READY 0x12c + + /* SMBus slave GW control bits offset in MLXBF_I2C_SMBUS_SLAVE_GW[31:19]. */ + #define MLXBF_I2C_SLAVE_BUSY_BIT BIT(30) /* Busy bit. */ +@@ -295,13 +290,13 @@ static u64 mlxbf_i2c_corepll_frequency; + #define MLXBF_I2C_SLAVE_SEND_PEC_SHIFT 21 /* Send PEC byte shift. */ + + /* SMBus slave GW Data descriptor. */ +-#define MLXBF_I2C_SLAVE_DATA_DESC_ADDR 0x480 ++#define MLXBF_I2C_SLAVE_DATA_DESC_ADDR 0x80 + #define MLXBF_I2C_SLAVE_DATA_DESC_SIZE 0x80 /* Size in bytes. */ + + /* SMbus slave configuration registers. */ +-#define MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG 0x514 ++#define MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG 0x114 + #define MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT 16 +-#define MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT 7 ++#define MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT BIT(7) + #define MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK GENMASK(6, 0) + + /* +@@ -311,6 +306,59 @@ static u64 mlxbf_i2c_corepll_frequency; + #define MLXBF_I2C_SMBUS_TIMEOUT (300 * 1000) /* 300ms */ + #define MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT (300 * 1000) /* 300ms */ + ++/* Polling frequency in microseconds. */ ++#define MLXBF_I2C_POLL_FREQ_IN_USEC 200 ++ ++#define MLXBF_I2C_SMBUS_OP_CNT_1 1 ++#define MLXBF_I2C_SMBUS_OP_CNT_2 2 ++#define MLXBF_I2C_SMBUS_OP_CNT_3 3 ++#define MLXBF_I2C_SMBUS_MAX_OP_CNT MLXBF_I2C_SMBUS_OP_CNT_3 ++ ++/* Helper macro to define an I2C resource parameters. */ ++#define MLXBF_I2C_RES_PARAMS(addr, size, str) \ ++ { \ ++ .start = (addr), \ ++ .end = (addr) + (size) - 1, \ ++ .name = (str) \ ++ } ++ ++enum { ++ MLXBF_I2C_TIMING_100KHZ = 100000, ++ MLXBF_I2C_TIMING_400KHZ = 400000, ++ MLXBF_I2C_TIMING_1000KHZ = 1000000, ++}; ++ ++enum { ++ MLXBF_I2C_F_READ = BIT(0), ++ MLXBF_I2C_F_WRITE = BIT(1), ++ MLXBF_I2C_F_NORESTART = BIT(3), ++ MLXBF_I2C_F_SMBUS_OPERATION = BIT(4), ++ MLXBF_I2C_F_SMBUS_BLOCK = BIT(5), ++ MLXBF_I2C_F_SMBUS_PEC = BIT(6), ++ MLXBF_I2C_F_SMBUS_PROCESS_CALL = BIT(7), ++}; ++ ++/* Mellanox BlueField chip type. */ ++enum mlxbf_i2c_chip_type { ++ MLXBF_I2C_CHIP_TYPE_1, /* Mellanox BlueField-1 chip. */ ++ MLXBF_I2C_CHIP_TYPE_2, /* Mellanox BlueField-2 chip. */ ++ MLXBF_I2C_CHIP_TYPE_3 /* Mellanox BlueField-3 chip. */ ++}; ++ ++/* List of chip resources that are being accessed by the driver. */ ++enum { ++ MLXBF_I2C_SMBUS_RES, ++ MLXBF_I2C_MST_CAUSE_RES, ++ MLXBF_I2C_SLV_CAUSE_RES, ++ MLXBF_I2C_COALESCE_RES, ++ MLXBF_I2C_SMBUS_TIMER_RES, ++ MLXBF_I2C_SMBUS_MST_RES, ++ MLXBF_I2C_SMBUS_SLV_RES, ++ MLXBF_I2C_COREPLL_RES, ++ MLXBF_I2C_GPIO_RES, ++ MLXBF_I2C_END_RES ++}; ++ + /* Encapsulates timing parameters. */ + struct mlxbf_i2c_timings { + u16 scl_high; /* Clock high period. */ +@@ -330,27 +378,12 @@ struct mlxbf_i2c_timings { + u32 timeout; /* Detect clock low timeout. */ + }; + +-enum { +- MLXBF_I2C_F_READ = BIT(0), +- MLXBF_I2C_F_WRITE = BIT(1), +- MLXBF_I2C_F_NORESTART = BIT(3), +- MLXBF_I2C_F_SMBUS_OPERATION = BIT(4), +- MLXBF_I2C_F_SMBUS_BLOCK = BIT(5), +- MLXBF_I2C_F_SMBUS_PEC = BIT(6), +- MLXBF_I2C_F_SMBUS_PROCESS_CALL = BIT(7), +-}; +- + struct mlxbf_i2c_smbus_operation { + u32 flags; + u32 length; /* Buffer length in bytes. */ + u8 *buffer; + }; + +-#define MLXBF_I2C_SMBUS_OP_CNT_1 1 +-#define MLXBF_I2C_SMBUS_OP_CNT_2 2 +-#define MLXBF_I2C_SMBUS_OP_CNT_3 3 +-#define MLXBF_I2C_SMBUS_MAX_OP_CNT MLXBF_I2C_SMBUS_OP_CNT_3 +- + struct mlxbf_i2c_smbus_request { + u8 slave; + u8 operation_cnt; +@@ -364,24 +397,38 @@ struct mlxbf_i2c_resource { + u8 type; + }; + +-/* List of chip resources that are being accessed by the driver. */ +-enum { +- MLXBF_I2C_SMBUS_RES, +- MLXBF_I2C_MST_CAUSE_RES, +- MLXBF_I2C_SLV_CAUSE_RES, +- MLXBF_I2C_COALESCE_RES, +- MLXBF_I2C_COREPLL_RES, +- MLXBF_I2C_GPIO_RES, +- MLXBF_I2C_END_RES, ++struct mlxbf_i2c_chip_info { ++ enum mlxbf_i2c_chip_type type; ++ /* Chip shared resources that are being used by the I2C controller. */ ++ struct mlxbf_i2c_resource *shared_res[MLXBF_I2C_SHARED_RES_MAX]; ++ ++ /* Callback to calculate the core PLL frequency. */ ++ u64 (*calculate_freq)(struct mlxbf_i2c_resource *corepll_res); ++ ++ /* Registers' address offset */ ++ u32 smbus_master_rs_bytes_off; ++ u32 smbus_master_fsm_off; + }; + +-/* Helper macro to define an I2C resource parameters. */ +-#define MLXBF_I2C_RES_PARAMS(addr, size, str) \ +- { \ +- .start = (addr), \ +- .end = (addr) + (size) - 1, \ +- .name = (str) \ +- } ++struct mlxbf_i2c_priv { ++ const struct mlxbf_i2c_chip_info *chip; ++ struct i2c_adapter adap; ++ struct mlxbf_i2c_resource *smbus; ++ struct mlxbf_i2c_resource *timer; ++ struct mlxbf_i2c_resource *mst; ++ struct mlxbf_i2c_resource *slv; ++ struct mlxbf_i2c_resource *mst_cause; ++ struct mlxbf_i2c_resource *slv_cause; ++ struct mlxbf_i2c_resource *coalesce; ++ u64 frequency; /* Core frequency in Hz. */ ++ int bus; /* Physical bus identifier. */ ++ int irq; ++ struct i2c_client *slave[MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT]; ++ u32 resource_version; ++}; ++ ++/* Core PLL frequency. */ ++static u64 mlxbf_i2c_corepll_frequency; + + static struct resource mlxbf_i2c_coalesce_tyu_params = + MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COALESCE_TYU_ADDR, +@@ -395,6 +442,10 @@ static struct resource mlxbf_i2c_corepll_yu_params = + MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COREPLL_YU_ADDR, + MLXBF_I2C_COREPLL_YU_SIZE, + "COREPLL_MEM"); ++static struct resource mlxbf_i2c_corepll_rsh_yu_params = ++ MLXBF_I2C_RES_PARAMS(MLXBF_I2C_COREPLL_RSH_YU_ADDR, ++ MLXBF_I2C_COREPLL_RSH_YU_SIZE, ++ "COREPLL_MEM"); + static struct resource mlxbf_i2c_gpio_tyu_params = + MLXBF_I2C_RES_PARAMS(MLXBF_I2C_GPIO_TYU_ADDR, + MLXBF_I2C_GPIO_TYU_SIZE, +@@ -404,34 +455,6 @@ static struct mutex mlxbf_i2c_coalesce_lock; + static struct mutex mlxbf_i2c_corepll_lock; + static struct mutex mlxbf_i2c_gpio_lock; + +-/* Mellanox BlueField chip type. */ +-enum mlxbf_i2c_chip_type { +- MLXBF_I2C_CHIP_TYPE_1, /* Mellanox BlueField-1 chip. */ +- MLXBF_I2C_CHIP_TYPE_2, /* Mallanox BlueField-2 chip. */ +-}; +- +-struct mlxbf_i2c_chip_info { +- enum mlxbf_i2c_chip_type type; +- /* Chip shared resources that are being used by the I2C controller. */ +- struct mlxbf_i2c_resource *shared_res[MLXBF_I2C_SHARED_RES_MAX]; +- +- /* Callback to calculate the core PLL frequency. */ +- u64 (*calculate_freq)(struct mlxbf_i2c_resource *corepll_res); +-}; +- +-struct mlxbf_i2c_priv { +- const struct mlxbf_i2c_chip_info *chip; +- struct i2c_adapter adap; +- struct mlxbf_i2c_resource *smbus; +- struct mlxbf_i2c_resource *mst_cause; +- struct mlxbf_i2c_resource *slv_cause; +- struct mlxbf_i2c_resource *coalesce; +- u64 frequency; /* Core frequency in Hz. */ +- int bus; /* Physical bus identifier. */ +- int irq; +- struct i2c_client *slave[MLXBF_I2C_SMBUS_SLAVE_ADDR_CNT]; +-}; +- + static struct mlxbf_i2c_resource mlxbf_i2c_coalesce_res[] = { + [MLXBF_I2C_CHIP_TYPE_1] = { + .params = &mlxbf_i2c_coalesce_tyu_params, +@@ -451,6 +474,11 @@ static struct mlxbf_i2c_resource mlxbf_i2c_corepll_res[] = { + .params = &mlxbf_i2c_corepll_yu_params, + .lock = &mlxbf_i2c_corepll_lock, + .type = MLXBF_I2C_COREPLL_RES, ++ }, ++ [MLXBF_I2C_CHIP_TYPE_3] = { ++ .params = &mlxbf_i2c_corepll_rsh_yu_params, ++ .lock = &mlxbf_i2c_corepll_lock, ++ .type = MLXBF_I2C_COREPLL_RES, + } + }; + +@@ -467,24 +495,13 @@ static u8 mlxbf_i2c_bus_count; + + static struct mutex mlxbf_i2c_bus_lock; + +-/* Polling frequency in microseconds. */ +-#define MLXBF_I2C_POLL_FREQ_IN_USEC 200 +- +-#define MLXBF_I2C_SHIFT_0 0 +-#define MLXBF_I2C_SHIFT_8 8 +-#define MLXBF_I2C_SHIFT_16 16 +-#define MLXBF_I2C_SHIFT_24 24 +- +-#define MLXBF_I2C_MASK_8 GENMASK(7, 0) +-#define MLXBF_I2C_MASK_16 GENMASK(15, 0) +- + /* + * Function to poll a set of bits at a specific address; it checks whether + * the bits are equal to zero when eq_zero is set to 'true', and not equal + * to zero when eq_zero is set to 'false'. + * Note that the timeout is given in microseconds. + */ +-static u32 mlxbf_smbus_poll(void __iomem *io, u32 addr, u32 mask, ++static u32 mlxbf_i2c_poll(void __iomem *io, u32 addr, u32 mask, + bool eq_zero, u32 timeout) + { + u32 bits; +@@ -506,13 +523,13 @@ static u32 mlxbf_smbus_poll(void __iomem *io, u32 addr, u32 mask, + * a transaction. Accordingly, this function polls the Master FSM stop + * bit; it returns false when the bit is asserted, true if not. + */ +-static bool mlxbf_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv) ++static bool mlxbf_i2c_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv) + { + u32 mask = MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK; +- u32 addr = MLXBF_I2C_SMBUS_MASTER_FSM; ++ u32 addr = priv->chip->smbus_master_fsm_off; + u32 timeout = MLXBF_I2C_SMBUS_TIMEOUT; + +- if (mlxbf_smbus_poll(priv->smbus->io, addr, mask, true, timeout)) ++ if (mlxbf_i2c_poll(priv->mst->io, addr, mask, true, timeout)) + return true; + + return false; +@@ -523,7 +540,7 @@ static bool mlxbf_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv) + */ + static bool mlxbf_i2c_smbus_master_lock(struct mlxbf_i2c_priv *priv) + { +- if (mlxbf_smbus_poll(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW, ++ if (mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW, + MLXBF_I2C_MASTER_LOCK_BIT, true, + MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT)) + return true; +@@ -534,7 +551,7 @@ static bool mlxbf_i2c_smbus_master_lock(struct mlxbf_i2c_priv *priv) + static void mlxbf_i2c_smbus_master_unlock(struct mlxbf_i2c_priv *priv) + { + /* Clear the gw to clear the lock */ +- writel(0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_GW); ++ writel(0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW); + } + + static bool mlxbf_i2c_smbus_transaction_success(u32 master_status, +@@ -574,7 +591,7 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) + * then read the cause and master status bits to determine if + * errors occurred during the transaction. + */ +- mlxbf_smbus_poll(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW, ++ mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW, + MLXBF_I2C_MASTER_BUSY_BIT, true, + MLXBF_I2C_SMBUS_TIMEOUT); + +@@ -587,7 +604,7 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) + * Parse both Cause and Master GW bits, then return transaction status. + */ + +- master_status_bits = readl(priv->smbus->io + ++ master_status_bits = readl(priv->mst->io + + MLXBF_I2C_SMBUS_MASTER_STATUS); + master_status_bits &= MLXBF_I2C_SMBUS_MASTER_STATUS_MASK; + +@@ -612,7 +629,8 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) + } + + static void mlxbf_i2c_smbus_write_data(struct mlxbf_i2c_priv *priv, +- const u8 *data, u8 length, u32 addr) ++ const u8 *data, u8 length, u32 addr, ++ bool is_master) + { + u8 offset, aligned_length; + u32 data32; +@@ -629,12 +647,16 @@ static void mlxbf_i2c_smbus_write_data(struct mlxbf_i2c_priv *priv, + */ + for (offset = 0; offset < aligned_length; offset += sizeof(u32)) { + data32 = *((u32 *)(data + offset)); +- iowrite32be(data32, priv->smbus->io + addr + offset); ++ if (is_master) ++ iowrite32be(data32, priv->mst->io + addr + offset); ++ else ++ iowrite32be(data32, priv->slv->io + addr + offset); + } + } + + static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv, +- u8 *data, u8 length, u32 addr) ++ u8 *data, u8 length, u32 addr, ++ bool is_master) + { + u32 data32, mask; + u8 byte, offset; +@@ -650,14 +672,20 @@ static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv, + */ + + for (offset = 0; offset < (length & ~mask); offset += sizeof(u32)) { +- data32 = ioread32be(priv->smbus->io + addr + offset); ++ if (is_master) ++ data32 = ioread32be(priv->mst->io + addr + offset); ++ else ++ data32 = ioread32be(priv->slv->io + addr + offset); + *((u32 *)(data + offset)) = data32; + } + + if (!(length & mask)) + return; + +- data32 = ioread32be(priv->smbus->io + addr + offset); ++ if (is_master) ++ data32 = ioread32be(priv->mst->io + addr + offset); ++ else ++ data32 = ioread32be(priv->slv->io + addr + offset); + + for (byte = 0; byte < (length & mask); byte++) { + data[offset + byte] = data32 & GENMASK(7, 0); +@@ -683,16 +711,16 @@ static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave, + command |= rol32(pec_en, MLXBF_I2C_MASTER_SEND_PEC_SHIFT); + + /* Clear status bits. */ +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_STATUS); ++ writel(0x0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_STATUS); + /* Set the cause data. */ + writel(~0x0, priv->mst_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR); + /* Zero PEC byte. */ +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_PEC); ++ writel(0x0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_PEC); + /* Zero byte count. */ +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_RS_BYTES); ++ writel(0x0, priv->mst->io + priv->chip->smbus_master_rs_bytes_off); + + /* GW activation. */ +- writel(command, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_GW); ++ writel(command, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW); + + /* + * Poll master status and check status bits. An ACK is sent when +@@ -736,7 +764,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + return -EBUSY; + + /* Check whether the HW is idle */ +- if (WARN_ON(!mlxbf_smbus_master_wait_for_idle(priv))) { ++ if (WARN_ON(!mlxbf_i2c_smbus_master_wait_for_idle(priv))) { + ret = -EBUSY; + goto out_unlock; + } +@@ -793,7 +821,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + * must be written to the data registers. + */ + mlxbf_i2c_smbus_write_data(priv, (const u8 *)data_desc, data_len, +- MLXBF_I2C_MASTER_DATA_DESC_ADDR); ++ MLXBF_I2C_MASTER_DATA_DESC_ADDR, true); + + if (write_en) { + ret = mlxbf_i2c_smbus_enable(priv, slave, write_len, block_en, +@@ -805,13 +833,13 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + if (read_en) { + /* Write slave address to Master GW data descriptor. */ + mlxbf_i2c_smbus_write_data(priv, (const u8 *)&addr, 1, +- MLXBF_I2C_MASTER_DATA_DESC_ADDR); ++ MLXBF_I2C_MASTER_DATA_DESC_ADDR, true); + ret = mlxbf_i2c_smbus_enable(priv, slave, read_len, block_en, + pec_en, 1); + if (!ret) { + /* Get Master GW data descriptor. */ + mlxbf_i2c_smbus_read_data(priv, data_desc, read_len + 1, +- MLXBF_I2C_MASTER_DATA_DESC_ADDR); ++ MLXBF_I2C_MASTER_DATA_DESC_ADDR, true); + + /* Get data from Master GW data descriptor. */ + memcpy(read_buf, data_desc, read_len + 1); +@@ -823,7 +851,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + * next tag integration. + */ + writel(MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK, +- priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_FSM); ++ priv->mst->io + priv->chip->smbus_master_fsm_off); + } + + out_unlock: +@@ -1115,7 +1143,7 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv, + timer |= mlxbf_i2c_set_timer(priv, timings->scl_low, + false, MLXBF_I2C_MASK_16, + MLXBF_I2C_SHIFT_16); +- writel(timer, priv->smbus->io + ++ writel(timer, priv->timer->io + + MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH); + + timer = mlxbf_i2c_set_timer(priv, timings->sda_rise, false, +@@ -1126,34 +1154,34 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv, + MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_16); + timer |= mlxbf_i2c_set_timer(priv, timings->scl_fall, false, + MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_24); +- writel(timer, priv->smbus->io + ++ writel(timer, priv->timer->io + + MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE); + + timer = mlxbf_i2c_set_timer(priv, timings->hold_start, true, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0); + timer |= mlxbf_i2c_set_timer(priv, timings->hold_data, true, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); +- writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_THOLD); ++ writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_TIMER_THOLD); + + timer = mlxbf_i2c_set_timer(priv, timings->setup_start, true, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0); + timer |= mlxbf_i2c_set_timer(priv, timings->setup_stop, true, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); +- writel(timer, priv->smbus->io + ++ writel(timer, priv->timer->io + + MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP); + + timer = mlxbf_i2c_set_timer(priv, timings->setup_data, true, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0); +- writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA); ++ writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA); + + timer = mlxbf_i2c_set_timer(priv, timings->buf, false, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0); + timer |= mlxbf_i2c_set_timer(priv, timings->thigh_max, false, + MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); +- writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF); ++ writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF); + + timer = timings->timeout; +- writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT); ++ writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT); + } + + enum mlxbf_i2c_timings_config { +@@ -1565,7 +1593,7 @@ static int mlxbf_i2c_slave_enable(struct mlxbf_i2c_priv *priv, + * Look for the next available slave register slot. + */ + for (reg = 0; reg < reg_cnt; reg++) { +- slave_reg = readl(priv->smbus->io + ++ slave_reg = readl(priv->slv->io + + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4); + /* + * Each register holds 4 slave addresses. So, we have to keep +@@ -1587,7 +1615,7 @@ static int mlxbf_i2c_slave_enable(struct mlxbf_i2c_priv *priv, + slave_reg &= ~(MLXBF_I2C_SMBUS_SLAVE_ADDR_MASK << (byte * 8)); + slave_reg |= (slave->addr << (byte * 8)); + slave_reg |= MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT << (byte * 8); +- writel(slave_reg, priv->smbus->io + ++ writel(slave_reg, priv->slv->io + + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + + (reg * 0x4)); + +@@ -1622,7 +1650,7 @@ static int mlxbf_i2c_slave_disable(struct mlxbf_i2c_priv *priv, u8 addr) + * Check if addr is present in the registers. + */ + for (reg = 0; reg < reg_cnt; reg++) { +- slave_reg = readl(priv->smbus->io + ++ slave_reg = readl(priv->slv->io + + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4); + + /* Check whether the address slots are empty. */ +@@ -1643,7 +1671,7 @@ static int mlxbf_i2c_slave_disable(struct mlxbf_i2c_priv *priv, u8 addr) + if (addr_tmp == addr) { + /* Clear the slave address slot. */ + slave_reg &= ~(GENMASK(7, 0) << (byte * 8)); +- writel(slave_reg, priv->smbus->io + ++ writel(slave_reg, priv->slv->io + + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + + (reg * 0x4)); + /* Free slave at the corresponding index */ +@@ -1747,7 +1775,7 @@ static int mlxbf_i2c_init_slave(struct platform_device *pdev, + int ret; + + /* Reset FSM. */ +- writel(0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_FSM); ++ writel(0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_FSM); + + /* + * Enable slave cause interrupt bits. Drive +@@ -1762,7 +1790,7 @@ static int mlxbf_i2c_init_slave(struct platform_device *pdev, + writel(int_reg, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_EVTEN0); + + /* Finally, set the 'ready' bit to start handling transactions. */ +- writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY); ++ writel(0x1, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_READY); + + /* Initialize the cause coalesce resource. */ + ret = mlxbf_i2c_init_coalesce(pdev, priv); +@@ -1807,13 +1835,13 @@ static bool mlxbf_i2c_has_coalesce(struct mlxbf_i2c_priv *priv, bool *read, + return true; + } + +-static bool mlxbf_smbus_slave_wait_for_idle(struct mlxbf_i2c_priv *priv, ++static bool mlxbf_i2c_slave_wait_for_idle(struct mlxbf_i2c_priv *priv, + u32 timeout) + { + u32 mask = MLXBF_I2C_CAUSE_S_GW_BUSY_FALL; + u32 addr = MLXBF_I2C_CAUSE_ARBITER; + +- if (mlxbf_smbus_poll(priv->slv_cause->io, addr, mask, false, timeout)) ++ if (mlxbf_i2c_poll(priv->slv_cause->io, addr, mask, false, timeout)) + return true; + + return false; +@@ -1852,7 +1880,7 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + * determine the slave address. This byte is located in the + * first data descriptor register of the slave GW. + */ +- data32 = ioread32be(priv->smbus->io + ++ data32 = ioread32be(priv->slv->io + + MLXBF_I2C_SLAVE_DATA_DESC_ADDR); + addr = (data32 & GENMASK(7, 0)) >> 1; + +@@ -1906,7 +1934,7 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + + /* Write data to Slave GW data descriptor. */ + mlxbf_i2c_smbus_write_data(priv, data_desc, byte_cnt, +- MLXBF_I2C_SLAVE_DATA_DESC_ADDR); ++ MLXBF_I2C_SLAVE_DATA_DESC_ADDR, false); + + pec_en = 0; /* Disable PEC since it is not supported. */ + +@@ -1915,19 +1943,19 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + control32 |= rol32(write_size, MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT); + control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT); + +- writel(control32, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_GW); ++ writel(control32, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_GW); + + /* + * Wait until the transfer is completed; the driver will wait + * until the GW is idle, a cause will rise on fall of GW busy. + */ +- mlxbf_smbus_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT); ++ mlxbf_i2c_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT); + + clear_csr: + /* Release the Slave GW. */ +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC); +- writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY); ++ writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); ++ writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_PEC); ++ writel(0x1, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_READY); + + return ret; + } +@@ -1945,7 +1973,7 @@ static int mlxbf_i2c_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + + /* Read data from Slave GW data descriptor. */ + mlxbf_i2c_smbus_read_data(priv, data_desc, recv_bytes, +- MLXBF_I2C_SLAVE_DATA_DESC_ADDR); ++ MLXBF_I2C_SLAVE_DATA_DESC_ADDR, false); + addr = data_desc[0] >> 1; + + /* +@@ -1981,9 +2009,9 @@ static int mlxbf_i2c_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes) + + clear_csr: + /* Release the Slave GW. */ +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); +- writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC); +- writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY); ++ writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); ++ writel(0x0, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_PEC); ++ writel(0x1, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_READY); + + return ret; + } +@@ -2018,7 +2046,7 @@ static irqreturn_t mlxbf_i2c_irq(int irq, void *ptr) + * slave, if the higher 8 bits are sent then the slave expect N bytes + * from the master. + */ +- rw_bytes_reg = readl(priv->smbus->io + ++ rw_bytes_reg = readl(priv->slv->io + + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); + recv_bytes = (rw_bytes_reg >> 8) & GENMASK(7, 0); + +@@ -2183,14 +2211,27 @@ static struct mlxbf_i2c_chip_info mlxbf_i2c_chip[] = { + [1] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_1], + [2] = &mlxbf_i2c_gpio_res[MLXBF_I2C_CHIP_TYPE_1] + }, +- .calculate_freq = mlxbf_i2c_calculate_freq_from_tyu ++ .calculate_freq = mlxbf_i2c_calculate_freq_from_tyu, ++ .smbus_master_rs_bytes_off = MLXBF_I2C_YU_SMBUS_RS_BYTES, ++ .smbus_master_fsm_off = MLXBF_I2C_YU_SMBUS_MASTER_FSM + }, + [MLXBF_I2C_CHIP_TYPE_2] = { + .type = MLXBF_I2C_CHIP_TYPE_2, + .shared_res = { + [0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_2] + }, +- .calculate_freq = mlxbf_i2c_calculate_freq_from_yu ++ .calculate_freq = mlxbf_i2c_calculate_freq_from_yu, ++ .smbus_master_rs_bytes_off = MLXBF_I2C_YU_SMBUS_RS_BYTES, ++ .smbus_master_fsm_off = MLXBF_I2C_YU_SMBUS_MASTER_FSM ++ }, ++ [MLXBF_I2C_CHIP_TYPE_3] = { ++ .type = MLXBF_I2C_CHIP_TYPE_3, ++ .shared_res = { ++ [0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_3] ++ }, ++ .calculate_freq = mlxbf_i2c_calculate_freq_from_yu, ++ .smbus_master_rs_bytes_off = MLXBF_I2C_RSH_YU_SMBUS_RS_BYTES, ++ .smbus_master_fsm_off = MLXBF_I2C_RSH_YU_SMBUS_MASTER_FSM + } + }; + +@@ -2215,6 +2256,10 @@ static const struct of_device_id mlxbf_i2c_dt_ids[] = { + .compatible = "mellanox,i2c-mlxbf2", + .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] + }, ++ { ++ .compatible = "mellanox,i2c-mlxbf3", ++ .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_3] ++ }, + {}, + }; + +@@ -2224,6 +2269,7 @@ MODULE_DEVICE_TABLE(of, mlxbf_i2c_dt_ids); + static const struct acpi_device_id mlxbf_i2c_acpi_ids[] = { + { "MLNXBF03", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] }, + { "MLNXBF23", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] }, ++ { "MLNXBF31", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_3] }, + {}, + }; + +@@ -2299,6 +2345,7 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct mlxbf_i2c_priv *priv; + struct i2c_adapter *adap; ++ u32 resource_version; + int irq, ret; + + priv = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_priv), GFP_KERNEL); +@@ -2312,11 +2359,60 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) + if (ret < 0) + return ret; + +- ret = mlxbf_i2c_init_resource(pdev, &priv->smbus, +- MLXBF_I2C_SMBUS_RES); +- if (ret < 0) { +- dev_err(dev, "Cannot fetch smbus resource info"); +- return ret; ++ /* This property allows the driver to stay backward compatible with older ++ * ACPI table and device trees versions. ++ * Starting BlueField-3 SoC, the "smbus" resource was broken down into 3 ++ * separate resources "timer", "master" and "slave". ++ */ ++ if (device_property_read_u32(dev, "resource_version", &resource_version)) ++ resource_version = 0; ++ ++ priv->resource_version = resource_version; ++ ++ if (priv->chip->type < MLXBF_I2C_CHIP_TYPE_3 && resource_version == 0) { ++ priv->timer = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource), GFP_KERNEL); ++ if (!priv->timer) ++ return -ENOMEM; ++ ++ priv->mst = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource), GFP_KERNEL); ++ if (!priv->mst) ++ return -ENOMEM; ++ ++ priv->slv = devm_kzalloc(dev, sizeof(struct mlxbf_i2c_resource), GFP_KERNEL); ++ if (!priv->slv) ++ return -ENOMEM; ++ ++ ret = mlxbf_i2c_init_resource(pdev, &priv->smbus, ++ MLXBF_I2C_SMBUS_RES); ++ if (ret < 0) { ++ dev_err(dev, "Cannot fetch smbus resource info"); ++ return ret; ++ } ++ ++ priv->timer->io = priv->smbus->io; ++ priv->mst->io = priv->smbus->io + MLXBF_I2C_MST_ADDR_OFFSET; ++ priv->slv->io = priv->smbus->io + MLXBF_I2C_SLV_ADDR_OFFSET; ++ } else { ++ ret = mlxbf_i2c_init_resource(pdev, &priv->timer, ++ MLXBF_I2C_SMBUS_TIMER_RES); ++ if (ret < 0) { ++ dev_err(dev, "Cannot fetch timer resource info"); ++ return ret; ++ } ++ ++ ret = mlxbf_i2c_init_resource(pdev, &priv->mst, ++ MLXBF_I2C_SMBUS_MST_RES); ++ if (ret < 0) { ++ dev_err(dev, "Cannot fetch master resource info"); ++ return ret; ++ } ++ ++ ret = mlxbf_i2c_init_resource(pdev, &priv->slv, ++ MLXBF_I2C_SMBUS_SLV_RES); ++ if (ret < 0) { ++ dev_err(dev, "Cannot fetch slave resource info"); ++ return ret; ++ } + } + + ret = mlxbf_i2c_init_resource(pdev, &priv->mst_cause, +@@ -2404,8 +2500,19 @@ static int mlxbf_i2c_remove(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct resource *params; + +- params = priv->smbus->params; +- devm_release_mem_region(dev, params->start, resource_size(params)); ++ if (priv->chip->type < MLXBF_I2C_CHIP_TYPE_3 && priv->resource_version == 0) { ++ params = priv->smbus->params; ++ devm_release_mem_region(dev, params->start, resource_size(params)); ++ } else { ++ params = priv->timer->params; ++ devm_release_mem_region(dev, params->start, resource_size(params)); ++ ++ params = priv->mst->params; ++ devm_release_mem_region(dev, params->start, resource_size(params)); ++ ++ params = priv->slv->params; ++ devm_release_mem_region(dev, params->start, resource_size(params)); ++ } + + params = priv->mst_cause->params; + devm_release_mem_region(dev, params->start, resource_size(params)); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0208-i2c-mlxbf-remove-device-tree-support.patch b/platform/mellanox/non-upstream-patches/patches/0208-i2c-mlxbf-remove-device-tree-support.patch new file mode 100644 index 0000000000..c2642e7a90 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0208-i2c-mlxbf-remove-device-tree-support.patch @@ -0,0 +1,211 @@ +From e2f59de3801d0899bb4622079b2d927aaf2404b7 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Tue, 27 Sep 2022 16:39:24 -0400 +Subject: [PATCH backport 5.10 09/63] i2c: mlxbf: remove device tree support + +BugLink: https://bugs.launchpad.net/bugs/1991551 + +BlueField customers have to use the BlueField firmware with +UEFI ACPI tables so there is no need to have device tree +support in the i2c-mlxbf.c driver. Remove the device tree +binding documentation as well. + +Signed-off-by: Asmaa Mnebhi +Reviewed-by: Khalil Blaiech +Signed-off-by: Wolfram Sang +(cherry picked from commit be18c5ede25da39a0eda541f6de3620a30cf731f) +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + .../bindings/i2c/mellanox,i2c-mlxbf.yaml | 78 ------------------- + MAINTAINERS | 1 - + drivers/i2c/busses/i2c-mlxbf.c | 49 +----------- + 3 files changed, 1 insertion(+), 127 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml + +diff --git a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml +deleted file mode 100644 +index d2b401d06..000000000 +--- a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml ++++ /dev/null +@@ -1,78 +0,0 @@ +-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +-%YAML 1.2 +---- +-$id: http://devicetree.org/schemas/i2c/mellanox,i2c-mlxbf.yaml# +-$schema: http://devicetree.org/meta-schemas/core.yaml# +- +-title: Mellanox I2C SMBus on BlueField SoCs +- +-maintainers: +- - Khalil Blaiech +- +-allOf: +- - $ref: /schemas/i2c/i2c-controller.yaml# +- +-properties: +- compatible: +- enum: +- - mellanox,i2c-mlxbf1 +- - mellanox,i2c-mlxbf2 +- +- reg: +- minItems: 3 +- maxItems: 4 +- items: +- - description: Smbus block registers +- - description: Cause master registers +- - description: Cause slave registers +- - description: Cause coalesce registers +- +- interrupts: +- maxItems: 1 +- +- clock-frequency: +- enum: [ 100000, 400000, 1000000 ] +- description: +- bus frequency used to configure timing registers; +- The frequency is expressed in Hz. Default is 100000. +- +-required: +- - compatible +- - reg +- - interrupts +- +-unevaluatedProperties: false +- +-if: +- properties: +- compatible: +- contains: +- enum: +- - mellanox,i2c-mlxbf1 +- +-then: +- properties: +- reg: +- maxItems: 3 +- +-examples: +- - | +- i2c@2804000 { +- compatible = "mellanox,i2c-mlxbf1"; +- reg = <0x02804000 0x800>, +- <0x02801200 0x020>, +- <0x02801260 0x020>; +- interrupts = <57>; +- clock-frequency = <100000>; +- }; +- +- - | +- i2c@2808800 { +- compatible = "mellanox,i2c-mlxbf2"; +- reg = <0x02808800 0x600>, +- <0x02808e00 0x020>, +- <0x02808e20 0x020>, +- <0x02808e40 0x010>; +- interrupts = <57>; +- clock-frequency = <400000>; +- }; +diff --git a/MAINTAINERS b/MAINTAINERS +index f6a974ade..1d43cd482 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -11178,7 +11178,6 @@ M: Khalil Blaiech + M: Asmaa Mnebhi + L: linux-i2c@vger.kernel.org + S: Supported +-F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml + F: drivers/i2c/busses/i2c-mlxbf.c + + MELLANOX ETHERNET DRIVER (mlx4_en) +diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c +index 75d8d00d1..67548702f 100644 +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -2247,24 +2247,6 @@ static struct i2c_adapter_quirks mlxbf_i2c_quirks = { + .max_write_len = MLXBF_I2C_MASTER_DATA_W_LENGTH, + }; + +-static const struct of_device_id mlxbf_i2c_dt_ids[] = { +- { +- .compatible = "mellanox,i2c-mlxbf1", +- .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] +- }, +- { +- .compatible = "mellanox,i2c-mlxbf2", +- .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] +- }, +- { +- .compatible = "mellanox,i2c-mlxbf3", +- .data = &mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_3] +- }, +- {}, +-}; +- +-MODULE_DEVICE_TABLE(of, mlxbf_i2c_dt_ids); +- + #ifdef CONFIG_ACPI + static const struct acpi_device_id mlxbf_i2c_acpi_ids[] = { + { "MLNXBF03", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] }, +@@ -2315,31 +2297,6 @@ static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv) + } + #endif /* CONFIG_ACPI */ + +-static int mlxbf_i2c_of_probe(struct device *dev, struct mlxbf_i2c_priv *priv) +-{ +- const struct of_device_id *oid; +- int bus_id = -1; +- +- if (IS_ENABLED(CONFIG_OF) && dev->of_node) { +- oid = of_match_node(mlxbf_i2c_dt_ids, dev->of_node); +- if (!oid) +- return -ENODEV; +- +- priv->chip = oid->data; +- +- bus_id = of_alias_get_id(dev->of_node, "i2c"); +- if (bus_id >= 0) +- priv->bus = bus_id; +- } +- +- if (bus_id < 0) { +- dev_err(dev, "Cannot get bus id"); +- return bus_id; +- } +- +- return 0; +-} +- + static int mlxbf_i2c_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -2353,14 +2310,11 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) + return -ENOMEM; + + ret = mlxbf_i2c_acpi_probe(dev, priv); +- if (ret < 0 && ret != -ENOENT && ret != -ENXIO) +- ret = mlxbf_i2c_of_probe(dev, priv); +- + if (ret < 0) + return ret; + + /* This property allows the driver to stay backward compatible with older +- * ACPI table and device trees versions. ++ * ACPI tables. + * Starting BlueField-3 SoC, the "smbus" resource was broken down into 3 + * separate resources "timer", "master" and "slave". + */ +@@ -2544,7 +2498,6 @@ static struct platform_driver mlxbf_i2c_driver = { + .remove = mlxbf_i2c_remove, + .driver = { + .name = "i2c-mlxbf", +- .of_match_table = mlxbf_i2c_dt_ids, + #ifdef CONFIG_ACPI + .acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids), + #endif /* CONFIG_ACPI */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0209-UBUNTU-SAUCE-i2c-mlxbf.c-Add-driver-version.patch b/platform/mellanox/non-upstream-patches/patches/0209-UBUNTU-SAUCE-i2c-mlxbf.c-Add-driver-version.patch new file mode 100644 index 0000000000..50e96af71c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0209-UBUNTU-SAUCE-i2c-mlxbf.c-Add-driver-version.patch @@ -0,0 +1,37 @@ +From c78abc95294213920e386abb941df6e23ba1ede3 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Tue, 11 Oct 2022 14:28:57 -0400 +Subject: [PATCH backport 5.10 10/63] UBUNTU: SAUCE: i2c-mlxbf.c: Add driver + version + +BugLink: https://bugs.launchpad.net/bugs/1991551 + +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/i2c/busses/i2c-mlxbf.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c +index 67548702f..0eb92bbc1 100644 +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -19,6 +19,8 @@ + #include + #include + ++#define DRV_VERSION "3.2" ++ + /* Defines what functionality is present. */ + #define MLXBF_I2C_FUNC_SMBUS_BLOCK \ + (I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL) +@@ -2532,3 +2534,4 @@ MODULE_DESCRIPTION("Mellanox BlueField I2C bus driver"); + MODULE_AUTHOR("Khalil Blaiech "); + MODULE_AUTHOR("Asmaa Mnebhi "); + MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRV_VERSION); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0210-platform-mellanox-Typo-fix-in-the-file-mlxbf-bootctl.patch b/platform/mellanox/non-upstream-patches/patches/0210-platform-mellanox-Typo-fix-in-the-file-mlxbf-bootctl.patch new file mode 100644 index 0000000000..43b606c269 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0210-platform-mellanox-Typo-fix-in-the-file-mlxbf-bootctl.patch @@ -0,0 +1,32 @@ +From 4c700c6b83fa8bf6347537279a0a5134d09cf004 Mon Sep 17 00:00:00 2001 +From: Bhaskar Chowdhury +Date: Wed, 17 Mar 2021 15:26:50 +0530 +Subject: [PATCH backport 5.10 11/63] platform/mellanox: Typo fix in the file + mlxbf-bootctl.c + +s/progamming/programming/ + +Signed-off-by: Bhaskar Chowdhury +Acked-by: Randy Dunlap +Link: https://lore.kernel.org/r/20210317095650.2036419-1-unixbhaskar@gmail.com +Signed-off-by: Hans de Goede +--- + drivers/platform/mellanox/mlxbf-bootctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c +index 5d21c6adf..1c7a288b5 100644 +--- a/drivers/platform/mellanox/mlxbf-bootctl.c ++++ b/drivers/platform/mellanox/mlxbf-bootctl.c +@@ -208,7 +208,7 @@ static ssize_t secure_boot_fuse_state_show(struct device *dev, + * 0011 = version 1, 0111 = version 2, 1111 = version 3). Upper 4 bits + * are a thermometer code indicating key programming has completed for + * key n (same encodings as the start bits). This allows for detection +- * of an interruption in the progamming process which has left the key ++ * of an interruption in the programming process which has left the key + * partially programmed (and thus invalid). The process is to burn the + * eFuse for the new key start bit, burn the key eFuses, then burn the + * eFuse for the new key complete bit. +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0211-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-boot.patch b/platform/mellanox/non-upstream-patches/patches/0211-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-boot.patch new file mode 100644 index 0000000000..d2f8e5ef25 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0211-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-boot.patch @@ -0,0 +1,1719 @@ +From 988b360c98ef157e37818f5f7db322c129d3dfb9 Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Wed, 6 Jul 2022 07:37:22 -0400 +Subject: [PATCH backport 5.10 12/63] UBUNTU: SAUCE: platform/mellanox: Updates + to mlxbf-bootctl + +BugLink: https://launchpad.net/bugs/1980832 + +The driver supports the VPD fields in the EEPROM and exposes +sysfs files for configuring and reading the same. +Also address buffer overflow and exclusion issues. + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/mlxbf-bootctl.c | 1410 ++++++++++++++++++--- + drivers/platform/mellanox/mlxbf-bootctl.h | 88 +- + 2 files changed, 1268 insertions(+), 230 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c +index 1c7a288b5..2302e1e09 100644 +--- a/drivers/platform/mellanox/mlxbf-bootctl.c ++++ b/drivers/platform/mellanox/mlxbf-bootctl.c +@@ -1,51 +1,129 @@ +-// SPDX-License-Identifier: GPL-2.0+ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause + /* +- * Mellanox boot control driver ++ * Mellanox boot control driver ++ * This driver provides a sysfs interface for systems management ++ * software to manage reset-time actions. + * +- * This driver provides a sysfs interface for systems management +- * software to manage reset-time actions. ++ * Copyright (C) 2020 Mellanox Technologies. All rights reserved. + * +- * Copyright (C) 2019 Mellanox Technologies ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License v2.0 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. + */ + + #include + #include ++#include ++#include + #include + #include +- + #include "mlxbf-bootctl.h" + +-#define MLXBF_BOOTCTL_SB_SECURE_MASK 0x03 +-#define MLXBF_BOOTCTL_SB_TEST_MASK 0x0c ++#define DRIVER_NAME "mlxbf-bootctl" ++#define DRIVER_VERSION "1.5" ++#define DRIVER_DESCRIPTION "Mellanox boot control driver" ++ ++#define SB_MODE_SECURE_MASK 0x03 ++#define SB_MODE_TEST_MASK 0x0c ++#define SB_MODE_DEV_MASK 0x10 + +-#define MLXBF_SB_KEY_NUM 4 ++#define SB_KEY_NUM 4 ++ ++struct boot_name { ++ int value; ++ const char name[12]; ++}; + +-/* UUID used to probe ATF service. */ +-static const char *mlxbf_bootctl_svc_uuid_str = +- "89c036b4-e7d7-11e6-8797-001aca00bfc4"; ++static struct boot_name boot_names[] = { ++ { MLNX_BOOT_EXTERNAL, "external" }, ++ { MLNX_BOOT_EMMC, "emmc" }, ++ { MLNX_BOOT_SWAP_EMMC, "swap_emmc" }, ++ { MLNX_BOOT_EMMC_LEGACY, "emmc_legacy" }, ++ { MLNX_BOOT_NONE, "none" }, ++ { -1, "" } ++}; + +-struct mlxbf_bootctl_name { +- u32 value; +- const char *name; ++enum { ++ SB_LIFECYCLE_PRODUCTION = 0, ++ SB_LIFECYCLE_GA_SECURE = 1, ++ SB_LIFECYCLE_GA_NON_SECURE = 2, ++ SB_LIFECYCLE_RMA = 3 + }; + +-static struct mlxbf_bootctl_name boot_names[] = { +- { MLXBF_BOOTCTL_EXTERNAL, "external" }, +- { MLXBF_BOOTCTL_EMMC, "emmc" }, +- { MLNX_BOOTCTL_SWAP_EMMC, "swap_emmc" }, +- { MLXBF_BOOTCTL_EMMC_LEGACY, "emmc_legacy" }, +- { MLXBF_BOOTCTL_NONE, "none" }, ++static char lifecycle_states[][16] = { ++ [SB_LIFECYCLE_PRODUCTION] = "Production", ++ [SB_LIFECYCLE_GA_SECURE] = "GA Secured", ++ [SB_LIFECYCLE_GA_NON_SECURE] = "GA Non-Secured", ++ [SB_LIFECYCLE_RMA] = "RMA", + }; + +-static const char * const mlxbf_bootctl_lifecycle_states[] = { +- [0] = "Production", +- [1] = "GA Secured", +- [2] = "GA Non-Secured", +- [3] = "RMA", ++/* ctl/data register within the resource. */ ++#define RSH_SCRATCH_BUF_CTL_OFF 0 ++#define RSH_SCRATCH_BUF_DATA_OFF 0x10 ++ ++static void __iomem *rsh_boot_data; ++static void __iomem *rsh_boot_cnt; ++static void __iomem *rsh_semaphore; ++static void __iomem *rsh_scratch_buf_ctl; ++static void __iomem *rsh_scratch_buf_data; ++ ++static int rsh_log_clear_on_read; ++module_param(rsh_log_clear_on_read, int, 0644); ++MODULE_PARM_DESC(rsh_log_clear_on_read, "Clear rshim logging buffer after read."); ++ ++/* ++ * Objects are stored within the MFG partition per type. Type 0 is not ++ * supported. ++ */ ++enum { ++ MLNX_MFG_TYPE_OOB_MAC = 1, ++ MLNX_MFG_TYPE_OPN_0, ++ MLNX_MFG_TYPE_OPN_1, ++ MLNX_MFG_TYPE_OPN_2, ++ MLNX_MFG_TYPE_SKU_0, ++ MLNX_MFG_TYPE_SKU_1, ++ MLNX_MFG_TYPE_SKU_2, ++ MLNX_MFG_TYPE_MODL_0, ++ MLNX_MFG_TYPE_MODL_1, ++ MLNX_MFG_TYPE_MODL_2, ++ MLNX_MFG_TYPE_SN_0, ++ MLNX_MFG_TYPE_SN_1, ++ MLNX_MFG_TYPE_SN_2, ++ MLNX_MFG_TYPE_UUID_0, ++ MLNX_MFG_TYPE_UUID_1, ++ MLNX_MFG_TYPE_UUID_2, ++ MLNX_MFG_TYPE_UUID_3, ++ MLNX_MFG_TYPE_UUID_4, ++ MLNX_MFG_TYPE_REV, + }; + +-/* ARM SMC call which is atomic and no need for lock. */ +-static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg) ++/* This mutex is used to serialize MFG write and lock operations. */ ++static DEFINE_MUTEX(mfg_ops_lock); ++ ++#define MLNX_MFG_OOB_MAC_LEN ETH_ALEN ++#define MLNX_MFG_OPN_VAL_LEN 24 ++#define MLNX_MFG_SKU_VAL_LEN 24 ++#define MLNX_MFG_MODL_VAL_LEN 24 ++#define MLNX_MFG_SN_VAL_LEN 24 ++#define MLNX_MFG_UUID_VAL_LEN 40 ++#define MLNX_MFG_REV_VAL_LEN 8 ++#define MLNX_MFG_VAL_QWORD_CNT(type) \ ++ (MLNX_MFG_##type##_VAL_LEN / sizeof(u64)) ++ ++/* ++ * The MAC address consists of 6 bytes (2 digits each) separated by ':'. ++ * The expected format is: "XX:XX:XX:XX:XX:XX" ++ */ ++#define MLNX_MFG_OOB_MAC_FORMAT_LEN \ ++ ((MLNX_MFG_OOB_MAC_LEN * 2) + (MLNX_MFG_OOB_MAC_LEN - 1)) ++ ++/* The SMC calls in question are atomic, so we don't have to lock here. */ ++static int smc_call1(unsigned int smc_op, int smc_arg) + { + struct arm_smccc_res res; + +@@ -54,268 +132,1212 @@ static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg) + return res.a0; + } + +-/* Return the action in integer or an error code. */ +-static int mlxbf_bootctl_reset_action_to_val(const char *action) ++/* Syntactic sugar to avoid having to specify an unused argument. */ ++#define smc_call0(smc_op) smc_call1(smc_op, 0) ++ ++static int reset_action_to_val(const char *action, size_t len) + { +- int i; ++ struct boot_name *bn; ++ ++ /* Accept string either with or without a newline terminator */ ++ if (action[len-1] == '\n') ++ --len; + +- for (i = 0; i < ARRAY_SIZE(boot_names); i++) +- if (sysfs_streq(boot_names[i].name, action)) +- return boot_names[i].value; ++ for (bn = boot_names; bn->value >= 0; ++bn) ++ if (strncmp(bn->name, action, len) == 0) ++ break; + +- return -EINVAL; ++ return bn->value; + } + +-/* Return the action in string. */ +-static const char *mlxbf_bootctl_action_to_string(int action) ++static const char *reset_action_to_string(int action) + { +- int i; ++ struct boot_name *bn; + +- for (i = 0; i < ARRAY_SIZE(boot_names); i++) +- if (boot_names[i].value == action) +- return boot_names[i].name; ++ for (bn = boot_names; bn->value >= 0; ++bn) ++ if (bn->value == action) ++ break; + +- return "invalid action"; ++ return bn->name; + } + +-static ssize_t post_reset_wdog_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t post_reset_wdog_show(struct device_driver *drv, ++ char *buf) + { +- int ret; ++ return snprintf(buf, PAGE_SIZE, "%d\n", ++ smc_call0(MLNX_GET_POST_RESET_WDOG)); ++} + +- ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_POST_RESET_WDOG, 0); +- if (ret < 0) +- return ret; ++static ssize_t post_reset_wdog_store(struct device_driver *drv, ++ const char *buf, size_t count) ++{ ++ int err; ++ unsigned long watchdog; ++ ++ err = kstrtoul(buf, 10, &watchdog); ++ if (err) ++ return err; ++ ++ if (smc_call1(MLNX_SET_POST_RESET_WDOG, watchdog) < 0) ++ return -EINVAL; + +- return sprintf(buf, "%d\n", ret); ++ return count; + } + +-static ssize_t post_reset_wdog_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) ++static ssize_t reset_action_show(struct device_driver *drv, ++ char *buf) + { +- unsigned long value; +- int ret; ++ return snprintf(buf, PAGE_SIZE, "%s\n", reset_action_to_string( ++ smc_call0(MLNX_GET_RESET_ACTION))); ++} + +- ret = kstrtoul(buf, 10, &value); +- if (ret) +- return ret; ++static ssize_t reset_action_store(struct device_driver *drv, ++ const char *buf, size_t count) ++{ ++ int action = reset_action_to_val(buf, count); + +- ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_SET_POST_RESET_WDOG, value); +- if (ret < 0) +- return ret; ++ if (action < 0 || action == MLNX_BOOT_NONE) ++ return -EINVAL; ++ ++ if (smc_call1(MLNX_SET_RESET_ACTION, action) < 0) ++ return -EINVAL; + + return count; + } + +-static ssize_t mlxbf_bootctl_show(int smc_op, char *buf) ++static ssize_t second_reset_action_show(struct device_driver *drv, ++ char *buf) + { +- int action; ++ return snprintf(buf, PAGE_SIZE, "%s\n", reset_action_to_string( ++ smc_call0(MLNX_GET_SECOND_RESET_ACTION))); ++} ++ ++static ssize_t second_reset_action_store(struct device_driver *drv, ++ const char *buf, size_t count) ++{ ++ int action = reset_action_to_val(buf, count); + +- action = mlxbf_bootctl_smc(smc_op, 0); + if (action < 0) +- return action; ++ return -EINVAL; ++ ++ if (smc_call1(MLNX_SET_SECOND_RESET_ACTION, action) < 0) ++ return -EINVAL; + +- return sprintf(buf, "%s\n", mlxbf_bootctl_action_to_string(action)); ++ return count; + } + +-static int mlxbf_bootctl_store(int smc_op, const char *buf, size_t count) ++static ssize_t lifecycle_state_show(struct device_driver *drv, ++ char *buf) + { +- int ret, action; ++ int lc_state = smc_call1(MLNX_GET_TBB_FUSE_STATUS, ++ MLNX_FUSE_STATUS_LIFECYCLE); + +- action = mlxbf_bootctl_reset_action_to_val(buf); +- if (action < 0) +- return action; ++ if (lc_state < 0) ++ return -EINVAL; ++ ++ lc_state &= (SB_MODE_TEST_MASK | ++ SB_MODE_SECURE_MASK | ++ SB_MODE_DEV_MASK); + +- ret = mlxbf_bootctl_smc(smc_op, action); +- if (ret < 0) +- return ret; ++ /* ++ * If the test bits are set, we specify that the current state may be ++ * due to using the test bits. ++ */ ++ if ((lc_state & SB_MODE_TEST_MASK) != 0) { ++ ++ lc_state &= SB_MODE_SECURE_MASK; ++ ++ return snprintf(buf, PAGE_SIZE, "%s(test)\n", ++ lifecycle_states[lc_state]); ++ } else if ((lc_state & SB_MODE_SECURE_MASK) == SB_LIFECYCLE_GA_SECURE ++ && (lc_state & SB_MODE_DEV_MASK)) { ++ return snprintf(buf, PAGE_SIZE, "Secured (development)\n"); ++ } ++ ++ return snprintf(buf, PAGE_SIZE, "%s\n", lifecycle_states[lc_state]); ++} ++ ++static ssize_t secure_boot_fuse_state_show(struct device_driver *drv, ++ char *buf) ++{ ++ int key; ++ int buf_len = 0; ++ int upper_key_used = 0; ++ int sb_key_state = smc_call1(MLNX_GET_TBB_FUSE_STATUS, ++ MLNX_FUSE_STATUS_KEYS); ++ ++ if (sb_key_state < 0) ++ return -EINVAL; ++ ++ for (key = SB_KEY_NUM - 1; key >= 0; key--) { ++ int burnt = ((sb_key_state & (1 << key)) != 0); ++ int valid = ((sb_key_state & (1 << (key + SB_KEY_NUM))) != 0); ++ ++ buf_len += sprintf(buf + buf_len, "Ver%d:", key); ++ if (upper_key_used) { ++ if (burnt) { ++ if (valid) ++ buf_len += sprintf(buf + buf_len, ++ "Used"); ++ else ++ buf_len += sprintf(buf + buf_len, ++ "Wasted"); ++ } else { ++ if (valid) ++ buf_len += sprintf(buf + buf_len, ++ "Invalid"); ++ else ++ buf_len += sprintf(buf + buf_len, ++ "Skipped"); ++ } ++ } else { ++ if (burnt) { ++ if (valid) { ++ upper_key_used = 1; ++ buf_len += sprintf(buf + buf_len, ++ "In use"); ++ } else ++ buf_len += sprintf(buf + buf_len, ++ "Burn incomplete"); ++ } else { ++ if (valid) ++ buf_len += sprintf(buf + buf_len, ++ "Invalid"); ++ else ++ buf_len += sprintf(buf + buf_len, ++ "Free"); ++ } ++ } ++ buf_len += sprintf(buf + buf_len, "\n"); ++ } ++ ++ return buf_len; ++} ++ ++static ssize_t fw_reset_store(struct device_driver *drv, ++ const char *buf, size_t count) ++{ ++ int err; ++ unsigned long key; ++ ++ err = kstrtoul(buf, 16, &key); ++ if (err) ++ return err; ++ ++ if (smc_call1(MLNX_HANDLE_FW_RESET, key) < 0) ++ return -EINVAL; + + return count; + } + +-static ssize_t reset_action_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t oob_mac_show(struct device_driver *drv, char *buf) + { +- return mlxbf_bootctl_show(MLXBF_BOOTCTL_GET_RESET_ACTION, buf); ++ char mac_str[MLNX_MFG_OOB_MAC_FORMAT_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ u8 *mac_byte_ptr; ++ ++ mutex_lock(&mfg_ops_lock); ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, MLNX_MFG_TYPE_OOB_MAC, 0, 0, 0, ++ 0, 0, 0, &res); ++ mutex_unlock(&mfg_ops_lock); ++ if (res.a0) ++ return -EPERM; ++ ++ mac_byte_ptr = (u8 *)&res.a1; ++ ++ sprintf(mac_str, "%02X:%02X:%02X:%02X:%02X:%02X", ++ mac_byte_ptr[0], mac_byte_ptr[1], mac_byte_ptr[2], ++ mac_byte_ptr[3], mac_byte_ptr[4], mac_byte_ptr[5]); ++ ++ return snprintf(buf, PAGE_SIZE, "%s", mac_str); + } + +-static ssize_t reset_action_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) ++static ssize_t oob_mac_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ int byte[MLNX_MFG_OOB_MAC_FORMAT_LEN] = { 0 }; ++ struct arm_smccc_res res; ++ u64 mac_addr = 0; ++ u8 *mac_byte_ptr; ++ int byte_idx, len; ++ ++ if ((count - 1) != MLNX_MFG_OOB_MAC_FORMAT_LEN) ++ return -EINVAL; ++ ++ len = sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", ++ &byte[0], &byte[1], &byte[2], ++ &byte[3], &byte[4], &byte[5]); ++ if (len != MLNX_MFG_OOB_MAC_LEN) ++ return -EINVAL; ++ ++ mac_byte_ptr = (u8 *)&mac_addr; ++ ++ for (byte_idx = 0; byte_idx < MLNX_MFG_OOB_MAC_LEN; byte_idx++) ++ mac_byte_ptr[byte_idx] = (u8) byte[byte_idx]; ++ ++ mutex_lock(&mfg_ops_lock); ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, MLNX_MFG_TYPE_OOB_MAC, ++ MLNX_MFG_OOB_MAC_LEN, mac_addr, 0, 0, 0, 0, &res); ++ mutex_unlock(&mfg_ops_lock); ++ ++ return res.a0 ? -EPERM : count; ++} ++ ++static ssize_t opn_show(struct device_driver *drv, char *buf) + { +- return mlxbf_bootctl_store(MLXBF_BOOTCTL_SET_RESET_ACTION, buf, count); ++ u64 opn_data[MLNX_MFG_VAL_QWORD_CNT(OPN)] = { 0 }; ++ char opn[MLNX_MFG_OPN_VAL_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(OPN); word++) { ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, ++ MLNX_MFG_TYPE_OPN_0 + word, ++ 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ opn_data[word] = res.a1; ++ } ++ mutex_unlock(&mfg_ops_lock); ++ memcpy(opn, opn_data, MLNX_MFG_OPN_VAL_LEN); ++ ++ return snprintf(buf, PAGE_SIZE, "%s", opn); + } + +-static ssize_t second_reset_action_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) ++static ssize_t opn_store(struct device_driver *drv, const char *buf, ++ size_t count) + { +- return mlxbf_bootctl_show(MLXBF_BOOTCTL_GET_SECOND_RESET_ACTION, buf); ++ u64 opn[MLNX_MFG_VAL_QWORD_CNT(OPN)] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ if (count > MLNX_MFG_OPN_VAL_LEN) ++ return -EINVAL; ++ ++ memcpy(opn, buf, count); ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(OPN); word++) { ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, ++ MLNX_MFG_TYPE_OPN_0 + word, ++ sizeof(u64), opn[word], 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ } ++ mutex_unlock(&mfg_ops_lock); ++ ++ return count; + } + +-static ssize_t second_reset_action_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) ++static ssize_t sku_show(struct device_driver *drv, char *buf) + { +- return mlxbf_bootctl_store(MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION, buf, +- count); ++ u64 sku_data[MLNX_MFG_VAL_QWORD_CNT(SKU)] = { 0 }; ++ char sku[MLNX_MFG_SKU_VAL_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(SKU); word++) { ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, ++ MLNX_MFG_TYPE_SKU_0 + word, ++ 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ sku_data[word] = res.a1; ++ } ++ mutex_unlock(&mfg_ops_lock); ++ memcpy(sku, sku_data, MLNX_MFG_SKU_VAL_LEN); ++ ++ return snprintf(buf, PAGE_SIZE, "%s", sku); + } + +-static ssize_t lifecycle_state_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t sku_store(struct device_driver *drv, const char *buf, ++ size_t count) + { +- int lc_state; ++ u64 sku[MLNX_MFG_VAL_QWORD_CNT(SKU)] = { 0 }; ++ struct arm_smccc_res res; ++ int word; + +- lc_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS, +- MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE); +- if (lc_state < 0) +- return lc_state; ++ if (count > MLNX_MFG_SKU_VAL_LEN) ++ return -EINVAL; + +- lc_state &= +- MLXBF_BOOTCTL_SB_TEST_MASK | MLXBF_BOOTCTL_SB_SECURE_MASK; ++ memcpy(sku, buf, count); + +- /* +- * If the test bits are set, we specify that the current state may be +- * due to using the test bits. +- */ +- if (lc_state & MLXBF_BOOTCTL_SB_TEST_MASK) { +- lc_state &= MLXBF_BOOTCTL_SB_SECURE_MASK; ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(SKU); word++) { ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, ++ MLNX_MFG_TYPE_SKU_0 + word, ++ sizeof(u64), sku[word], 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ } ++ mutex_unlock(&mfg_ops_lock); + +- return sprintf(buf, "%s(test)\n", +- mlxbf_bootctl_lifecycle_states[lc_state]); ++ return count; ++} ++ ++static ssize_t modl_show(struct device_driver *drv, char *buf) ++{ ++ u64 modl_data[MLNX_MFG_VAL_QWORD_CNT(MODL)] = { 0 }; ++ char modl[MLNX_MFG_MODL_VAL_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(MODL); word++) { ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, ++ MLNX_MFG_TYPE_MODL_0 + word, ++ 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ modl_data[word] = res.a1; + } ++ mutex_unlock(&mfg_ops_lock); ++ memcpy(modl, modl_data, MLNX_MFG_MODL_VAL_LEN); + +- return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]); ++ return snprintf(buf, PAGE_SIZE, "%s", modl); + } + +-static ssize_t secure_boot_fuse_state_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) ++static ssize_t modl_store(struct device_driver *drv, const char *buf, ++ size_t count) + { +- int burnt, valid, key, key_state, buf_len = 0, upper_key_used = 0; +- const char *status; ++ u64 modl[MLNX_MFG_VAL_QWORD_CNT(MODL)] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ if (count > MLNX_MFG_MODL_VAL_LEN) ++ return -EINVAL; ++ ++ memcpy(modl, buf, count); ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(MODL); word++) { ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, ++ MLNX_MFG_TYPE_MODL_0 + word, ++ sizeof(u64), modl[word], 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ } ++ mutex_unlock(&mfg_ops_lock); ++ ++ return count; ++} ++ ++static ssize_t sn_show(struct device_driver *drv, char *buf) ++{ ++ u64 sn_data[MLNX_MFG_VAL_QWORD_CNT(SN)] = { 0 }; ++ char sn[MLNX_MFG_SN_VAL_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(SN); word++) { ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, ++ MLNX_MFG_TYPE_SN_0 + word, ++ 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ sn_data[word] = res.a1; ++ } ++ mutex_unlock(&mfg_ops_lock); ++ memcpy(sn, sn_data, MLNX_MFG_SN_VAL_LEN); ++ ++ return snprintf(buf, PAGE_SIZE, "%s", sn); ++} ++ ++static ssize_t sn_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ u64 sn[MLNX_MFG_VAL_QWORD_CNT(SN)] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ if (count > MLNX_MFG_SN_VAL_LEN) ++ return -EINVAL; ++ ++ memcpy(sn, buf, count); ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(SN); word++) { ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, ++ MLNX_MFG_TYPE_SN_0 + word, ++ sizeof(u64), sn[word], 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ } ++ mutex_unlock(&mfg_ops_lock); ++ ++ return count; ++} ++ ++static ssize_t uuid_show(struct device_driver *drv, char *buf) ++{ ++ u64 uuid_data[MLNX_MFG_VAL_QWORD_CNT(UUID)] = { 0 }; ++ char uuid[MLNX_MFG_UUID_VAL_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(UUID); word++) { ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, ++ MLNX_MFG_TYPE_UUID_0 + word, ++ 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ uuid_data[word] = res.a1; ++ } ++ mutex_unlock(&mfg_ops_lock); ++ memcpy(uuid, uuid_data, MLNX_MFG_UUID_VAL_LEN); ++ ++ return snprintf(buf, PAGE_SIZE, "%s", uuid); ++} ++ ++static ssize_t uuid_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ u64 uuid[MLNX_MFG_VAL_QWORD_CNT(UUID)] = { 0 }; ++ struct arm_smccc_res res; ++ int word; + +- key_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS, +- MLXBF_BOOTCTL_FUSE_STATUS_KEYS); +- if (key_state < 0) +- return key_state; ++ if (count > MLNX_MFG_UUID_VAL_LEN) ++ return -EINVAL; ++ ++ memcpy(uuid, buf, count); ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(UUID); word++) { ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, ++ MLNX_MFG_TYPE_UUID_0 + word, ++ sizeof(u64), uuid[word], 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ } ++ mutex_unlock(&mfg_ops_lock); ++ ++ return count; ++} ++ ++static ssize_t rev_show(struct device_driver *drv, char *buf) ++{ ++ u64 rev_data[MLNX_MFG_VAL_QWORD_CNT(REV)] = { 0 }; ++ char rev[MLNX_MFG_REV_VAL_LEN + 1] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(REV); word++) { ++ arm_smccc_smc(MLNX_HANDLE_GET_MFG_INFO, ++ MLNX_MFG_TYPE_REV + word, ++ 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ rev_data[word] = res.a1; ++ } ++ mutex_unlock(&mfg_ops_lock); ++ memcpy(rev, rev_data, MLNX_MFG_REV_VAL_LEN); ++ ++ return snprintf(buf, PAGE_SIZE, "%s", rev); ++} ++ ++static ssize_t rev_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ u64 rev[MLNX_MFG_VAL_QWORD_CNT(REV)] = { 0 }; ++ struct arm_smccc_res res; ++ int word; ++ ++ if (count > MLNX_MFG_REV_VAL_LEN) ++ return -EINVAL; ++ ++ memcpy(rev, buf, count); ++ ++ mutex_lock(&mfg_ops_lock); ++ for (word = 0; word < MLNX_MFG_VAL_QWORD_CNT(REV); word++) { ++ arm_smccc_smc(MLNX_HANDLE_SET_MFG_INFO, ++ MLNX_MFG_TYPE_REV + word, ++ sizeof(u64), rev[word], 0, 0, 0, 0, &res); ++ if (res.a0) { ++ mutex_unlock(&mfg_ops_lock); ++ return -EPERM; ++ } ++ } ++ mutex_unlock(&mfg_ops_lock); ++ ++ return count; ++} ++ ++static ssize_t mfg_lock_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err) ++ return err; ++ ++ if (val != 1) ++ return -EINVAL; ++ ++ mutex_lock(&mfg_ops_lock); ++ smc_call0(MLNX_HANDLE_LOCK_MFG_INFO); ++ mutex_unlock(&mfg_ops_lock); ++ ++ return count; ++} ++ ++/* Log header format. */ ++#define RSH_LOG_TYPE_SHIFT 56 ++#define RSH_LOG_LEN_SHIFT 48 ++#define RSH_LOG_LEVEL_SHIFT 0 ++ ++/* Module ID and type used here. */ ++#define BF_RSH_LOG_TYPE_UNKNOWN 0x00ULL ++#define BF_RSH_LOG_TYPE_PANIC 0x01ULL ++#define BF_RSH_LOG_TYPE_EXCEPTION 0x02ULL ++#define BF_RSH_LOG_TYPE_UNUSED 0x03ULL ++#define BF_RSH_LOG_TYPE_MSG 0x04ULL ++ ++/* Utility macro. */ ++#define BF_RSH_LOG_MOD_MASK 0x0FULL ++#define BF_RSH_LOG_MOD_SHIFT 60 ++#define BF_RSH_LOG_TYPE_MASK 0x0FULL ++#define BF_RSH_LOG_TYPE_SHIFT 56 ++#define BF_RSH_LOG_LEN_MASK 0x7FULL ++#define BF_RSH_LOG_LEN_SHIFT 48 ++#define BF_RSH_LOG_ARG_MASK 0xFFFFFFFFULL ++#define BF_RSH_LOG_ARG_SHIFT 16 ++#define BF_RSH_LOG_HAS_ARG_MASK 0xFFULL ++#define BF_RSH_LOG_HAS_ARG_SHIFT 8 ++#define BF_RSH_LOG_LEVEL_MASK 0xFFULL ++#define BF_RSH_LOG_LEVEL_SHIFT 0 ++#define BF_RSH_LOG_PC_MASK 0xFFFFFFFFULL ++#define BF_RSH_LOG_PC_SHIFT 0 ++#define BF_RSH_LOG_SYNDROME_MASK 0xFFFFFFFFULL ++#define BF_RSH_LOG_SYNDROME_SHIFT 0 ++ ++#define BF_RSH_LOG_HEADER_GET(f, h) \ ++ (((h) >> BF_RSH_LOG_##f##_SHIFT) & BF_RSH_LOG_##f##_MASK) ++ ++/* Log message level. */ ++enum { ++ RSH_LOG_INFO, ++ RSH_LOG_WARN, ++ RSH_LOG_ERR ++}; ++ ++/* Log module */ ++const char * const rsh_log_mod[] = { ++ "MISC", "BL1", "BL2", "BL2R", "BL31", "UEFI" ++}; ++ ++const char *rsh_log_level[] = {"INFO", "WARN", "ERR", "ASSERT"}; ++ ++#define AARCH64_MRS_REG_SHIFT 5 ++#define AARCH64_MRS_REG_MASK 0xffff ++#define AARCH64_ESR_ELX_EXCEPTION_CLASS_SHIFT 26 ++ ++struct rsh_log_reg { ++ char *name; ++ u32 opcode; ++} rsh_log_reg; ++ ++static struct rsh_log_reg rsh_log_regs[] = { ++ {"actlr_el1", 0b1100000010000001}, ++ {"actlr_el2", 0b1110000010000001}, ++ {"actlr_el3", 0b1111000010000001}, ++ {"afsr0_el1", 0b1100001010001000}, ++ {"afsr0_el2", 0b1110001010001000}, ++ {"afsr0_el3", 0b1111001010001000}, ++ {"afsr1_el1", 0b1100001010001001}, ++ {"afsr1_el2", 0b1110001010001001}, ++ {"afsr1_el3", 0b1111001010001001}, ++ {"amair_el1", 0b1100010100011000}, ++ {"amair_el2", 0b1110010100011000}, ++ {"amair_el3", 0b1111010100011000}, ++ {"ccsidr_el1", 0b1100100000000000}, ++ {"clidr_el1", 0b1100100000000001}, ++ {"cntkctl_el1", 0b1100011100001000}, ++ {"cntp_ctl_el0", 0b1101111100010001}, ++ {"cntp_cval_el0", 0b1101111100010010}, ++ {"cntv_ctl_el0", 0b1101111100011001}, ++ {"cntv_cval_el0", 0b1101111100011010}, ++ {"contextidr_el1", 0b1100011010000001}, ++ {"cpacr_el1", 0b1100000010000010}, ++ {"cptr_el2", 0b1110000010001010}, ++ {"cptr_el3", 0b1111000010001010}, ++ {"vtcr_el2", 0b1110000100001010}, ++ {"ctr_el0", 0b1101100000000001}, ++ {"currentel", 0b1100001000010010}, ++ {"dacr32_el2", 0b1110000110000000}, ++ {"daif", 0b1101101000010001}, ++ {"dczid_el0", 0b1101100000000111}, ++ {"dlr_el0", 0b1101101000101001}, ++ {"dspsr_el0", 0b1101101000101000}, ++ {"elr_el1", 0b1100001000000001}, ++ {"elr_el2", 0b1110001000000001}, ++ {"elr_el3", 0b1111001000000001}, ++ {"esr_el1", 0b1100001010010000}, ++ {"esr_el2", 0b1110001010010000}, ++ {"esr_el3", 0b1111001010010000}, ++ {"esselr_el1", 0b1101000000000000}, ++ {"far_el1", 0b1100001100000000}, ++ {"far_el2", 0b1110001100000000}, ++ {"far_el3", 0b1111001100000000}, ++ {"fpcr", 0b1101101000100000}, ++ {"fpexc32_el2", 0b1110001010011000}, ++ {"fpsr", 0b1101101000100001}, ++ {"hacr_el2", 0b1110000010001111}, ++ {"har_el2", 0b1110000010001000}, ++ {"hpfar_el2", 0b1110001100000100}, ++ {"hstr_el2", 0b1110000010001011}, ++ {"far_el1", 0b1100001100000000}, ++ {"far_el2", 0b1110001100000000}, ++ {"far_el3", 0b1111001100000000}, ++ {"hcr_el2", 0b1110000010001000}, ++ {"hpfar_el2", 0b1110001100000100}, ++ {"id_aa64afr0_el1", 0b1100000000101100}, ++ {"id_aa64afr1_el1", 0b1100000000101101}, ++ {"id_aa64dfr0_el1", 0b1100000000101100}, ++ {"id_aa64isar0_el1", 0b1100000000110000}, ++ {"id_aa64isar1_el1", 0b1100000000110001}, ++ {"id_aa64mmfr0_el1", 0b1100000000111000}, ++ {"id_aa64mmfr1_el1", 0b1100000000111001}, ++ {"id_aa64pfr0_el1", 0b1100000000100000}, ++ {"id_aa64pfr1_el1", 0b1100000000100001}, ++ {"ifsr32_el2", 0b1110001010000001}, ++ {"isr_el1", 0b1100011000001000}, ++ {"mair_el1", 0b1100010100010000}, ++ {"mair_el2", 0b1110010100010000}, ++ {"mair_el3", 0b1111010100010000}, ++ {"midr_el1", 0b1100000000000000}, ++ {"mpidr_el1", 0b1100000000000101}, ++ {"nzcv", 0b1101101000010000}, ++ {"revidr_el1", 0b1100000000000110}, ++ {"rmr_el3", 0b1111011000000010}, ++ {"par_el1", 0b1100001110100000}, ++ {"rvbar_el3", 0b1111011000000001}, ++ {"scr_el3", 0b1111000010001000}, ++ {"sctlr_el1", 0b1100000010000000}, ++ {"sctlr_el2", 0b1110000010000000}, ++ {"sctlr_el3", 0b1111000010000000}, ++ {"sp_el0", 0b1100001000001000}, ++ {"sp_el1", 0b1110001000001000}, ++ {"spsel", 0b1100001000010000}, ++ {"spsr_abt", 0b1110001000011001}, ++ {"spsr_el1", 0b1100001000000000}, ++ {"spsr_el2", 0b1110001000000000}, ++ {"spsr_el3", 0b1111001000000000}, ++ {"spsr_fiq", 0b1110001000011011}, ++ {"spsr_irq", 0b1110001000011000}, ++ {"spsr_und", 0b1110001000011010}, ++ {"tcr_el1", 0b1100000100000010}, ++ {"tcr_el2", 0b1110000100000010}, ++ {"tcr_el3", 0b1111000100000010}, ++ {"tpidr_el0", 0b1101111010000010}, ++ {"tpidr_el1", 0b1100011010000100}, ++ {"tpidr_el2", 0b1110011010000010}, ++ {"tpidr_el3", 0b1111011010000010}, ++ {"tpidpro_el0", 0b1101111010000011}, ++ {"vbar_el1", 0b1100011000000000}, ++ {"vbar_el2", 0b1110011000000000}, ++ {"vbar_el3", 0b1111011000000000}, ++ {"vmpidr_el2", 0b1110000000000101}, ++ {"vpidr_el2", 0b1110000000000000}, ++ {"ttbr0_el1", 0b1100000100000000}, ++ {"ttbr0_el2", 0b1110000100000000}, ++ {"ttbr0_el3", 0b1111000100000000}, ++ {"ttbr1_el1", 0b1100000100000001}, ++ {"vtcr_el2", 0b1110000100001010}, ++ {"vttbr_el2", 0b1110000100001000}, ++ {NULL, 0b0000000000000000}, ++}; ++ ++/* Size(8-byte words) of the log buffer. */ ++#define RSH_SCRATCH_BUF_CTL_IDX_MASK 0x7f ++ ++static int rsh_log_sem_lock(void) ++{ ++ unsigned long timeout; ++ ++ /* Take the semaphore. */ ++ timeout = jiffies + msecs_to_jiffies(100); ++ while (readq(rsh_semaphore)) { ++ if (time_after(jiffies, timeout)) ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static void rsh_log_sem_unlock(void) ++{ ++ writeq(0, rsh_semaphore); ++} ++ ++static ssize_t rsh_log_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ int idx, num, len, size = (int)count, level = RSH_LOG_INFO, rc; ++ u64 data; ++ ++ if (!size) ++ return -EINVAL; ++ ++ if (!rsh_semaphore || !rsh_scratch_buf_ctl) ++ return -EOPNOTSUPP; ++ ++ /* Ignore line break at the end. */ ++ if (buf[size-1] == 0xa) ++ size--; ++ ++ /* Check the message prefix. */ ++ for (idx = 0; idx < ARRAY_SIZE(rsh_log_level); idx++) { ++ len = strlen(rsh_log_level[idx]); ++ if (len + 1 < size && !strncmp(buf, rsh_log_level[idx], len)) { ++ buf += len + 1; ++ size -= len + 1; ++ level = idx; ++ break; ++ } ++ } ++ ++ /* Ignore leading spaces. */ ++ while (size > 0 && buf[0] == ' ') { ++ size--; ++ buf++; ++ } ++ ++ /* Take the semaphore. */ ++ rc = rsh_log_sem_lock(); ++ if (rc) ++ return rc; ++ ++ /* Calculate how many words are available. */ ++ num = (size + sizeof(u64) - 1) / sizeof(u64); ++ idx = readq(rsh_scratch_buf_ctl); ++ if (idx + num + 1 >= RSH_SCRATCH_BUF_CTL_IDX_MASK) ++ num = RSH_SCRATCH_BUF_CTL_IDX_MASK - idx - 1; ++ if (num <= 0) ++ goto done; ++ ++ /* Write Header. */ ++ data = (BF_RSH_LOG_TYPE_MSG << RSH_LOG_TYPE_SHIFT) | ++ ((u64)num << RSH_LOG_LEN_SHIFT) | ++ ((u64)level << RSH_LOG_LEVEL_SHIFT); ++ writeq(data, rsh_scratch_buf_data); ++ ++ /* Write message. */ ++ for (idx = 0, len = size; idx < num && len > 0; idx++) { ++ if (len <= sizeof(u64)) { ++ data = 0; ++ memcpy(&data, buf, len); ++ len = 0; ++ } else { ++ memcpy(&data, buf, sizeof(u64)); ++ len -= sizeof(u64); ++ buf += sizeof(u64); ++ } ++ writeq(data, rsh_scratch_buf_data); ++ } ++ ++done: ++ /* Release the semaphore. */ ++ rsh_log_sem_unlock(); ++ ++ /* Ignore the rest if no more space. */ ++ return count; ++} ++ ++static char *rsh_log_get_reg_name(u64 opcode) ++{ ++ struct rsh_log_reg *reg = rsh_log_regs; ++ ++ while (reg->name) { ++ if (reg->opcode == opcode) ++ return reg->name; ++ reg++; ++ } ++ ++ return "unknown"; ++} ++ ++static int rsh_log_show_crash(u64 hdr, char *buf, int size) ++{ ++ int i, module, type, len, n = 0; ++ u32 pc, syndrome, ec; ++ u64 opcode, data; ++ char *p = buf; ++ ++ module = BF_RSH_LOG_HEADER_GET(MOD, hdr); ++ if (module >= ARRAY_SIZE(rsh_log_mod)) ++ module = 0; ++ type = BF_RSH_LOG_HEADER_GET(TYPE, hdr); ++ len = BF_RSH_LOG_HEADER_GET(LEN, hdr); ++ ++ if (type == BF_RSH_LOG_TYPE_EXCEPTION) { ++ syndrome = BF_RSH_LOG_HEADER_GET(SYNDROME, hdr); ++ ec = syndrome >> AARCH64_ESR_ELX_EXCEPTION_CLASS_SHIFT; ++ n = snprintf(p, size, " Exception(%s): syndrome = 0x%x%s\n", ++ rsh_log_mod[module], syndrome, ++ (ec == 0x24 || ec == 0x25) ? "(Data Abort)" : ++ (ec == 0x2f) ? "(SError)" : ""); ++ } else if (type == BF_RSH_LOG_TYPE_PANIC) { ++ pc = BF_RSH_LOG_HEADER_GET(PC, hdr); ++ n = snprintf(p, size, ++ " PANIC(%s): PC = 0x%x\n", rsh_log_mod[module], ++ pc); ++ } ++ if (n > 0) { ++ p += n; ++ size -= n; ++ } + + /* +- * key_state contains the bits for 4 Key versions, loaded from eFuses +- * after a hard reset. Lower 4 bits are a thermometer code indicating +- * key programming has started for key n (0000 = none, 0001 = version 0, +- * 0011 = version 1, 0111 = version 2, 1111 = version 3). Upper 4 bits +- * are a thermometer code indicating key programming has completed for +- * key n (same encodings as the start bits). This allows for detection +- * of an interruption in the programming process which has left the key +- * partially programmed (and thus invalid). The process is to burn the +- * eFuse for the new key start bit, burn the key eFuses, then burn the +- * eFuse for the new key complete bit. +- * +- * For example 0000_0000: no key valid, 0001_0001: key version 0 valid, +- * 0011_0011: key 1 version valid, 0011_0111: key version 2 started +- * programming but did not complete, etc. The most recent key for which +- * both start and complete bit is set is loaded. On soft reset, this +- * register is not modified. ++ * Read the registers in a loop. 'len' is the total number of words in ++ * 8-bytes. Two words are read in each loop. + */ +- for (key = MLXBF_SB_KEY_NUM - 1; key >= 0; key--) { +- burnt = key_state & BIT(key); +- valid = key_state & BIT(key + MLXBF_SB_KEY_NUM); ++ for (i = 0; i < len/2; i++) { ++ opcode = readq(rsh_scratch_buf_data); ++ data = readq(rsh_scratch_buf_data); ++ ++ opcode = (opcode >> AARCH64_MRS_REG_SHIFT) & ++ AARCH64_MRS_REG_MASK; ++ n = snprintf(p, size, ++ " %-16s0x%llx\n", rsh_log_get_reg_name(opcode), ++ (unsigned long long)data); ++ if (n > 0) { ++ p += n; ++ size -= n; ++ } ++ } + +- if (burnt && valid) +- upper_key_used = 1; ++ return p - buf; ++} + +- if (upper_key_used) { +- if (burnt) +- status = valid ? "Used" : "Wasted"; +- else +- status = valid ? "Invalid" : "Skipped"; +- } else { +- if (burnt) +- status = valid ? "InUse" : "Incomplete"; +- else +- status = valid ? "Invalid" : "Free"; ++static int rsh_log_format_msg(char *buf, int size, const char *msg, ...) ++{ ++ va_list args; ++ int len; ++ ++ va_start(args, msg); ++ len = vsnprintf(buf, size, msg, args); ++ va_end(args); ++ ++ return len; ++} ++ ++static int rsh_log_show_msg(u64 hdr, char *buf, int size) ++{ ++ int has_arg = BF_RSH_LOG_HEADER_GET(HAS_ARG, hdr); ++ int level = BF_RSH_LOG_HEADER_GET(LEVEL, hdr); ++ int module = BF_RSH_LOG_HEADER_GET(MOD, hdr); ++ int len = BF_RSH_LOG_HEADER_GET(LEN, hdr); ++ u32 arg = BF_RSH_LOG_HEADER_GET(ARG, hdr); ++ char *msg, *p; ++ u64 data; ++ ++ if (len <= 0) ++ return -EINVAL; ++ ++ if (module >= ARRAY_SIZE(rsh_log_mod)) ++ module = 0; ++ ++ if (level >= ARRAY_SIZE(rsh_log_level)) ++ level = 0; ++ ++ msg = kmalloc(len * sizeof(u64) + 1, GFP_KERNEL); ++ if (!msg) ++ return 0; ++ p = msg; ++ ++ while (len--) { ++ data = readq(rsh_scratch_buf_data); ++ memcpy(p, &data, sizeof(data)); ++ p += sizeof(data); ++ } ++ *p = '\0'; ++ if (!has_arg) { ++ len = snprintf(buf, size, " %s[%s]: %s\n", rsh_log_level[level], ++ rsh_log_mod[module], msg); ++ } else { ++ len = snprintf(buf, size, " %s[%s]: ", rsh_log_level[level], ++ rsh_log_mod[module]); ++ len += rsh_log_format_msg(buf + len, size - len, msg, arg); ++ len += snprintf(buf + len, size - len, "\n"); ++ } ++ ++ kfree(msg); ++ return len; ++} ++ ++static ssize_t rsh_log_show(struct device_driver *drv, char *buf) ++{ ++ u64 hdr; ++ char *p = buf; ++ int i, n, rc, idx, type, len, size = PAGE_SIZE; ++ ++ if (!rsh_semaphore || !rsh_scratch_buf_ctl) ++ return -EOPNOTSUPP; ++ ++ /* Take the semaphore. */ ++ rc = rsh_log_sem_lock(); ++ if (rc) ++ return rc; ++ ++ /* Save the current index and read from 0. */ ++ idx = readq(rsh_scratch_buf_ctl) & RSH_SCRATCH_BUF_CTL_IDX_MASK; ++ if (!idx) ++ goto done; ++ writeq(0, rsh_scratch_buf_ctl); ++ ++ i = 0; ++ while (i < idx) { ++ hdr = readq(rsh_scratch_buf_data); ++ type = BF_RSH_LOG_HEADER_GET(TYPE, hdr); ++ len = BF_RSH_LOG_HEADER_GET(LEN, hdr); ++ i += 1 + len; ++ if (i > idx) ++ break; ++ ++ switch (type) { ++ case BF_RSH_LOG_TYPE_PANIC: ++ case BF_RSH_LOG_TYPE_EXCEPTION: ++ n = rsh_log_show_crash(hdr, p, size); ++ p += n; ++ size -= n; ++ break; ++ case BF_RSH_LOG_TYPE_MSG: ++ n = rsh_log_show_msg(hdr, p, size); ++ p += n; ++ size -= n; ++ break; ++ default: ++ /* Drain this message. */ ++ while (len--) ++ (void) readq(rsh_scratch_buf_data); ++ break; + } +- buf_len += sprintf(buf + buf_len, "%d:%s ", key, status); + } +- buf_len += sprintf(buf + buf_len, "\n"); + +- return buf_len; ++ if (rsh_log_clear_on_read) ++ writeq(0, rsh_scratch_buf_ctl); ++ else ++ writeq(idx, rsh_scratch_buf_ctl); ++ ++done: ++ /* Release the semaphore. */ ++ rsh_log_sem_unlock(); ++ ++ return p - buf; + } + +-static DEVICE_ATTR_RW(post_reset_wdog); +-static DEVICE_ATTR_RW(reset_action); +-static DEVICE_ATTR_RW(second_reset_action); +-static DEVICE_ATTR_RO(lifecycle_state); +-static DEVICE_ATTR_RO(secure_boot_fuse_state); ++static DRIVER_ATTR_RW(post_reset_wdog); ++static DRIVER_ATTR_RW(reset_action); ++static DRIVER_ATTR_RW(second_reset_action); ++static DRIVER_ATTR_RO(lifecycle_state); ++static DRIVER_ATTR_RO(secure_boot_fuse_state); ++static DRIVER_ATTR_WO(fw_reset); ++static DRIVER_ATTR_RW(oob_mac); ++static DRIVER_ATTR_RW(opn); ++static DRIVER_ATTR_RW(sku); ++static DRIVER_ATTR_RW(modl); ++static DRIVER_ATTR_RW(sn); ++static DRIVER_ATTR_RW(uuid); ++static DRIVER_ATTR_RW(rev); ++static DRIVER_ATTR_WO(mfg_lock); ++static DRIVER_ATTR_RW(rsh_log); + +-static struct attribute *mlxbf_bootctl_attrs[] = { +- &dev_attr_post_reset_wdog.attr, +- &dev_attr_reset_action.attr, +- &dev_attr_second_reset_action.attr, +- &dev_attr_lifecycle_state.attr, +- &dev_attr_secure_boot_fuse_state.attr, ++static struct attribute *mbc_dev_attrs[] = { ++ &driver_attr_post_reset_wdog.attr, ++ &driver_attr_reset_action.attr, ++ &driver_attr_second_reset_action.attr, ++ &driver_attr_lifecycle_state.attr, ++ &driver_attr_secure_boot_fuse_state.attr, ++ &driver_attr_fw_reset.attr, ++ &driver_attr_oob_mac.attr, ++ &driver_attr_opn.attr, ++ &driver_attr_sku.attr, ++ &driver_attr_modl.attr, ++ &driver_attr_sn.attr, ++ &driver_attr_uuid.attr, ++ &driver_attr_rev.attr, ++ &driver_attr_mfg_lock.attr, ++ &driver_attr_rsh_log.attr, + NULL + }; + +-ATTRIBUTE_GROUPS(mlxbf_bootctl); ++static struct attribute_group mbc_attr_group = { ++ .attrs = mbc_dev_attrs ++}; + +-static const struct acpi_device_id mlxbf_bootctl_acpi_ids[] = { ++static const struct attribute_group *mbc_attr_groups[] = { ++ &mbc_attr_group, ++ NULL ++}; ++ ++static const struct of_device_id mbc_dt_ids[] = { ++ {.compatible = "mellanox,bootctl"}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, mbc_dt_ids); ++ ++static const struct acpi_device_id mbc_acpi_ids[] = { + {"MLNXBF04", 0}, +- {} ++ {}, + }; + +-MODULE_DEVICE_TABLE(acpi, mlxbf_bootctl_acpi_ids); ++MODULE_DEVICE_TABLE(acpi, mbc_acpi_ids); + +-static bool mlxbf_bootctl_guid_match(const guid_t *guid, +- const struct arm_smccc_res *res) ++static ssize_t mbc_bootfifo_read_raw(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *bin_attr, ++ char *buf, loff_t pos, size_t count) + { +- guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16, +- res->a2, res->a2 >> 8, res->a2 >> 16, +- res->a2 >> 24, res->a3, res->a3 >> 8, +- res->a3 >> 16, res->a3 >> 24); ++ unsigned long timeout = jiffies + HZ / 2; ++ char *p = buf; ++ int cnt = 0; ++ u64 data; + +- return guid_equal(guid, &id); ++ /* Give up reading if no more data within 500ms. */ ++ while (count >= sizeof(data)) { ++ if (!cnt) { ++ cnt = readq(rsh_boot_cnt); ++ if (!cnt) { ++ if (time_after(jiffies, timeout)) ++ break; ++ udelay(10); ++ continue; ++ } ++ } ++ ++ data = readq(rsh_boot_data); ++ memcpy(p, &data, sizeof(data)); ++ count -= sizeof(data); ++ p += sizeof(data); ++ cnt--; ++ timeout = jiffies + HZ / 2; ++ } ++ ++ return p - buf; + } + +-static int mlxbf_bootctl_probe(struct platform_device *pdev) ++static struct bin_attribute mbc_bootfifo_sysfs_attr = { ++ .attr = { .name = "bootfifo", .mode = 0400 }, ++ .read = mbc_bootfifo_read_raw, ++}; ++ ++static int mbc_probe(struct platform_device *pdev) + { +- struct arm_smccc_res res = { 0 }; +- guid_t guid; +- int ret; ++ struct resource *resource; ++ struct arm_smccc_res res; ++ void __iomem *data; ++ int err; + +- /* Ensure we have the UUID we expect for this service. */ +- arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); +- guid_parse(mlxbf_bootctl_svc_uuid_str, &guid); +- if (!mlxbf_bootctl_guid_match(&guid, &res)) ++ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!resource) + return -ENODEV; ++ rsh_boot_data = devm_ioremap_resource(&pdev->dev, resource); ++ if (IS_ERR(rsh_boot_data)) ++ return PTR_ERR(rsh_boot_data); ++ ++ resource = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!resource) ++ return -ENODEV; ++ rsh_boot_cnt = devm_ioremap_resource(&pdev->dev, resource); ++ if (IS_ERR(rsh_boot_cnt)) ++ return PTR_ERR(rsh_boot_cnt); ++ ++ resource = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (resource) { ++ data = devm_ioremap_resource(&pdev->dev, resource); ++ if (!IS_ERR(data)) ++ rsh_semaphore = data; ++ } ++ ++ resource = platform_get_resource(pdev, IORESOURCE_MEM, 3); ++ if (resource) { ++ data = devm_ioremap_resource(&pdev->dev, resource); ++ if (!IS_ERR(data)) { ++ rsh_scratch_buf_ctl = data + RSH_SCRATCH_BUF_CTL_OFF; ++ rsh_scratch_buf_data = data + RSH_SCRATCH_BUF_DATA_OFF; ++ } ++ } + + /* +- * When watchdog is used, it sets boot mode to MLXBF_BOOTCTL_SWAP_EMMC ++ * Ensure we have the UUID we expect for this service. ++ * Note that the functionality we want is present in the first ++ * released version of this service, so we don't check the version. ++ */ ++ arm_smccc_smc(MLNX_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0 != 0x89c036b4 || res.a1 != 0x11e6e7d7 || ++ res.a2 != 0x1a009787 || res.a3 != 0xc4bf00ca) ++ return -ENODEV; ++ ++ /* ++ * When watchdog is used, it sets the boot mode to MLNX_BOOT_SWAP_EMMC + * in case of boot failures. However it doesn't clear the state if there + * is no failure. Restore the default boot mode here to avoid any + * unnecessary boot partition swapping. + */ +- ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_SET_RESET_ACTION, +- MLXBF_BOOTCTL_EMMC); +- if (ret < 0) +- dev_warn(&pdev->dev, "Unable to reset the EMMC boot mode\n"); ++ if (smc_call1(MLNX_SET_RESET_ACTION, MLNX_BOOT_EMMC) < 0) ++ pr_err("Unable to reset the EMMC boot mode\n"); ++ ++ err = sysfs_create_bin_file(&pdev->dev.kobj, &mbc_bootfifo_sysfs_attr); ++ if (err) { ++ pr_err("Unable to create bootfifo sysfs file, error %d\n", err); ++ return err; ++ } ++ ++ pr_info("%s (version %s)\n", DRIVER_DESCRIPTION, DRIVER_VERSION); ++ ++ return 0; ++} ++ ++static int mbc_remove(struct platform_device *pdev) ++{ ++ sysfs_remove_bin_file(&pdev->dev.kobj, &mbc_bootfifo_sysfs_attr); + + return 0; + } + +-static struct platform_driver mlxbf_bootctl_driver = { +- .probe = mlxbf_bootctl_probe, ++static struct platform_driver mbc_driver = { ++ .probe = mbc_probe, ++ .remove = mbc_remove, + .driver = { +- .name = "mlxbf-bootctl", +- .dev_groups = mlxbf_bootctl_groups, +- .acpi_match_table = mlxbf_bootctl_acpi_ids, ++ .name = DRIVER_NAME, ++ .groups = mbc_attr_groups, ++ .of_match_table = mbc_dt_ids, ++ .acpi_match_table = ACPI_PTR(mbc_acpi_ids), + } + }; + +-module_platform_driver(mlxbf_bootctl_driver); ++module_platform_driver(mbc_driver); + +-MODULE_DESCRIPTION("Mellanox boot control driver"); +-MODULE_LICENSE("GPL v2"); +-MODULE_AUTHOR("Mellanox Technologies"); ++MODULE_DESCRIPTION(DRIVER_DESCRIPTION); ++MODULE_VERSION(DRIVER_VERSION); ++MODULE_AUTHOR("Shravan Kumar Ramani "); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/platform/mellanox/mlxbf-bootctl.h b/drivers/platform/mellanox/mlxbf-bootctl.h +index 148fdb43b..3e9dda829 100644 +--- a/drivers/platform/mellanox/mlxbf-bootctl.h ++++ b/drivers/platform/mellanox/mlxbf-bootctl.h +@@ -1,11 +1,22 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause + /* +- * Copyright (c) 2019, Mellanox Technologies. All rights reserved. ++ * Copyright (C) 2020 Mellanox Technologies. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License v2.0 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. + */ + + #ifndef __MLXBF_BOOTCTL_H__ + #define __MLXBF_BOOTCTL_H__ + ++/* BlueField-specific SMC function IDs */ ++ + /* + * Request that the on-chip watchdog be enabled, or disabled, after + * the next chip soft reset. This call does not affect the current +@@ -14,14 +25,14 @@ + * will not be enabled after the next soft reset. Non-zero errors are + * returned as documented below. + */ +-#define MLXBF_BOOTCTL_SET_POST_RESET_WDOG 0x82000000 ++#define MLNX_SET_POST_RESET_WDOG 0x82000000 + + /* + * Query the status which has been requested for the on-chip watchdog + * after the next chip soft reset. Returns the interval as set by +- * MLXBF_BOOTCTL_SET_POST_RESET_WDOG. ++ * MLNX_SET_POST_RESET_WDOG. + */ +-#define MLXBF_BOOTCTL_GET_POST_RESET_WDOG 0x82000001 ++#define MLNX_GET_POST_RESET_WDOG 0x82000001 + + /* + * Request that a specific boot action be taken at the next soft +@@ -32,72 +43,77 @@ + * invoked. See below for the available MLNX_BOOT_xxx parameter + * values. Non-zero errors are returned as documented below. + */ +-#define MLXBF_BOOTCTL_SET_RESET_ACTION 0x82000002 ++#define MLNX_SET_RESET_ACTION 0x82000002 + + /* + * Return the specific boot action which will be taken at the next + * soft reset. Returns the reset action (see below for the parameter +- * values for MLXBF_BOOTCTL_SET_RESET_ACTION). ++ * values for MLNX_SET_RESET_ACTION). + */ +-#define MLXBF_BOOTCTL_GET_RESET_ACTION 0x82000003 ++#define MLNX_GET_RESET_ACTION 0x82000003 + + /* + * Request that a specific boot action be taken at the soft reset + * after the next soft reset. For a specified valid boot mode, the + * effect of this call is identical to that of invoking +- * MLXBF_BOOTCTL_SET_RESET_ACTION after the next chip soft reset; in ++ * MLNX_SET_RESET_ACTION after the next chip soft reset; in + * particular, after that reset, the action for the now next reset can +- * be queried with MLXBF_BOOTCTL_GET_RESET_ACTION and modified with +- * MLXBF_BOOTCTL_SET_RESET_ACTION. You may also specify the parameter as ++ * be queried with MLNX_GET_RESET_ACTION and modified with ++ * MLNX_SET_RESET_ACTION. You may also specify the parameter as + * MLNX_BOOT_NONE, which is equivalent to specifying that no call to +- * MLXBF_BOOTCTL_SET_RESET_ACTION be taken after the next chip soft reset. ++ * MLNX_SET_RESET_ACTION be taken after the next chip soft reset. + * This call does not affect the action to be taken at the next soft + * reset. Non-zero errors are returned as documented below. + */ +-#define MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION 0x82000004 ++#define MLNX_SET_SECOND_RESET_ACTION 0x82000004 + + /* + * Return the specific boot action which will be taken at the soft + * reset after the next soft reset; this will be one of the valid +- * actions for MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION. ++ * actions for MLNX_SET_SECOND_RESET_ACTION. + */ +-#define MLXBF_BOOTCTL_GET_SECOND_RESET_ACTION 0x82000005 ++#define MLNX_GET_SECOND_RESET_ACTION 0x82000005 + + /* + * Return the fuse status of the current chip. The caller should specify + * with the second argument if the state of the lifecycle fuses or the + * version of secure boot fuse keys left should be returned. + */ +-#define MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS 0x82000006 ++#define MLNX_GET_TBB_FUSE_STATUS 0x82000006 + +-/* Reset eMMC by programming the RST_N register. */ +-#define MLXBF_BOOTCTL_SET_EMMC_RST_N 0x82000007 ++/* ++ * Initiate Firmware Reset via TYU. This might be invoked during the reset ++ * flow in isolation mode. ++ */ ++#define MLNX_HANDLE_FW_RESET 0x8200000D + +-#define MLXBF_BOOTCTL_GET_DIMM_INFO 0x82000008 ++/* ++ * SMC function IDs to set, get and reset the manufacturing information ++ * stored within the eeprom. ++ */ ++#define MLNX_HANDLE_SET_MFG_INFO 0x8200000E ++#define MLNX_HANDLE_GET_MFG_INFO 0x8200000F ++#define MLNX_HANDLE_LOCK_MFG_INFO 0x82000011 + + /* SMC function IDs for SiP Service queries */ +-#define MLXBF_BOOTCTL_SIP_SVC_CALL_COUNT 0x8200ff00 +-#define MLXBF_BOOTCTL_SIP_SVC_UID 0x8200ff01 +-#define MLXBF_BOOTCTL_SIP_SVC_VERSION 0x8200ff03 +- +-/* ARM Standard Service Calls version numbers */ +-#define MLXBF_BOOTCTL_SVC_VERSION_MAJOR 0x0 +-#define MLXBF_BOOTCTL_SVC_VERSION_MINOR 0x2 ++#define MLNX_SIP_SVC_CALL_COUNT 0x8200ff00 ++#define MLNX_SIP_SVC_UID 0x8200ff01 ++#define MLNX_SIP_SVC_VERSION 0x8200ff03 + + /* Number of svc calls defined. */ +-#define MLXBF_BOOTCTL_NUM_SVC_CALLS 12 ++#define MLNX_NUM_SVC_CALLS 16 + +-/* Valid reset actions for MLXBF_BOOTCTL_SET_RESET_ACTION. */ +-#define MLXBF_BOOTCTL_EXTERNAL 0 /* Not boot from eMMC */ +-#define MLXBF_BOOTCTL_EMMC 1 /* From primary eMMC boot partition */ +-#define MLNX_BOOTCTL_SWAP_EMMC 2 /* Swap eMMC boot partitions and reboot */ +-#define MLXBF_BOOTCTL_EMMC_LEGACY 3 /* From primary eMMC in legacy mode */ ++/* Valid reset actions for MLNX_SET_RESET_ACTION. */ ++#define MLNX_BOOT_EXTERNAL 0 /* Do not boot from eMMC */ ++#define MLNX_BOOT_EMMC 1 /* Boot from primary eMMC boot partition */ ++#define MLNX_BOOT_SWAP_EMMC 2 /* Swap eMMC boot partitions and reboot */ ++#define MLNX_BOOT_EMMC_LEGACY 3 /* Boot from primary eMMC in legacy mode */ + + /* Valid arguments for requesting the fuse status. */ +-#define MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE 0 /* Return lifecycle status. */ +-#define MLXBF_BOOTCTL_FUSE_STATUS_KEYS 1 /* Return secure boot key status */ ++#define MLNX_FUSE_STATUS_LIFECYCLE 0 /* Return the lifecycle status. */ ++#define MLNX_FUSE_STATUS_KEYS 1 /* Return secure boot key status */ + +-/* Additional value to disable the MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION. */ +-#define MLXBF_BOOTCTL_NONE 0x7fffffff /* Don't change next boot action */ ++/* Additional parameter value to disable the MLNX_SET_SECOND_RESET_ACTION. */ ++#define MLNX_BOOT_NONE 0x7fffffff /* Don't change next boot action */ + + #endif /* __MLXBF_BOOTCTL_H__ */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0212-platform-mellanox-mlxbf-pmc-Add-Mellanox-BlueField-P.patch b/platform/mellanox/non-upstream-patches/patches/0212-platform-mellanox-mlxbf-pmc-Add-Mellanox-BlueField-P.patch new file mode 100644 index 0000000000..03e53f0590 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0212-platform-mellanox-mlxbf-pmc-Add-Mellanox-BlueField-P.patch @@ -0,0 +1,1560 @@ +From 4a2c58ddcfdcff3afbc62c170c4fc7bbf73a5a9f Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Thu, 8 Oct 2020 08:37:17 -0400 +Subject: [PATCH backport 5.10 13/63] platform/mellanox: mlxbf-pmc: Add + Mellanox BlueField PMC driver + +The performance modules in BlueField are present in several hardware +blocks and each block provides access to these stats either through +counters that can be programmed to monitor supported events or +through memory-mapped registers that hold the relevant information. +The hardware blocks that include a performance module are: + * Tile (block containing 2 cores and a shared L2 cache) + * TRIO (PCIe root complex) + * MSS (Memory Sub-system containing the Memory Controller and L3 cache) + * GIC (Interrupt controller) + * SMMU (System Memory Management Unit) +The mlx_pmc driver provides access to all of these performance modules +through a hwmon sysfs interface. + +v2 --> v3 +Update copyright info. + +v1 --> v2 +Remove unused headers. +Add comma to arrays where last line is not a termination. +Use kstrtoint in place of sscanf. +UUID manipulation follows drivers/platform/mellanox/mlxbf-bootctl.c + +Signed-off-by: Shravan Kumar Ramani +Reviewed-by: Vadim Pasternak +Reviewed-by: Jiri Pirko +Link: https://lore.kernel.org/r/4e19a1e5bf4197ad27fc57981fd280eaebd23577.1602160468.git.shravankr@nvidia.com +Signed-off-by: Hans de Goede +--- + drivers/platform/mellanox/Kconfig | 10 + + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/mellanox/mlxbf-pmc.c | 1478 +++++++++++++++++++++++++ + 3 files changed, 1489 insertions(+) + create mode 100644 drivers/platform/mellanox/mlxbf-pmc.c + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index 5bd6ddd42..b0d2c3343 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -80,6 +80,16 @@ config MLXBF_BOOTCTL + to the userspace tools, to be used in conjunction with the eMMC + device driver to do necessary initial swap of the boot partition. + ++config MLXBF_PMC ++ tristate "Mellanox BlueField Performance Monitoring Counters driver" ++ depends on ARM64 ++ depends on HWMON ++ depends on ACPI ++ help ++ Say y here to enable PMC support. The PMC driver provides access ++ to performance monitoring counters within various blocks in the ++ Mellanox BlueField SoC via a sysfs interface. ++ + config NVSW_SN2201 + tristate "Nvidia SN2201 platform driver support" + depends on REGMAP +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index 23919e56a..ba56485cb 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -5,6 +5,7 @@ + # + obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o + obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o ++obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o + obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +new file mode 100644 +index 000000000..358839842 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -0,0 +1,1478 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB ++/* ++ * Mellanox BlueField Performance Monitoring Counters driver ++ * ++ * This driver provides a sysfs interface for monitoring ++ * performance statistics in BlueField SoC. ++ * ++ * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MLXBF_PMC_WRITE_REG_32 0x82000009 ++#define MLXBF_PMC_READ_REG_32 0x8200000A ++#define MLXBF_PMC_WRITE_REG_64 0x8200000B ++#define MLXBF_PMC_READ_REG_64 0x8200000C ++#define MLXBF_PMC_SIP_SVC_UID 0x8200ff01 ++#define MLXBF_PMC_SIP_SVC_VERSION 0x8200ff03 ++#define MLXBF_PMC_SVC_REQ_MAJOR 0 ++#define MLXBF_PMC_SVC_MIN_MINOR 3 ++ ++#define MLXBF_PMC_SMCCC_ACCESS_VIOLATION -4 ++ ++#define MLXBF_PMC_EVENT_SET_BF1 0 ++#define MLXBF_PMC_EVENT_SET_BF2 1 ++#define MLXBF_PMC_EVENT_INFO_LEN 100 ++ ++#define MLXBF_PMC_MAX_BLOCKS 30 ++#define MLXBF_PMC_MAX_ATTRS 30 ++#define MLXBF_PMC_INFO_SZ 4 ++#define MLXBF_PMC_REG_SIZE 8 ++#define MLXBF_PMC_L3C_REG_SIZE 4 ++ ++#define MLXBF_PMC_TYPE_COUNTER 1 ++#define MLXBF_PMC_TYPE_REGISTER 0 ++ ++#define MLXBF_PMC_PERFCTL 0 ++#define MLXBF_PMC_PERFEVT 1 ++#define MLXBF_PMC_PERFACC0 4 ++ ++#define MLXBF_PMC_PERFMON_CONFIG_WR_R_B BIT(0) ++#define MLXBF_PMC_PERFMON_CONFIG_STROBE BIT(1) ++#define MLXBF_PMC_PERFMON_CONFIG_ADDR GENMASK_ULL(4, 2) ++#define MLXBF_PMC_PERFMON_CONFIG_WDATA GENMASK_ULL(60, 5) ++ ++#define MLXBF_PMC_PERFCTL_FM0 GENMASK_ULL(18, 16) ++#define MLXBF_PMC_PERFCTL_MS0 GENMASK_ULL(21, 20) ++#define MLXBF_PMC_PERFCTL_ACCM0 GENMASK_ULL(26, 24) ++#define MLXBF_PMC_PERFCTL_AD0 BIT(27) ++#define MLXBF_PMC_PERFCTL_ETRIG0 GENMASK_ULL(29, 28) ++#define MLXBF_PMC_PERFCTL_EB0 BIT(30) ++#define MLXBF_PMC_PERFCTL_EN0 BIT(31) ++ ++#define MLXBF_PMC_PERFEVT_EVTSEL GENMASK_ULL(31, 24) ++ ++#define MLXBF_PMC_L3C_PERF_CNT_CFG 0x0 ++#define MLXBF_PMC_L3C_PERF_CNT_SEL 0x10 ++#define MLXBF_PMC_L3C_PERF_CNT_SEL_1 0x14 ++#define MLXBF_PMC_L3C_PERF_CNT_LOW 0x40 ++#define MLXBF_PMC_L3C_PERF_CNT_HIGH 0x60 ++ ++#define MLXBF_PMC_L3C_PERF_CNT_CFG_EN BIT(0) ++#define MLXBF_PMC_L3C_PERF_CNT_CFG_RST BIT(1) ++#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0 GENMASK(5, 0) ++#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1 GENMASK(13, 8) ++#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2 GENMASK(21, 16) ++#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3 GENMASK(29, 24) ++ ++#define MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4 GENMASK(5, 0) ++ ++#define MLXBF_PMC_L3C_PERF_CNT_LOW_VAL GENMASK(31, 0) ++#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0) ++ ++/** ++ * Structure to hold attribute and block info for each sysfs entry ++ * @dev_attr: Device attribute struct ++ * @index: index to identify counter number within a block ++ * @nr: block number to which the sysfs belongs ++ */ ++struct mlxbf_pmc_attribute { ++ struct device_attribute dev_attr; ++ int index; ++ int nr; ++}; ++ ++/** ++ * Structure to hold info for each HW block ++ * ++ * @mmio_base: The VA at which the PMC block is mapped ++ * @blk_size: Size of each mapped region ++ * @counters: Number of counters in the block ++ * @type: Type of counters in the block ++ * @attr_counter: Attributes for "counter" sysfs files ++ * @attr_event: Attributes for "event" sysfs files ++ * @attr_event_list: Attributes for "event_list" sysfs files ++ * @attr_enable: Attributes for "enable" sysfs files ++ * @block_attr: All attributes needed for the block ++ * @blcok_attr_grp: Attribute group for the block ++ */ ++struct mlxbf_pmc_block_info { ++ void __iomem *mmio_base; ++ size_t blk_size; ++ size_t counters; ++ int type; ++ struct mlxbf_pmc_attribute *attr_counter; ++ struct mlxbf_pmc_attribute *attr_event; ++ struct mlxbf_pmc_attribute attr_event_list; ++ struct mlxbf_pmc_attribute attr_enable; ++ struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS]; ++ struct attribute_group block_attr_grp; ++}; ++ ++/** ++ * Structure to hold PMC context info ++ * ++ * @pdev: The kernel structure representing the device ++ * @total_blocks: Total number of blocks ++ * @tile_count: Number of tiles in the system ++ * @hwmon_dev: Hwmon device for bfperf ++ * @block_name: Block name ++ * @block: Block info ++ * @groups: Attribute groups from each block ++ * @sv_sreg_support: Whether SMCs are used to access performance registers ++ * @sreg_tbl_perf: Secure register access table number ++ * @event_set: Event set to use ++ */ ++struct mlxbf_pmc_context { ++ struct platform_device *pdev; ++ uint32_t total_blocks; ++ uint32_t tile_count; ++ struct device *hwmon_dev; ++ const char *block_name[MLXBF_PMC_MAX_BLOCKS]; ++ struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS]; ++ const struct attribute_group *groups[MLXBF_PMC_MAX_BLOCKS]; ++ bool svc_sreg_support; ++ uint32_t sreg_tbl_perf; ++ unsigned int event_set; ++}; ++ ++/** ++ * Structure to hold supported events for each block ++ * @evt_num: Event number used to program counters ++ * @evt_name: Name of the event ++ */ ++struct mlxbf_pmc_events { ++ int evt_num; ++ char *evt_name; ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_pcie_events[] = { ++ { 0x0, "IN_P_PKT_CNT" }, ++ { 0x10, "IN_NP_PKT_CNT" }, ++ { 0x18, "IN_C_PKT_CNT" }, ++ { 0x20, "OUT_P_PKT_CNT" }, ++ { 0x28, "OUT_NP_PKT_CNT" }, ++ { 0x30, "OUT_C_PKT_CNT" }, ++ { 0x38, "IN_P_BYTE_CNT" }, ++ { 0x40, "IN_NP_BYTE_CNT" }, ++ { 0x48, "IN_C_BYTE_CNT" }, ++ { 0x50, "OUT_P_BYTE_CNT" }, ++ { 0x58, "OUT_NP_BYTE_CNT" }, ++ { 0x60, "OUT_C_BYTE_CNT" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_smgen_events[] = { ++ { 0x0, "AW_REQ" }, ++ { 0x1, "AW_BEATS" }, ++ { 0x2, "AW_TRANS" }, ++ { 0x3, "AW_RESP" }, ++ { 0x4, "AW_STL" }, ++ { 0x5, "AW_LAT" }, ++ { 0x6, "AW_REQ_TBU" }, ++ { 0x8, "AR_REQ" }, ++ { 0x9, "AR_BEATS" }, ++ { 0xa, "AR_TRANS" }, ++ { 0xb, "AR_STL" }, ++ { 0xc, "AR_LAT" }, ++ { 0xd, "AR_REQ_TBU" }, ++ { 0xe, "TBU_MISS" }, ++ { 0xf, "TX_DAT_AF" }, ++ { 0x10, "RX_DAT_AF" }, ++ { 0x11, "RETRYQ_CRED" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = { ++ { 0xa0, "TPIO_DATA_BEAT" }, ++ { 0xa1, "TDMA_DATA_BEAT" }, ++ { 0xa2, "MAP_DATA_BEAT" }, ++ { 0xa3, "TXMSG_DATA_BEAT" }, ++ { 0xa4, "TPIO_DATA_PACKET" }, ++ { 0xa5, "TDMA_DATA_PACKET" }, ++ { 0xa6, "MAP_DATA_PACKET" }, ++ { 0xa7, "TXMSG_DATA_PACKET" }, ++ { 0xa8, "TDMA_RT_AF" }, ++ { 0xa9, "TDMA_PBUF_MAC_AF" }, ++ { 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" }, ++ { 0xab, "TRIO_MAP_CPL_BUF_EMPTY" }, ++ { 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" }, ++ { 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" }, ++ { 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" }, ++ { 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" }, ++ { 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" }, ++ { 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" }, ++ { 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" }, ++ { 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = { ++ { 0xa0, "TPIO_DATA_BEAT" }, ++ { 0xa1, "TDMA_DATA_BEAT" }, ++ { 0xa2, "MAP_DATA_BEAT" }, ++ { 0xa3, "TXMSG_DATA_BEAT" }, ++ { 0xa4, "TPIO_DATA_PACKET" }, ++ { 0xa5, "TDMA_DATA_PACKET" }, ++ { 0xa6, "MAP_DATA_PACKET" }, ++ { 0xa7, "TXMSG_DATA_PACKET" }, ++ { 0xa8, "TDMA_RT_AF" }, ++ { 0xa9, "TDMA_PBUF_MAC_AF" }, ++ { 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" }, ++ { 0xab, "TRIO_MAP_CPL_BUF_EMPTY" }, ++ { 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" }, ++ { 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" }, ++ { 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" }, ++ { 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" }, ++ { 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" }, ++ { 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" }, ++ { 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" }, ++ { 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" }, ++ { 0xb4, "TRIO_RING_TX_FLIT_CH0" }, ++ { 0xb5, "TRIO_RING_TX_FLIT_CH1" }, ++ { 0xb6, "TRIO_RING_TX_FLIT_CH2" }, ++ { 0xb7, "TRIO_RING_TX_FLIT_CH3" }, ++ { 0xb8, "TRIO_RING_TX_FLIT_CH4" }, ++ { 0xb9, "TRIO_RING_RX_FLIT_CH0" }, ++ { 0xba, "TRIO_RING_RX_FLIT_CH1" }, ++ { 0xbb, "TRIO_RING_RX_FLIT_CH2" }, ++ { 0xbc, "TRIO_RING_RX_FLIT_CH3" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = { ++ { 0x100, "ECC_SINGLE_ERROR_CNT" }, ++ { 0x104, "ECC_DOUBLE_ERROR_CNT" }, ++ { 0x114, "SERR_INJ" }, ++ { 0x118, "DERR_INJ" }, ++ { 0x124, "ECC_SINGLE_ERROR_0" }, ++ { 0x164, "ECC_DOUBLE_ERROR_0" }, ++ { 0x340, "DRAM_ECC_COUNT" }, ++ { 0x344, "DRAM_ECC_INJECT" }, ++ { 0x348, "DRAM_ECC_ERROR" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = { ++ { 0xc0, "RXREQ_MSS" }, ++ { 0xc1, "RXDAT_MSS" }, ++ { 0xc2, "TXRSP_MSS" }, ++ { 0xc3, "TXDAT_MSS" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = { ++ { 0x45, "HNF_REQUESTS" }, ++ { 0x46, "HNF_REJECTS" }, ++ { 0x47, "ALL_BUSY" }, ++ { 0x48, "MAF_BUSY" }, ++ { 0x49, "MAF_REQUESTS" }, ++ { 0x4a, "RNF_REQUESTS" }, ++ { 0x4b, "REQUEST_TYPE" }, ++ { 0x4c, "MEMORY_READS" }, ++ { 0x4d, "MEMORY_WRITES" }, ++ { 0x4e, "VICTIM_WRITE" }, ++ { 0x4f, "POC_FULL" }, ++ { 0x50, "POC_FAIL" }, ++ { 0x51, "POC_SUCCESS" }, ++ { 0x52, "POC_WRITES" }, ++ { 0x53, "POC_READS" }, ++ { 0x54, "FORWARD" }, ++ { 0x55, "RXREQ_HNF" }, ++ { 0x56, "RXRSP_HNF" }, ++ { 0x57, "RXDAT_HNF" }, ++ { 0x58, "TXREQ_HNF" }, ++ { 0x59, "TXRSP_HNF" }, ++ { 0x5a, "TXDAT_HNF" }, ++ { 0x5b, "TXSNP_HNF" }, ++ { 0x5c, "INDEX_MATCH" }, ++ { 0x5d, "A72_ACCESS" }, ++ { 0x5e, "IO_ACCESS" }, ++ { 0x5f, "TSO_WRITE" }, ++ { 0x60, "TSO_CONFLICT" }, ++ { 0x61, "DIR_HIT" }, ++ { 0x62, "HNF_ACCEPTS" }, ++ { 0x63, "REQ_BUF_EMPTY" }, ++ { 0x64, "REQ_BUF_IDLE_MAF" }, ++ { 0x65, "TSO_NOARB" }, ++ { 0x66, "TSO_NOARB_CYCLES" }, ++ { 0x67, "MSS_NO_CREDIT" }, ++ { 0x68, "TXDAT_NO_LCRD" }, ++ { 0x69, "TXSNP_NO_LCRD" }, ++ { 0x6a, "TXRSP_NO_LCRD" }, ++ { 0x6b, "TXREQ_NO_LCRD" }, ++ { 0x6c, "TSO_CL_MATCH" }, ++ { 0x6d, "MEMORY_READS_BYPASS" }, ++ { 0x6e, "TSO_NOARB_TIMEOUT" }, ++ { 0x6f, "ALLOCATE" }, ++ { 0x70, "VICTIM" }, ++ { 0x71, "A72_WRITE" }, ++ { 0x72, "A72_READ" }, ++ { 0x73, "IO_WRITE" }, ++ { 0x74, "IO_READ" }, ++ { 0x75, "TSO_REJECT" }, ++ { 0x80, "TXREQ_RN" }, ++ { 0x81, "TXRSP_RN" }, ++ { 0x82, "TXDAT_RN" }, ++ { 0x83, "RXSNP_RN" }, ++ { 0x84, "RXRSP_RN" }, ++ { 0x85, "RXDAT_RN" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = { ++ { 0x12, "CDN_REQ" }, ++ { 0x13, "DDN_REQ" }, ++ { 0x14, "NDN_REQ" }, ++ { 0x15, "CDN_DIAG_N_OUT_OF_CRED" }, ++ { 0x16, "CDN_DIAG_S_OUT_OF_CRED" }, ++ { 0x17, "CDN_DIAG_E_OUT_OF_CRED" }, ++ { 0x18, "CDN_DIAG_W_OUT_OF_CRED" }, ++ { 0x19, "CDN_DIAG_C_OUT_OF_CRED" }, ++ { 0x1a, "CDN_DIAG_N_EGRESS" }, ++ { 0x1b, "CDN_DIAG_S_EGRESS" }, ++ { 0x1c, "CDN_DIAG_E_EGRESS" }, ++ { 0x1d, "CDN_DIAG_W_EGRESS" }, ++ { 0x1e, "CDN_DIAG_C_EGRESS" }, ++ { 0x1f, "CDN_DIAG_N_INGRESS" }, ++ { 0x20, "CDN_DIAG_S_INGRESS" }, ++ { 0x21, "CDN_DIAG_E_INGRESS" }, ++ { 0x22, "CDN_DIAG_W_INGRESS" }, ++ { 0x23, "CDN_DIAG_C_INGRESS" }, ++ { 0x24, "CDN_DIAG_CORE_SENT" }, ++ { 0x25, "DDN_DIAG_N_OUT_OF_CRED" }, ++ { 0x26, "DDN_DIAG_S_OUT_OF_CRED" }, ++ { 0x27, "DDN_DIAG_E_OUT_OF_CRED" }, ++ { 0x28, "DDN_DIAG_W_OUT_OF_CRED" }, ++ { 0x29, "DDN_DIAG_C_OUT_OF_CRED" }, ++ { 0x2a, "DDN_DIAG_N_EGRESS" }, ++ { 0x2b, "DDN_DIAG_S_EGRESS" }, ++ { 0x2c, "DDN_DIAG_E_EGRESS" }, ++ { 0x2d, "DDN_DIAG_W_EGRESS" }, ++ { 0x2e, "DDN_DIAG_C_EGRESS" }, ++ { 0x2f, "DDN_DIAG_N_INGRESS" }, ++ { 0x30, "DDN_DIAG_S_INGRESS" }, ++ { 0x31, "DDN_DIAG_E_INGRESS" }, ++ { 0x32, "DDN_DIAG_W_INGRESS" }, ++ { 0x33, "DDN_DIAG_C_INGRESS" }, ++ { 0x34, "DDN_DIAG_CORE_SENT" }, ++ { 0x35, "NDN_DIAG_S_OUT_OF_CRED" }, ++ { 0x36, "NDN_DIAG_S_OUT_OF_CRED" }, ++ { 0x37, "NDN_DIAG_E_OUT_OF_CRED" }, ++ { 0x38, "NDN_DIAG_W_OUT_OF_CRED" }, ++ { 0x39, "NDN_DIAG_C_OUT_OF_CRED" }, ++ { 0x3a, "NDN_DIAG_N_EGRESS" }, ++ { 0x3b, "NDN_DIAG_S_EGRESS" }, ++ { 0x3c, "NDN_DIAG_E_EGRESS" }, ++ { 0x3d, "NDN_DIAG_W_EGRESS" }, ++ { 0x3e, "NDN_DIAG_C_EGRESS" }, ++ { 0x3f, "NDN_DIAG_N_INGRESS" }, ++ { 0x40, "NDN_DIAG_S_INGRESS" }, ++ { 0x41, "NDN_DIAG_E_INGRESS" }, ++ { 0x42, "NDN_DIAG_W_INGRESS" }, ++ { 0x43, "NDN_DIAG_C_INGRESS" }, ++ { 0x44, "NDN_DIAG_CORE_SENT" }, ++}; ++ ++static const struct mlxbf_pmc_events mlxbf_pmc_l3c_events[] = { ++ { 0x00, "DISABLE" }, ++ { 0x01, "CYCLES" }, ++ { 0x02, "TOTAL_RD_REQ_IN" }, ++ { 0x03, "TOTAL_WR_REQ_IN" }, ++ { 0x04, "TOTAL_WR_DBID_ACK" }, ++ { 0x05, "TOTAL_WR_DATA_IN" }, ++ { 0x06, "TOTAL_WR_COMP" }, ++ { 0x07, "TOTAL_RD_DATA_OUT" }, ++ { 0x08, "TOTAL_CDN_REQ_IN_BANK0" }, ++ { 0x09, "TOTAL_CDN_REQ_IN_BANK1" }, ++ { 0x0a, "TOTAL_DDN_REQ_IN_BANK0" }, ++ { 0x0b, "TOTAL_DDN_REQ_IN_BANK1" }, ++ { 0x0c, "TOTAL_EMEM_RD_RES_IN_BANK0" }, ++ { 0x0d, "TOTAL_EMEM_RD_RES_IN_BANK1" }, ++ { 0x0e, "TOTAL_CACHE_RD_RES_IN_BANK0" }, ++ { 0x0f, "TOTAL_CACHE_RD_RES_IN_BANK1" }, ++ { 0x10, "TOTAL_EMEM_RD_REQ_BANK0" }, ++ { 0x11, "TOTAL_EMEM_RD_REQ_BANK1" }, ++ { 0x12, "TOTAL_EMEM_WR_REQ_BANK0" }, ++ { 0x13, "TOTAL_EMEM_WR_REQ_BANK1" }, ++ { 0x14, "TOTAL_RD_REQ_OUT" }, ++ { 0x15, "TOTAL_WR_REQ_OUT" }, ++ { 0x16, "TOTAL_RD_RES_IN" }, ++ { 0x17, "HITS_BANK0" }, ++ { 0x18, "HITS_BANK1" }, ++ { 0x19, "MISSES_BANK0" }, ++ { 0x1a, "MISSES_BANK1" }, ++ { 0x1b, "ALLOCATIONS_BANK0" }, ++ { 0x1c, "ALLOCATIONS_BANK1" }, ++ { 0x1d, "EVICTIONS_BANK0" }, ++ { 0x1e, "EVICTIONS_BANK1" }, ++ { 0x1f, "DBID_REJECT" }, ++ { 0x20, "WRDB_REJECT_BANK0" }, ++ { 0x21, "WRDB_REJECT_BANK1" }, ++ { 0x22, "CMDQ_REJECT_BANK0" }, ++ { 0x23, "CMDQ_REJECT_BANK1" }, ++ { 0x24, "COB_REJECT_BANK0" }, ++ { 0x25, "COB_REJECT_BANK1" }, ++ { 0x26, "TRB_REJECT_BANK0" }, ++ { 0x27, "TRB_REJECT_BANK1" }, ++ { 0x28, "TAG_REJECT_BANK0" }, ++ { 0x29, "TAG_REJECT_BANK1" }, ++ { 0x2a, "ANY_REJECT_BANK0" }, ++ { 0x2b, "ANY_REJECT_BANK1" }, ++}; ++ ++static struct mlxbf_pmc_context *pmc; ++ ++/* UUID used to probe ATF service. */ ++static const char *mlxbf_pmc_svc_uuid_str = "89c036b4-e7d7-11e6-8797-001aca00bfc4"; ++ ++/* Calls an SMC to access a performance register */ ++static int mlxbf_pmc_secure_read(void __iomem *addr, uint32_t command, ++ uint64_t *result) ++{ ++ struct arm_smccc_res res; ++ int status, err = 0; ++ ++ arm_smccc_smc(command, pmc->sreg_tbl_perf, (uintptr_t)addr, 0, 0, 0, 0, ++ 0, &res); ++ ++ status = res.a0; ++ ++ switch (status) { ++ case PSCI_RET_NOT_SUPPORTED: ++ err = -EINVAL; ++ break; ++ case MLXBF_PMC_SMCCC_ACCESS_VIOLATION: ++ err = -EACCES; ++ break; ++ default: ++ *result = res.a1; ++ break; ++ } ++ ++ return err; ++} ++ ++/* Read from a performance counter */ ++static int mlxbf_pmc_read(void __iomem *addr, uint32_t command, ++ uint64_t *result) ++{ ++ if (pmc->svc_sreg_support) ++ return mlxbf_pmc_secure_read(addr, command, result); ++ ++ if (command == MLXBF_PMC_READ_REG_32) ++ *result = readl(addr); ++ else ++ *result = readq(addr); ++ ++ return 0; ++} ++ ++/* Convenience function for 32-bit reads */ ++static int mlxbf_pmc_readl(void __iomem *addr, uint32_t *result) ++{ ++ uint64_t read_out; ++ int status; ++ ++ status = mlxbf_pmc_read(addr, MLXBF_PMC_READ_REG_32, &read_out); ++ if (status) ++ return status; ++ *result = (uint32_t)read_out; ++ ++ return 0; ++} ++ ++/* Calls an SMC to access a performance register */ ++static int mlxbf_pmc_secure_write(void __iomem *addr, uint32_t command, ++ uint64_t value) ++{ ++ struct arm_smccc_res res; ++ int status, err = 0; ++ ++ arm_smccc_smc(command, pmc->sreg_tbl_perf, value, (uintptr_t)addr, 0, 0, ++ 0, 0, &res); ++ ++ status = res.a0; ++ ++ switch (status) { ++ case PSCI_RET_NOT_SUPPORTED: ++ err = -EINVAL; ++ break; ++ case MLXBF_PMC_SMCCC_ACCESS_VIOLATION: ++ err = -EACCES; ++ break; ++ } ++ ++ return err; ++} ++ ++/* Write to a performance counter */ ++static int mlxbf_pmc_write(void __iomem *addr, int command, uint64_t value) ++{ ++ if (pmc->svc_sreg_support) ++ return mlxbf_pmc_secure_write(addr, command, value); ++ ++ if (command == MLXBF_PMC_WRITE_REG_32) ++ writel(value, addr); ++ else ++ writeq(value, addr); ++ ++ return 0; ++} ++ ++/* Check if the register offset is within the mapped region for the block */ ++static bool mlxbf_pmc_valid_range(int blk_num, uint32_t offset) ++{ ++ if ((offset >= 0) && !(offset % MLXBF_PMC_REG_SIZE) && ++ (offset + MLXBF_PMC_REG_SIZE <= pmc->block[blk_num].blk_size)) ++ return true; /* inside the mapped PMC space */ ++ ++ return false; ++} ++ ++/* Get the event list corresponding to a certain block */ ++static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk, ++ int *size) ++{ ++ const struct mlxbf_pmc_events *events; ++ ++ if (strstr(blk, "tilenet")) { ++ events = mlxbf_pmc_hnfnet_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_hnfnet_events); ++ } else if (strstr(blk, "tile")) { ++ events = mlxbf_pmc_hnf_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_hnf_events); ++ } else if (strstr(blk, "triogen")) { ++ events = mlxbf_pmc_smgen_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_smgen_events); ++ } else if (strstr(blk, "trio")) { ++ switch (pmc->event_set) { ++ case MLXBF_PMC_EVENT_SET_BF1: ++ events = mlxbf_pmc_trio_events_1; ++ *size = ARRAY_SIZE(mlxbf_pmc_trio_events_1); ++ break; ++ case MLXBF_PMC_EVENT_SET_BF2: ++ events = mlxbf_pmc_trio_events_2; ++ *size = ARRAY_SIZE(mlxbf_pmc_trio_events_2); ++ break; ++ default: ++ events = NULL; ++ *size = 0; ++ break; ++ } ++ } else if (strstr(blk, "mss")) { ++ events = mlxbf_pmc_mss_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_mss_events); ++ } else if (strstr(blk, "ecc")) { ++ events = mlxbf_pmc_ecc_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_ecc_events); ++ } else if (strstr(blk, "pcie")) { ++ events = mlxbf_pmc_pcie_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_pcie_events); ++ } else if (strstr(blk, "l3cache")) { ++ events = mlxbf_pmc_l3c_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_l3c_events); ++ } else if (strstr(blk, "gic")) { ++ events = mlxbf_pmc_smgen_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_smgen_events); ++ } else if (strstr(blk, "smmu")) { ++ events = mlxbf_pmc_smgen_events; ++ *size = ARRAY_SIZE(mlxbf_pmc_smgen_events); ++ } else { ++ events = NULL; ++ *size = 0; ++ } ++ ++ return events; ++} ++ ++/* Get the event number given the name */ ++static int mlxbf_pmc_get_event_num(const char *blk, const char *evt) ++{ ++ const struct mlxbf_pmc_events *events; ++ int i, size; ++ ++ events = mlxbf_pmc_event_list(blk, &size); ++ if (!events) ++ return -EINVAL; ++ ++ for (i = 0; i < size; ++i) { ++ if (!strcmp(evt, events[i].evt_name)) ++ return events[i].evt_num; ++ } ++ ++ return -ENODEV; ++} ++ ++/* Get the event number given the name */ ++static char *mlxbf_pmc_get_event_name(const char *blk, int evt) ++{ ++ const struct mlxbf_pmc_events *events; ++ int i, size; ++ ++ events = mlxbf_pmc_event_list(blk, &size); ++ if (!events) ++ return NULL; ++ ++ for (i = 0; i < size; ++i) { ++ if (evt == events[i].evt_num) ++ return events[i].evt_name; ++ } ++ ++ return NULL; ++} ++ ++/* Method to enable/disable/reset l3cache counters */ ++static int mlxbf_pmc_config_l3_counters(int blk_num, bool enable, bool reset) ++{ ++ uint32_t perfcnt_cfg = 0; ++ ++ if (enable) ++ perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_EN; ++ if (reset) ++ perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_RST; ++ ++ return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_CFG, ++ MLXBF_PMC_WRITE_REG_32, perfcnt_cfg); ++} ++ ++/* Method to handle l3cache counter programming */ ++static int mlxbf_pmc_program_l3_counter(int blk_num, uint32_t cnt_num, ++ uint32_t evt) ++{ ++ uint32_t perfcnt_sel_1 = 0; ++ uint32_t perfcnt_sel = 0; ++ uint32_t *wordaddr; ++ void __iomem *pmcaddr; ++ int ret; ++ ++ /* Disable all counters before programming them */ ++ if (mlxbf_pmc_config_l3_counters(blk_num, false, false)) ++ return -EINVAL; ++ ++ /* Select appropriate register information */ ++ switch (cnt_num) { ++ case 0 ... 3: ++ pmcaddr = pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_SEL; ++ wordaddr = &perfcnt_sel; ++ break; ++ case 4: ++ pmcaddr = pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_SEL_1; ++ wordaddr = &perfcnt_sel_1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = mlxbf_pmc_readl(pmcaddr, wordaddr); ++ if (ret) ++ return ret; ++ ++ switch (cnt_num) { ++ case 0: ++ perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0; ++ perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, ++ evt); ++ break; ++ case 1: ++ perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1; ++ perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, ++ evt); ++ break; ++ case 2: ++ perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2; ++ perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, ++ evt); ++ break; ++ case 3: ++ perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3; ++ perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, ++ evt); ++ break; ++ case 4: ++ perfcnt_sel_1 &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4; ++ perfcnt_sel_1 |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4, ++ evt); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return mlxbf_pmc_write(pmcaddr, MLXBF_PMC_WRITE_REG_32, *wordaddr); ++} ++ ++/* Method to program a counter to monitor an event */ ++static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num, ++ uint32_t evt, bool is_l3) ++{ ++ uint64_t perfctl, perfevt, perfmon_cfg; ++ ++ if (cnt_num >= pmc->block[blk_num].counters) ++ return -ENODEV; ++ ++ if (is_l3) ++ return mlxbf_pmc_program_l3_counter(blk_num, cnt_num, evt); ++ ++ /* Configure the counter */ ++ perfctl = FIELD_PREP(MLXBF_PMC_PERFCTL_EN0, 1); ++ perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_EB0, 0); ++ perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ETRIG0, 1); ++ perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_AD0, 0); ++ perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ACCM0, 0); ++ perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_MS0, 0); ++ perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_FM0, 0); ++ ++ perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfctl); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, ++ MLXBF_PMC_PERFCTL); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); ++ ++ if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + ++ cnt_num * MLXBF_PMC_REG_SIZE, ++ MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ return -EFAULT; ++ ++ /* Select the event */ ++ perfevt = FIELD_PREP(MLXBF_PMC_PERFEVT_EVTSEL, evt); ++ ++ perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfevt); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, ++ MLXBF_PMC_PERFEVT); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); ++ ++ if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + ++ cnt_num * MLXBF_PMC_REG_SIZE, ++ MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ return -EFAULT; ++ ++ /* Clear the accumulator */ ++ perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, ++ MLXBF_PMC_PERFACC0); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); ++ ++ if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + ++ cnt_num * MLXBF_PMC_REG_SIZE, ++ MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++/* Method to handle l3 counter reads */ ++static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num, ++ uint64_t *result) ++{ ++ uint32_t perfcnt_low = 0, perfcnt_high = 0; ++ uint64_t value; ++ int status = 0; ++ ++ status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_LOW + ++ cnt_num * MLXBF_PMC_L3C_REG_SIZE, ++ &perfcnt_low); ++ ++ if (status) ++ return status; ++ ++ status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_HIGH + ++ cnt_num * MLXBF_PMC_L3C_REG_SIZE, ++ &perfcnt_high); ++ ++ if (status) ++ return status; ++ ++ value = perfcnt_high; ++ value = value << 32; ++ value |= perfcnt_low; ++ *result = value; ++ ++ return 0; ++} ++ ++/* Method to read the counter value */ ++static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3, ++ uint64_t *result) ++{ ++ uint32_t perfcfg_offset, perfval_offset; ++ uint64_t perfmon_cfg; ++ int status; ++ ++ if (cnt_num >= pmc->block[blk_num].counters) ++ return -EINVAL; ++ ++ if (is_l3) ++ return mlxbf_pmc_read_l3_counter(blk_num, cnt_num, result); ++ ++ perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE; ++ perfval_offset = perfcfg_offset + ++ pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE; ++ ++ /* Set counter in "read" mode */ ++ perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, ++ MLXBF_PMC_PERFACC0); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); ++ ++ status = mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, ++ MLXBF_PMC_WRITE_REG_64, perfmon_cfg); ++ ++ if (status) ++ return status; ++ ++ /* Get the counter value */ ++ return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, ++ MLXBF_PMC_READ_REG_64, result); ++} ++ ++/* Method to read L3 block event */ ++static int mlxbf_pmc_read_l3_event(int blk_num, uint32_t cnt_num, ++ uint64_t *result) ++{ ++ uint32_t perfcnt_sel = 0, perfcnt_sel_1 = 0; ++ uint32_t *wordaddr; ++ void __iomem *pmcaddr; ++ uint64_t evt; ++ ++ /* Select appropriate register information */ ++ switch (cnt_num) { ++ case 0 ... 3: ++ pmcaddr = pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_SEL; ++ wordaddr = &perfcnt_sel; ++ break; ++ case 4: ++ pmcaddr = pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_SEL_1; ++ wordaddr = &perfcnt_sel_1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (mlxbf_pmc_readl(pmcaddr, wordaddr)) ++ return -EINVAL; ++ ++ /* Read from appropriate register field for the counter */ ++ switch (cnt_num) { ++ case 0: ++ evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, perfcnt_sel); ++ break; ++ case 1: ++ evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, perfcnt_sel); ++ break; ++ case 2: ++ evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, perfcnt_sel); ++ break; ++ case 3: ++ evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, perfcnt_sel); ++ break; ++ case 4: ++ evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4, ++ perfcnt_sel_1); ++ break; ++ default: ++ return -EINVAL; ++ } ++ *result = evt; ++ ++ return 0; ++} ++ ++/* Method to find the event currently being monitored by a counter */ ++static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3, ++ uint64_t *result) ++{ ++ uint32_t perfcfg_offset, perfval_offset; ++ uint64_t perfmon_cfg, perfevt, perfctl; ++ ++ if (cnt_num >= pmc->block[blk_num].counters) ++ return -EINVAL; ++ ++ if (is_l3) ++ return mlxbf_pmc_read_l3_event(blk_num, cnt_num, result); ++ ++ perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE; ++ perfval_offset = perfcfg_offset + ++ pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE; ++ ++ /* Set counter in "read" mode */ ++ perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, ++ MLXBF_PMC_PERFCTL); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); ++ ++ if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, ++ MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ return -EFAULT; ++ ++ /* Check if the counter is enabled */ ++ ++ if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, ++ MLXBF_PMC_READ_REG_64, &perfctl)) ++ return -EFAULT; ++ ++ if (!FIELD_GET(MLXBF_PMC_PERFCTL_EN0, perfctl)) ++ return -EINVAL; ++ ++ /* Set counter in "read" mode */ ++ perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, ++ MLXBF_PMC_PERFEVT); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); ++ ++ if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, ++ MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ return -EFAULT; ++ ++ /* Get the event number */ ++ if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, ++ MLXBF_PMC_READ_REG_64, &perfevt)) ++ return -EFAULT; ++ ++ *result = FIELD_GET(MLXBF_PMC_PERFEVT_EVTSEL, perfevt); ++ ++ return 0; ++} ++ ++/* Method to read a register */ ++static int mlxbf_pmc_read_reg(int blk_num, uint32_t offset, uint64_t *result) ++{ ++ uint32_t ecc_out; ++ ++ if (strstr(pmc->block_name[blk_num], "ecc")) { ++ if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + offset, ++ &ecc_out)) ++ return -EFAULT; ++ ++ *result = ecc_out; ++ return 0; ++ } ++ ++ if (mlxbf_pmc_valid_range(blk_num, offset)) ++ return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + offset, ++ MLXBF_PMC_READ_REG_64, result); ++ ++ return -EINVAL; ++} ++ ++/* Method to write to a register */ ++static int mlxbf_pmc_write_reg(int blk_num, uint32_t offset, uint64_t data) ++{ ++ if (strstr(pmc->block_name[blk_num], "ecc")) { ++ return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, ++ MLXBF_PMC_WRITE_REG_32, data); ++ } ++ ++ if (mlxbf_pmc_valid_range(blk_num, offset)) ++ return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, ++ MLXBF_PMC_WRITE_REG_64, data); ++ ++ return -EINVAL; ++} ++ ++/* Show function for "counter" sysfs files */ ++static ssize_t mlxbf_pmc_counter_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct mlxbf_pmc_attribute *attr_counter = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ int blk_num, cnt_num, offset; ++ bool is_l3 = false; ++ uint64_t value; ++ ++ blk_num = attr_counter->nr; ++ cnt_num = attr_counter->index; ++ ++ if (strstr(pmc->block_name[blk_num], "l3cache")) ++ is_l3 = true; ++ ++ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) { ++ if (mlxbf_pmc_read_counter(blk_num, cnt_num, is_l3, &value)) ++ return -EINVAL; ++ } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) { ++ offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], ++ attr->attr.name); ++ if (offset < 0) ++ return -EINVAL; ++ if (mlxbf_pmc_read_reg(blk_num, offset, &value)) ++ return -EINVAL; ++ } else ++ return -EINVAL; ++ ++ return sprintf(buf, "0x%llx\n", value); ++} ++ ++/* Store function for "counter" sysfs files */ ++static ssize_t mlxbf_pmc_counter_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct mlxbf_pmc_attribute *attr_counter = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ int blk_num, cnt_num, offset, err, data; ++ bool is_l3 = false; ++ uint64_t evt_num; ++ ++ blk_num = attr_counter->nr; ++ cnt_num = attr_counter->index; ++ ++ err = kstrtoint(buf, 0, &data); ++ if (err < 0) ++ return err; ++ ++ /* Allow non-zero writes only to the ecc regs */ ++ if (!(strstr(pmc->block_name[blk_num], "ecc")) && data) ++ return -EINVAL; ++ ++ /* Do not allow writes to the L3C regs */ ++ if (strstr(pmc->block_name[blk_num], "l3cache")) ++ return -EINVAL; ++ ++ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) { ++ err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num); ++ if (err) ++ return err; ++ err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, ++ is_l3); ++ if (err) ++ return err; ++ } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) { ++ offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], ++ attr->attr.name); ++ if (offset < 0) ++ return -EINVAL; ++ err = mlxbf_pmc_write_reg(blk_num, offset, data); ++ if (err) ++ return err; ++ } else ++ return -EINVAL; ++ ++ return count; ++} ++ ++/* Show function for "event" sysfs files */ ++static ssize_t mlxbf_pmc_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct mlxbf_pmc_attribute *attr_event = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ int blk_num, cnt_num, err; ++ bool is_l3 = false; ++ uint64_t evt_num; ++ char *evt_name; ++ ++ blk_num = attr_event->nr; ++ cnt_num = attr_event->index; ++ ++ if (strstr(pmc->block_name[blk_num], "l3cache")) ++ is_l3 = true; ++ ++ err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num); ++ if (err) ++ return sprintf(buf, "No event being monitored\n"); ++ ++ evt_name = mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num); ++ if (!evt_name) ++ return -EINVAL; ++ ++ return sprintf(buf, "0x%llx: %s\n", evt_num, evt_name); ++} ++ ++/* Store function for "event" sysfs files */ ++static ssize_t mlxbf_pmc_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct mlxbf_pmc_attribute *attr_event = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ int blk_num, cnt_num, evt_num, err; ++ bool is_l3 = false; ++ ++ blk_num = attr_event->nr; ++ cnt_num = attr_event->index; ++ ++ if (isalpha(buf[0])) { ++ evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], ++ buf); ++ if (evt_num < 0) ++ return -EINVAL; ++ } else { ++ err = kstrtoint(buf, 0, &evt_num); ++ if (err < 0) ++ return err; ++ } ++ ++ if (strstr(pmc->block_name[blk_num], "l3cache")) ++ is_l3 = true; ++ ++ err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, is_l3); ++ if (err) ++ return err; ++ ++ return count; ++} ++ ++/* Show function for "event_list" sysfs files */ ++static ssize_t mlxbf_pmc_event_list_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct mlxbf_pmc_attribute *attr_event_list = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ int blk_num, i, size, len = 0, ret = 0; ++ const struct mlxbf_pmc_events *events; ++ char e_info[MLXBF_PMC_EVENT_INFO_LEN]; ++ ++ blk_num = attr_event_list->nr; ++ ++ events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &size); ++ if (!events) ++ return -EINVAL; ++ ++ for (i = 0, buf[0] = '\0'; i < size; ++i) { ++ len += sprintf(e_info, "0x%x: %s\n", events[i].evt_num, ++ events[i].evt_name); ++ if (len > PAGE_SIZE) ++ break; ++ strcat(buf, e_info); ++ ret = len; ++ } ++ ++ return ret; ++} ++ ++/* Show function for "enable" sysfs files - only for l3cache */ ++static ssize_t mlxbf_pmc_enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct mlxbf_pmc_attribute *attr_enable = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ uint32_t perfcnt_cfg; ++ int blk_num, value; ++ ++ blk_num = attr_enable->nr; ++ ++ if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + ++ MLXBF_PMC_L3C_PERF_CNT_CFG, ++ &perfcnt_cfg)) ++ return -EINVAL; ++ ++ value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg); ++ ++ return sprintf(buf, "%d\n", value); ++} ++ ++/* Store function for "enable" sysfs files - only for l3cache */ ++static ssize_t mlxbf_pmc_enable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct mlxbf_pmc_attribute *attr_enable = container_of( ++ attr, struct mlxbf_pmc_attribute, dev_attr); ++ int err, en, blk_num; ++ ++ blk_num = attr_enable->nr; ++ ++ err = kstrtoint(buf, 0, &en); ++ if (err < 0) ++ return err; ++ ++ if (!en) { ++ err = mlxbf_pmc_config_l3_counters(blk_num, false, false); ++ if (err) ++ return err; ++ } else if (en == 1) { ++ err = mlxbf_pmc_config_l3_counters(blk_num, false, true); ++ if (err) ++ return err; ++ err = mlxbf_pmc_config_l3_counters(blk_num, true, false); ++ if (err) ++ return err; ++ } else ++ return -EINVAL; ++ ++ return count; ++} ++ ++/* Populate attributes for blocks with counters to monitor performance */ ++static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num) ++{ ++ struct mlxbf_pmc_attribute *attr; ++ int i = 0, j = 0; ++ ++ /* "event_list" sysfs to list events supported by the block */ ++ attr = &pmc->block[blk_num].attr_event_list; ++ attr->dev_attr.attr.mode = 0444; ++ attr->dev_attr.show = mlxbf_pmc_event_list_show; ++ attr->nr = blk_num; ++ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list"); ++ pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr; ++ attr = NULL; ++ ++ /* "enable" sysfs to start/stop the counters. Only in L3C blocks */ ++ if (strstr(pmc->block_name[blk_num], "l3cache")) { ++ attr = &pmc->block[blk_num].attr_enable; ++ attr->dev_attr.attr.mode = 0644; ++ attr->dev_attr.show = mlxbf_pmc_enable_show; ++ attr->dev_attr.store = mlxbf_pmc_enable_store; ++ attr->nr = blk_num; ++ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, ++ "enable"); ++ pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; ++ attr = NULL; ++ } ++ ++ pmc->block[blk_num].attr_counter = devm_kcalloc( ++ dev, pmc->block[blk_num].counters, ++ sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); ++ if (!pmc->block[blk_num].attr_counter) ++ return -ENOMEM; ++ ++ pmc->block[blk_num].attr_event = devm_kcalloc( ++ dev, pmc->block[blk_num].counters, ++ sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); ++ if (!pmc->block[blk_num].attr_event) ++ return -ENOMEM; ++ ++ /* "eventX" and "counterX" sysfs to program and read counter values */ ++ for (j = 0; j < pmc->block[blk_num].counters; ++j) { ++ attr = &pmc->block[blk_num].attr_counter[j]; ++ attr->dev_attr.attr.mode = 0644; ++ attr->dev_attr.show = mlxbf_pmc_counter_show; ++ attr->dev_attr.store = mlxbf_pmc_counter_store; ++ attr->index = j; ++ attr->nr = blk_num; ++ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, ++ "counter%d", j); ++ pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; ++ attr = NULL; ++ ++ attr = &pmc->block[blk_num].attr_event[j]; ++ attr->dev_attr.attr.mode = 0644; ++ attr->dev_attr.show = mlxbf_pmc_event_show; ++ attr->dev_attr.store = mlxbf_pmc_event_store; ++ attr->index = j; ++ attr->nr = blk_num; ++ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, ++ "event%d", j); ++ pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; ++ attr = NULL; ++ } ++ ++ return 0; ++} ++ ++/* Populate attributes for blocks with registers to monitor performance */ ++static int mlxbf_pmc_init_perftype_reg(struct device *dev, int blk_num) ++{ ++ struct mlxbf_pmc_attribute *attr; ++ const struct mlxbf_pmc_events *events; ++ int i = 0, j = 0; ++ ++ events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &j); ++ if (!events) ++ return -EINVAL; ++ ++ pmc->block[blk_num].attr_event = devm_kcalloc( ++ dev, j, sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); ++ if (!pmc->block[blk_num].attr_event) ++ return -ENOMEM; ++ ++ while (j > 0) { ++ --j; ++ attr = &pmc->block[blk_num].attr_event[j]; ++ attr->dev_attr.attr.mode = 0644; ++ attr->dev_attr.show = mlxbf_pmc_counter_show; ++ attr->dev_attr.store = mlxbf_pmc_counter_store; ++ attr->nr = blk_num; ++ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, ++ events[j].evt_name); ++ pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr; ++ attr = NULL; ++ i++; ++ } ++ ++ return 0; ++} ++ ++/* Helper to create the bfperf sysfs sub-directories and files */ ++static int mlxbf_pmc_create_groups(struct device *dev, int blk_num) ++{ ++ int err; ++ ++ /* Populate attributes based on counter type */ ++ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ++ err = mlxbf_pmc_init_perftype_counter(dev, blk_num); ++ else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) ++ err = mlxbf_pmc_init_perftype_reg(dev, blk_num); ++ else ++ err = -EINVAL; ++ ++ if (err) ++ return err; ++ ++ /* Add a new attribute_group for the block */ ++ pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr; ++ pmc->block[blk_num].block_attr_grp.name = devm_kasprintf( ++ dev, GFP_KERNEL, pmc->block_name[blk_num]); ++ pmc->groups[blk_num] = &pmc->block[blk_num].block_attr_grp; ++ ++ return 0; ++} ++ ++static bool mlxbf_pmc_guid_match(const guid_t *guid, ++ const struct arm_smccc_res *res) ++{ ++ guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16, res->a2, ++ res->a2 >> 8, res->a2 >> 16, res->a2 >> 24, ++ res->a3, res->a3 >> 8, res->a3 >> 16, ++ res->a3 >> 24); ++ ++ return guid_equal(guid, &id); ++} ++ ++/* Helper to map the Performance Counters from the varios blocks */ ++static int mlxbf_pmc_map_counters(struct device *dev) ++{ ++ uint64_t info[MLXBF_PMC_INFO_SZ]; ++ int i, tile_num, ret; ++ ++ for (i = 0; i < pmc->total_blocks; ++i) { ++ if (strstr(pmc->block_name[i], "tile")) { ++ ret = sscanf(pmc->block_name[i], "tile%d", &tile_num); ++ if (ret < 0) ++ return ret; ++ ++ if (tile_num >= pmc->tile_count) ++ continue; ++ } ++ ret = device_property_read_u64_array(dev, pmc->block_name[i], ++ info, MLXBF_PMC_INFO_SZ); ++ if (ret) ++ return ret; ++ ++ /* ++ * Do not remap if the proper SMC calls are supported, ++ * since the SMC calls expect physical addresses. ++ */ ++ if (pmc->svc_sreg_support) ++ pmc->block[i].mmio_base = (void __iomem *)info[0]; ++ else ++ pmc->block[i].mmio_base = ++ devm_ioremap(dev, info[0], info[1]); ++ ++ pmc->block[i].blk_size = info[1]; ++ pmc->block[i].counters = info[2]; ++ pmc->block[i].type = info[3]; ++ ++ if (IS_ERR(pmc->block[i].mmio_base)) ++ return PTR_ERR(pmc->block[i].mmio_base); ++ ++ ret = mlxbf_pmc_create_groups(dev, i); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mlxbf_pmc_probe(struct platform_device *pdev) ++{ ++ struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev); ++ const char *hid = acpi_device_hid(acpi_dev); ++ struct device *dev = &pdev->dev; ++ struct arm_smccc_res res; ++ guid_t guid; ++ int ret; ++ ++ /* Ensure we have the UUID we expect for this service. */ ++ arm_smccc_smc(MLXBF_PMC_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); ++ guid_parse(mlxbf_pmc_svc_uuid_str, &guid); ++ if (!mlxbf_pmc_guid_match(&guid, &res)) ++ return -ENODEV; ++ ++ pmc = devm_kzalloc(dev, sizeof(struct mlxbf_pmc_context), GFP_KERNEL); ++ if (!pmc) ++ return -ENOMEM; ++ ++ /* ++ * ACPI indicates whether we use SMCs to access registers or not. ++ * If sreg_tbl_perf is not present, just assume we're not using SMCs. ++ */ ++ ret = device_property_read_u32(dev, "sec_reg_block", ++ &pmc->sreg_tbl_perf); ++ if (ret) { ++ pmc->svc_sreg_support = false; ++ } else { ++ /* ++ * Check service version to see if we actually do support the ++ * needed SMCs. If we have the calls we need, mark support for ++ * them in the pmc struct. ++ */ ++ arm_smccc_smc(MLXBF_PMC_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, ++ &res); ++ if (res.a0 == MLXBF_PMC_SVC_REQ_MAJOR && ++ res.a1 >= MLXBF_PMC_SVC_MIN_MINOR) ++ pmc->svc_sreg_support = true; ++ else ++ return -EINVAL; ++ } ++ ++ if (!strcmp(hid, "MLNXBFD0")) ++ pmc->event_set = MLXBF_PMC_EVENT_SET_BF1; ++ else if (!strcmp(hid, "MLNXBFD1")) ++ pmc->event_set = MLXBF_PMC_EVENT_SET_BF2; ++ else ++ return -ENODEV; ++ ++ ret = device_property_read_u32(dev, "block_num", &pmc->total_blocks); ++ if (ret) ++ return ret; ++ ++ ret = device_property_read_string_array(dev, "block_name", ++ pmc->block_name, ++ pmc->total_blocks); ++ if (ret != pmc->total_blocks) ++ return -EFAULT; ++ ++ ret = device_property_read_u32(dev, "tile_num", &pmc->tile_count); ++ if (ret) ++ return ret; ++ ++ pmc->pdev = pdev; ++ ++ ret = mlxbf_pmc_map_counters(dev); ++ if (ret) ++ return ret; ++ ++ pmc->hwmon_dev = devm_hwmon_device_register_with_groups( ++ dev, "bfperf", pmc, pmc->groups); ++ platform_set_drvdata(pdev, pmc); ++ ++ return 0; ++} ++ ++static const struct acpi_device_id mlxbf_pmc_acpi_ids[] = { { "MLNXBFD0", 0 }, ++ { "MLNXBFD1", 0 }, ++ {}, }; ++ ++MODULE_DEVICE_TABLE(acpi, mlxbf_pmc_acpi_ids); ++static struct platform_driver pmc_driver = { ++ .driver = { .name = "mlxbf-pmc", ++ .acpi_match_table = ACPI_PTR(mlxbf_pmc_acpi_ids), }, ++ .probe = mlxbf_pmc_probe, ++}; ++ ++module_platform_driver(pmc_driver); ++ ++MODULE_AUTHOR("Shravan Kumar Ramani "); ++MODULE_DESCRIPTION("Mellanox PMC driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0213-platform-mellanox-mlxbf-pmc-fix-kernel-doc-notation.patch b/platform/mellanox/non-upstream-patches/patches/0213-platform-mellanox-mlxbf-pmc-fix-kernel-doc-notation.patch new file mode 100644 index 0000000000..cfb80ac326 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0213-platform-mellanox-mlxbf-pmc-fix-kernel-doc-notation.patch @@ -0,0 +1,94 @@ +From 1494c3af245d1298a2fc7027c0724f8703820396 Mon Sep 17 00:00:00 2001 +From: Randy Dunlap +Date: Sun, 22 Aug 2021 10:17:42 -0700 +Subject: [PATCH backport 5.10 14/63] platform/mellanox: mlxbf-pmc: fix + kernel-doc notation + +Fix kernel-doc warnings reported by the kernel test robot: + +drivers/platform/mellanox/mlxbf-pmc.c:82: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst + * Structure to hold attribute and block info for each sysfs entry +drivers/platform/mellanox/mlxbf-pmc.c:94: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst + * Structure to hold info for each HW block +drivers/platform/mellanox/mlxbf-pmc.c:121: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst + * Structure to hold PMC context info +drivers/platform/mellanox/mlxbf-pmc.c:148: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst + * Structure to hold supported events for each block + +Also fix typos in a few struct member names. + +Signed-off-by: Randy Dunlap +Reported-by: kernel test robot +Cc: Aditya Srivastava +Cc: Hans de Goede +Cc: Mark Gross +Cc: Vadim Pasternak +Cc: platform-driver-x86@vger.kernel.org +Link: https://lore.kernel.org/r/20210822171742.26921-1-rdunlap@infradead.org +Signed-off-by: Hans de Goede +--- + drivers/platform/mellanox/mlxbf-pmc.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 358839842..04bc3b50a 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -79,7 +79,8 @@ + #define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0) + + /** +- * Structure to hold attribute and block info for each sysfs entry ++ * struct mlxbf_pmc_attribute - Structure to hold attribute and block info ++ * for each sysfs entry + * @dev_attr: Device attribute struct + * @index: index to identify counter number within a block + * @nr: block number to which the sysfs belongs +@@ -91,7 +92,7 @@ struct mlxbf_pmc_attribute { + }; + + /** +- * Structure to hold info for each HW block ++ * struct mlxbf_pmc_block_info - Structure to hold info for each HW block + * + * @mmio_base: The VA at which the PMC block is mapped + * @blk_size: Size of each mapped region +@@ -102,7 +103,7 @@ struct mlxbf_pmc_attribute { + * @attr_event_list: Attributes for "event_list" sysfs files + * @attr_enable: Attributes for "enable" sysfs files + * @block_attr: All attributes needed for the block +- * @blcok_attr_grp: Attribute group for the block ++ * @block_attr_grp: Attribute group for the block + */ + struct mlxbf_pmc_block_info { + void __iomem *mmio_base; +@@ -118,7 +119,7 @@ struct mlxbf_pmc_block_info { + }; + + /** +- * Structure to hold PMC context info ++ * struct mlxbf_pmc_context - Structure to hold PMC context info + * + * @pdev: The kernel structure representing the device + * @total_blocks: Total number of blocks +@@ -127,7 +128,7 @@ struct mlxbf_pmc_block_info { + * @block_name: Block name + * @block: Block info + * @groups: Attribute groups from each block +- * @sv_sreg_support: Whether SMCs are used to access performance registers ++ * @svc_sreg_support: Whether SMCs are used to access performance registers + * @sreg_tbl_perf: Secure register access table number + * @event_set: Event set to use + */ +@@ -145,7 +146,7 @@ struct mlxbf_pmc_context { + }; + + /** +- * Structure to hold supported events for each block ++ * struct mlxbf_pmc_events - Structure to hold supported events for each block + * @evt_num: Event number used to program counters + * @evt_name: Name of the event + */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0214-platform-mellanox-mlxbf-pmc-Fix-an-IS_ERR-vs-NULL-bu.patch b/platform/mellanox/non-upstream-patches/patches/0214-platform-mellanox-mlxbf-pmc-Fix-an-IS_ERR-vs-NULL-bu.patch new file mode 100644 index 0000000000..b1308c8f63 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0214-platform-mellanox-mlxbf-pmc-Fix-an-IS_ERR-vs-NULL-bu.patch @@ -0,0 +1,42 @@ +From fd81d5b65715344eeb492dfb3d818551446021c9 Mon Sep 17 00:00:00 2001 +From: Miaoqian Lin +Date: Fri, 10 Dec 2021 07:07:53 +0000 +Subject: [PATCH backport 5.10 15/63] platform/mellanox: mlxbf-pmc: Fix an + IS_ERR() vs NULL bug in mlxbf_pmc_map_counters + +BugLink: https://bugs.launchpad.net/bugs/1956926 + +[ Upstream commit 804034c4ffc502795cea9b3867acb2ec7fad99ba ] + +The devm_ioremap() function returns NULL on error, it doesn't return +error pointers. Also according to doc of device_property_read_u64_array, +values in info array are properties of device or NULL. + +Signed-off-by: Miaoqian Lin +Link: https://lore.kernel.org/r/20211210070753.10761-1-linmq006@gmail.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +Signed-off-by: Paolo Pisati +--- + drivers/platform/mellanox/mlxbf-pmc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 04bc3b50a..65b4a819f 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -1374,8 +1374,8 @@ static int mlxbf_pmc_map_counters(struct device *dev) + pmc->block[i].counters = info[2]; + pmc->block[i].type = info[3]; + +- if (IS_ERR(pmc->block[i].mmio_base)) +- return PTR_ERR(pmc->block[i].mmio_base); ++ if (!pmc->block[i].mmio_base) ++ return -ENOMEM; + + ret = mlxbf_pmc_create_groups(dev, i); + if (ret) +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0215-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-pmc.patch b/platform/mellanox/non-upstream-patches/patches/0215-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-pmc.patch new file mode 100644 index 0000000000..91d0f9e7a3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0215-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-pmc.patch @@ -0,0 +1,2674 @@ +From cc23dfd2e05d8e9ef59bcd5f760cc613e72bb80b Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Tue, 5 Jul 2022 10:52:05 -0400 +Subject: [PATCH backport 5.10 16/63] UBUNTU: SAUCE: platform/mellanox: Updates + to mlxbf-pmc + +BugLink: https://launchpad.net/bugs/1980746 + +This commit reorganizes the code by moving all the macros +to a header file, and fixes bugs with reprogramming the +counters. + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/mlxbf-pmc.c | 1722 +++++++++++-------------- + drivers/platform/mellanox/mlxbf-pmc.h | 428 ++++++ + 2 files changed, 1176 insertions(+), 974 deletions(-) + create mode 100644 drivers/platform/mellanox/mlxbf-pmc.h + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 65b4a819f..a9debcdf9 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -1,482 +1,111 @@ +-// SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB +-/* +- * Mellanox BlueField Performance Monitoring Counters driver +- * +- * This driver provides a sysfs interface for monitoring +- * performance statistics in BlueField SoC. +- * +- * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. +- */ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause + + #include + #include + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + #include +-#include ++#include ++#include ++#include ++#include + #include + +-#define MLXBF_PMC_WRITE_REG_32 0x82000009 +-#define MLXBF_PMC_READ_REG_32 0x8200000A +-#define MLXBF_PMC_WRITE_REG_64 0x8200000B +-#define MLXBF_PMC_READ_REG_64 0x8200000C +-#define MLXBF_PMC_SIP_SVC_UID 0x8200ff01 +-#define MLXBF_PMC_SIP_SVC_VERSION 0x8200ff03 +-#define MLXBF_PMC_SVC_REQ_MAJOR 0 +-#define MLXBF_PMC_SVC_MIN_MINOR 3 +- +-#define MLXBF_PMC_SMCCC_ACCESS_VIOLATION -4 +- +-#define MLXBF_PMC_EVENT_SET_BF1 0 +-#define MLXBF_PMC_EVENT_SET_BF2 1 +-#define MLXBF_PMC_EVENT_INFO_LEN 100 +- +-#define MLXBF_PMC_MAX_BLOCKS 30 +-#define MLXBF_PMC_MAX_ATTRS 30 +-#define MLXBF_PMC_INFO_SZ 4 +-#define MLXBF_PMC_REG_SIZE 8 +-#define MLXBF_PMC_L3C_REG_SIZE 4 +- +-#define MLXBF_PMC_TYPE_COUNTER 1 +-#define MLXBF_PMC_TYPE_REGISTER 0 +- +-#define MLXBF_PMC_PERFCTL 0 +-#define MLXBF_PMC_PERFEVT 1 +-#define MLXBF_PMC_PERFACC0 4 +- +-#define MLXBF_PMC_PERFMON_CONFIG_WR_R_B BIT(0) +-#define MLXBF_PMC_PERFMON_CONFIG_STROBE BIT(1) +-#define MLXBF_PMC_PERFMON_CONFIG_ADDR GENMASK_ULL(4, 2) +-#define MLXBF_PMC_PERFMON_CONFIG_WDATA GENMASK_ULL(60, 5) +- +-#define MLXBF_PMC_PERFCTL_FM0 GENMASK_ULL(18, 16) +-#define MLXBF_PMC_PERFCTL_MS0 GENMASK_ULL(21, 20) +-#define MLXBF_PMC_PERFCTL_ACCM0 GENMASK_ULL(26, 24) +-#define MLXBF_PMC_PERFCTL_AD0 BIT(27) +-#define MLXBF_PMC_PERFCTL_ETRIG0 GENMASK_ULL(29, 28) +-#define MLXBF_PMC_PERFCTL_EB0 BIT(30) +-#define MLXBF_PMC_PERFCTL_EN0 BIT(31) +- +-#define MLXBF_PMC_PERFEVT_EVTSEL GENMASK_ULL(31, 24) +- +-#define MLXBF_PMC_L3C_PERF_CNT_CFG 0x0 +-#define MLXBF_PMC_L3C_PERF_CNT_SEL 0x10 +-#define MLXBF_PMC_L3C_PERF_CNT_SEL_1 0x14 +-#define MLXBF_PMC_L3C_PERF_CNT_LOW 0x40 +-#define MLXBF_PMC_L3C_PERF_CNT_HIGH 0x60 +- +-#define MLXBF_PMC_L3C_PERF_CNT_CFG_EN BIT(0) +-#define MLXBF_PMC_L3C_PERF_CNT_CFG_RST BIT(1) +-#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0 GENMASK(5, 0) +-#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1 GENMASK(13, 8) +-#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2 GENMASK(21, 16) +-#define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3 GENMASK(29, 24) +- +-#define MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4 GENMASK(5, 0) +- +-#define MLXBF_PMC_L3C_PERF_CNT_LOW_VAL GENMASK(31, 0) +-#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0) +- +-/** +- * struct mlxbf_pmc_attribute - Structure to hold attribute and block info +- * for each sysfs entry +- * @dev_attr: Device attribute struct +- * @index: index to identify counter number within a block +- * @nr: block number to which the sysfs belongs +- */ +-struct mlxbf_pmc_attribute { +- struct device_attribute dev_attr; +- int index; +- int nr; +-}; +- +-/** +- * struct mlxbf_pmc_block_info - Structure to hold info for each HW block +- * +- * @mmio_base: The VA at which the PMC block is mapped +- * @blk_size: Size of each mapped region +- * @counters: Number of counters in the block +- * @type: Type of counters in the block +- * @attr_counter: Attributes for "counter" sysfs files +- * @attr_event: Attributes for "event" sysfs files +- * @attr_event_list: Attributes for "event_list" sysfs files +- * @attr_enable: Attributes for "enable" sysfs files +- * @block_attr: All attributes needed for the block +- * @block_attr_grp: Attribute group for the block +- */ +-struct mlxbf_pmc_block_info { +- void __iomem *mmio_base; +- size_t blk_size; +- size_t counters; +- int type; +- struct mlxbf_pmc_attribute *attr_counter; +- struct mlxbf_pmc_attribute *attr_event; +- struct mlxbf_pmc_attribute attr_event_list; +- struct mlxbf_pmc_attribute attr_enable; +- struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS]; +- struct attribute_group block_attr_grp; +-}; +- +-/** +- * struct mlxbf_pmc_context - Structure to hold PMC context info +- * +- * @pdev: The kernel structure representing the device +- * @total_blocks: Total number of blocks +- * @tile_count: Number of tiles in the system +- * @hwmon_dev: Hwmon device for bfperf +- * @block_name: Block name +- * @block: Block info +- * @groups: Attribute groups from each block +- * @svc_sreg_support: Whether SMCs are used to access performance registers +- * @sreg_tbl_perf: Secure register access table number +- * @event_set: Event set to use +- */ +-struct mlxbf_pmc_context { +- struct platform_device *pdev; +- uint32_t total_blocks; +- uint32_t tile_count; +- struct device *hwmon_dev; +- const char *block_name[MLXBF_PMC_MAX_BLOCKS]; +- struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS]; +- const struct attribute_group *groups[MLXBF_PMC_MAX_BLOCKS]; +- bool svc_sreg_support; +- uint32_t sreg_tbl_perf; +- unsigned int event_set; +-}; +- +-/** +- * struct mlxbf_pmc_events - Structure to hold supported events for each block +- * @evt_num: Event number used to program counters +- * @evt_name: Name of the event +- */ +-struct mlxbf_pmc_events { +- int evt_num; +- char *evt_name; +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_pcie_events[] = { +- { 0x0, "IN_P_PKT_CNT" }, +- { 0x10, "IN_NP_PKT_CNT" }, +- { 0x18, "IN_C_PKT_CNT" }, +- { 0x20, "OUT_P_PKT_CNT" }, +- { 0x28, "OUT_NP_PKT_CNT" }, +- { 0x30, "OUT_C_PKT_CNT" }, +- { 0x38, "IN_P_BYTE_CNT" }, +- { 0x40, "IN_NP_BYTE_CNT" }, +- { 0x48, "IN_C_BYTE_CNT" }, +- { 0x50, "OUT_P_BYTE_CNT" }, +- { 0x58, "OUT_NP_BYTE_CNT" }, +- { 0x60, "OUT_C_BYTE_CNT" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_smgen_events[] = { +- { 0x0, "AW_REQ" }, +- { 0x1, "AW_BEATS" }, +- { 0x2, "AW_TRANS" }, +- { 0x3, "AW_RESP" }, +- { 0x4, "AW_STL" }, +- { 0x5, "AW_LAT" }, +- { 0x6, "AW_REQ_TBU" }, +- { 0x8, "AR_REQ" }, +- { 0x9, "AR_BEATS" }, +- { 0xa, "AR_TRANS" }, +- { 0xb, "AR_STL" }, +- { 0xc, "AR_LAT" }, +- { 0xd, "AR_REQ_TBU" }, +- { 0xe, "TBU_MISS" }, +- { 0xf, "TX_DAT_AF" }, +- { 0x10, "RX_DAT_AF" }, +- { 0x11, "RETRYQ_CRED" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = { +- { 0xa0, "TPIO_DATA_BEAT" }, +- { 0xa1, "TDMA_DATA_BEAT" }, +- { 0xa2, "MAP_DATA_BEAT" }, +- { 0xa3, "TXMSG_DATA_BEAT" }, +- { 0xa4, "TPIO_DATA_PACKET" }, +- { 0xa5, "TDMA_DATA_PACKET" }, +- { 0xa6, "MAP_DATA_PACKET" }, +- { 0xa7, "TXMSG_DATA_PACKET" }, +- { 0xa8, "TDMA_RT_AF" }, +- { 0xa9, "TDMA_PBUF_MAC_AF" }, +- { 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" }, +- { 0xab, "TRIO_MAP_CPL_BUF_EMPTY" }, +- { 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" }, +- { 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" }, +- { 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" }, +- { 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" }, +- { 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" }, +- { 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" }, +- { 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" }, +- { 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = { +- { 0xa0, "TPIO_DATA_BEAT" }, +- { 0xa1, "TDMA_DATA_BEAT" }, +- { 0xa2, "MAP_DATA_BEAT" }, +- { 0xa3, "TXMSG_DATA_BEAT" }, +- { 0xa4, "TPIO_DATA_PACKET" }, +- { 0xa5, "TDMA_DATA_PACKET" }, +- { 0xa6, "MAP_DATA_PACKET" }, +- { 0xa7, "TXMSG_DATA_PACKET" }, +- { 0xa8, "TDMA_RT_AF" }, +- { 0xa9, "TDMA_PBUF_MAC_AF" }, +- { 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" }, +- { 0xab, "TRIO_MAP_CPL_BUF_EMPTY" }, +- { 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" }, +- { 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" }, +- { 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" }, +- { 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" }, +- { 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" }, +- { 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" }, +- { 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" }, +- { 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" }, +- { 0xb4, "TRIO_RING_TX_FLIT_CH0" }, +- { 0xb5, "TRIO_RING_TX_FLIT_CH1" }, +- { 0xb6, "TRIO_RING_TX_FLIT_CH2" }, +- { 0xb7, "TRIO_RING_TX_FLIT_CH3" }, +- { 0xb8, "TRIO_RING_TX_FLIT_CH4" }, +- { 0xb9, "TRIO_RING_RX_FLIT_CH0" }, +- { 0xba, "TRIO_RING_RX_FLIT_CH1" }, +- { 0xbb, "TRIO_RING_RX_FLIT_CH2" }, +- { 0xbc, "TRIO_RING_RX_FLIT_CH3" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = { +- { 0x100, "ECC_SINGLE_ERROR_CNT" }, +- { 0x104, "ECC_DOUBLE_ERROR_CNT" }, +- { 0x114, "SERR_INJ" }, +- { 0x118, "DERR_INJ" }, +- { 0x124, "ECC_SINGLE_ERROR_0" }, +- { 0x164, "ECC_DOUBLE_ERROR_0" }, +- { 0x340, "DRAM_ECC_COUNT" }, +- { 0x344, "DRAM_ECC_INJECT" }, +- { 0x348, "DRAM_ECC_ERROR" }, +-}; ++#include "mlxbf-pmc.h" + +-static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = { +- { 0xc0, "RXREQ_MSS" }, +- { 0xc1, "RXDAT_MSS" }, +- { 0xc2, "TXRSP_MSS" }, +- { 0xc3, "TXDAT_MSS" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = { +- { 0x45, "HNF_REQUESTS" }, +- { 0x46, "HNF_REJECTS" }, +- { 0x47, "ALL_BUSY" }, +- { 0x48, "MAF_BUSY" }, +- { 0x49, "MAF_REQUESTS" }, +- { 0x4a, "RNF_REQUESTS" }, +- { 0x4b, "REQUEST_TYPE" }, +- { 0x4c, "MEMORY_READS" }, +- { 0x4d, "MEMORY_WRITES" }, +- { 0x4e, "VICTIM_WRITE" }, +- { 0x4f, "POC_FULL" }, +- { 0x50, "POC_FAIL" }, +- { 0x51, "POC_SUCCESS" }, +- { 0x52, "POC_WRITES" }, +- { 0x53, "POC_READS" }, +- { 0x54, "FORWARD" }, +- { 0x55, "RXREQ_HNF" }, +- { 0x56, "RXRSP_HNF" }, +- { 0x57, "RXDAT_HNF" }, +- { 0x58, "TXREQ_HNF" }, +- { 0x59, "TXRSP_HNF" }, +- { 0x5a, "TXDAT_HNF" }, +- { 0x5b, "TXSNP_HNF" }, +- { 0x5c, "INDEX_MATCH" }, +- { 0x5d, "A72_ACCESS" }, +- { 0x5e, "IO_ACCESS" }, +- { 0x5f, "TSO_WRITE" }, +- { 0x60, "TSO_CONFLICT" }, +- { 0x61, "DIR_HIT" }, +- { 0x62, "HNF_ACCEPTS" }, +- { 0x63, "REQ_BUF_EMPTY" }, +- { 0x64, "REQ_BUF_IDLE_MAF" }, +- { 0x65, "TSO_NOARB" }, +- { 0x66, "TSO_NOARB_CYCLES" }, +- { 0x67, "MSS_NO_CREDIT" }, +- { 0x68, "TXDAT_NO_LCRD" }, +- { 0x69, "TXSNP_NO_LCRD" }, +- { 0x6a, "TXRSP_NO_LCRD" }, +- { 0x6b, "TXREQ_NO_LCRD" }, +- { 0x6c, "TSO_CL_MATCH" }, +- { 0x6d, "MEMORY_READS_BYPASS" }, +- { 0x6e, "TSO_NOARB_TIMEOUT" }, +- { 0x6f, "ALLOCATE" }, +- { 0x70, "VICTIM" }, +- { 0x71, "A72_WRITE" }, +- { 0x72, "A72_READ" }, +- { 0x73, "IO_WRITE" }, +- { 0x74, "IO_READ" }, +- { 0x75, "TSO_REJECT" }, +- { 0x80, "TXREQ_RN" }, +- { 0x81, "TXRSP_RN" }, +- { 0x82, "TXDAT_RN" }, +- { 0x83, "RXSNP_RN" }, +- { 0x84, "RXRSP_RN" }, +- { 0x85, "RXDAT_RN" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = { +- { 0x12, "CDN_REQ" }, +- { 0x13, "DDN_REQ" }, +- { 0x14, "NDN_REQ" }, +- { 0x15, "CDN_DIAG_N_OUT_OF_CRED" }, +- { 0x16, "CDN_DIAG_S_OUT_OF_CRED" }, +- { 0x17, "CDN_DIAG_E_OUT_OF_CRED" }, +- { 0x18, "CDN_DIAG_W_OUT_OF_CRED" }, +- { 0x19, "CDN_DIAG_C_OUT_OF_CRED" }, +- { 0x1a, "CDN_DIAG_N_EGRESS" }, +- { 0x1b, "CDN_DIAG_S_EGRESS" }, +- { 0x1c, "CDN_DIAG_E_EGRESS" }, +- { 0x1d, "CDN_DIAG_W_EGRESS" }, +- { 0x1e, "CDN_DIAG_C_EGRESS" }, +- { 0x1f, "CDN_DIAG_N_INGRESS" }, +- { 0x20, "CDN_DIAG_S_INGRESS" }, +- { 0x21, "CDN_DIAG_E_INGRESS" }, +- { 0x22, "CDN_DIAG_W_INGRESS" }, +- { 0x23, "CDN_DIAG_C_INGRESS" }, +- { 0x24, "CDN_DIAG_CORE_SENT" }, +- { 0x25, "DDN_DIAG_N_OUT_OF_CRED" }, +- { 0x26, "DDN_DIAG_S_OUT_OF_CRED" }, +- { 0x27, "DDN_DIAG_E_OUT_OF_CRED" }, +- { 0x28, "DDN_DIAG_W_OUT_OF_CRED" }, +- { 0x29, "DDN_DIAG_C_OUT_OF_CRED" }, +- { 0x2a, "DDN_DIAG_N_EGRESS" }, +- { 0x2b, "DDN_DIAG_S_EGRESS" }, +- { 0x2c, "DDN_DIAG_E_EGRESS" }, +- { 0x2d, "DDN_DIAG_W_EGRESS" }, +- { 0x2e, "DDN_DIAG_C_EGRESS" }, +- { 0x2f, "DDN_DIAG_N_INGRESS" }, +- { 0x30, "DDN_DIAG_S_INGRESS" }, +- { 0x31, "DDN_DIAG_E_INGRESS" }, +- { 0x32, "DDN_DIAG_W_INGRESS" }, +- { 0x33, "DDN_DIAG_C_INGRESS" }, +- { 0x34, "DDN_DIAG_CORE_SENT" }, +- { 0x35, "NDN_DIAG_S_OUT_OF_CRED" }, +- { 0x36, "NDN_DIAG_S_OUT_OF_CRED" }, +- { 0x37, "NDN_DIAG_E_OUT_OF_CRED" }, +- { 0x38, "NDN_DIAG_W_OUT_OF_CRED" }, +- { 0x39, "NDN_DIAG_C_OUT_OF_CRED" }, +- { 0x3a, "NDN_DIAG_N_EGRESS" }, +- { 0x3b, "NDN_DIAG_S_EGRESS" }, +- { 0x3c, "NDN_DIAG_E_EGRESS" }, +- { 0x3d, "NDN_DIAG_W_EGRESS" }, +- { 0x3e, "NDN_DIAG_C_EGRESS" }, +- { 0x3f, "NDN_DIAG_N_INGRESS" }, +- { 0x40, "NDN_DIAG_S_INGRESS" }, +- { 0x41, "NDN_DIAG_E_INGRESS" }, +- { 0x42, "NDN_DIAG_W_INGRESS" }, +- { 0x43, "NDN_DIAG_C_INGRESS" }, +- { 0x44, "NDN_DIAG_CORE_SENT" }, +-}; +- +-static const struct mlxbf_pmc_events mlxbf_pmc_l3c_events[] = { +- { 0x00, "DISABLE" }, +- { 0x01, "CYCLES" }, +- { 0x02, "TOTAL_RD_REQ_IN" }, +- { 0x03, "TOTAL_WR_REQ_IN" }, +- { 0x04, "TOTAL_WR_DBID_ACK" }, +- { 0x05, "TOTAL_WR_DATA_IN" }, +- { 0x06, "TOTAL_WR_COMP" }, +- { 0x07, "TOTAL_RD_DATA_OUT" }, +- { 0x08, "TOTAL_CDN_REQ_IN_BANK0" }, +- { 0x09, "TOTAL_CDN_REQ_IN_BANK1" }, +- { 0x0a, "TOTAL_DDN_REQ_IN_BANK0" }, +- { 0x0b, "TOTAL_DDN_REQ_IN_BANK1" }, +- { 0x0c, "TOTAL_EMEM_RD_RES_IN_BANK0" }, +- { 0x0d, "TOTAL_EMEM_RD_RES_IN_BANK1" }, +- { 0x0e, "TOTAL_CACHE_RD_RES_IN_BANK0" }, +- { 0x0f, "TOTAL_CACHE_RD_RES_IN_BANK1" }, +- { 0x10, "TOTAL_EMEM_RD_REQ_BANK0" }, +- { 0x11, "TOTAL_EMEM_RD_REQ_BANK1" }, +- { 0x12, "TOTAL_EMEM_WR_REQ_BANK0" }, +- { 0x13, "TOTAL_EMEM_WR_REQ_BANK1" }, +- { 0x14, "TOTAL_RD_REQ_OUT" }, +- { 0x15, "TOTAL_WR_REQ_OUT" }, +- { 0x16, "TOTAL_RD_RES_IN" }, +- { 0x17, "HITS_BANK0" }, +- { 0x18, "HITS_BANK1" }, +- { 0x19, "MISSES_BANK0" }, +- { 0x1a, "MISSES_BANK1" }, +- { 0x1b, "ALLOCATIONS_BANK0" }, +- { 0x1c, "ALLOCATIONS_BANK1" }, +- { 0x1d, "EVICTIONS_BANK0" }, +- { 0x1e, "EVICTIONS_BANK1" }, +- { 0x1f, "DBID_REJECT" }, +- { 0x20, "WRDB_REJECT_BANK0" }, +- { 0x21, "WRDB_REJECT_BANK1" }, +- { 0x22, "CMDQ_REJECT_BANK0" }, +- { 0x23, "CMDQ_REJECT_BANK1" }, +- { 0x24, "COB_REJECT_BANK0" }, +- { 0x25, "COB_REJECT_BANK1" }, +- { 0x26, "TRB_REJECT_BANK0" }, +- { 0x27, "TRB_REJECT_BANK1" }, +- { 0x28, "TAG_REJECT_BANK0" }, +- { 0x29, "TAG_REJECT_BANK1" }, +- { 0x2a, "ANY_REJECT_BANK0" }, +- { 0x2b, "ANY_REJECT_BANK1" }, +-}; ++#define DRIVER_VERSION 2.2 + + static struct mlxbf_pmc_context *pmc; + +-/* UUID used to probe ATF service. */ +-static const char *mlxbf_pmc_svc_uuid_str = "89c036b4-e7d7-11e6-8797-001aca00bfc4"; ++#define SIZE_64 0 ++#define SIZE_32 1 + + /* Calls an SMC to access a performance register */ +-static int mlxbf_pmc_secure_read(void __iomem *addr, uint32_t command, +- uint64_t *result) ++static int mlxbf_pmc_secure_read(void *addr, int size, uint64_t *result) + { + struct arm_smccc_res res; +- int status, err = 0; ++ uint32_t command; ++ int status; ++ ++ switch (size) { ++ case SIZE_32: ++ command = MLNX_READ_REG_32; ++ break; ++ case SIZE_64: ++ command = MLNX_READ_REG_64; ++ break; ++ default: ++ dev_err(pmc->hwmon_dev, ++ "%s: invalid size: %d\n", __func__, size); ++ return -EINVAL; ++ } + +- arm_smccc_smc(command, pmc->sreg_tbl_perf, (uintptr_t)addr, 0, 0, 0, 0, +- 0, &res); ++ arm_smccc_smc( ++ command, ++ pmc->sreg_tbl_perf, ++ (uintptr_t) addr, ++ 0, 0, 0, 0, 0, &res); + + status = res.a0; + + switch (status) { ++ /* ++ * Note: PSCI_RET_NOT_SUPPORTED is used here to maintain compatibility ++ * with older kernels that do not have SMCCC_RET_NOT_SUPPORTED ++ */ + case PSCI_RET_NOT_SUPPORTED: +- err = -EINVAL; +- break; +- case MLXBF_PMC_SMCCC_ACCESS_VIOLATION: +- err = -EACCES; +- break; ++ dev_err(pmc->hwmon_dev, ++ "%s: required SMC unsupported", __func__); ++ return -EINVAL; ++ case SMCCC_ACCESS_VIOLATION: ++ dev_err(pmc->hwmon_dev, ++ "%s: could not read register %p. Is it perf?", ++ __func__, ++ addr); ++ return -EACCES; + default: +- *result = res.a1; +- break; ++ *result = (uint64_t)res.a1; ++ return 0; + } +- +- return err; + } + + /* Read from a performance counter */ +-static int mlxbf_pmc_read(void __iomem *addr, uint32_t command, +- uint64_t *result) ++static int mlxbf_pmc_read(void *addr, int size, uint64_t *result) + { +- if (pmc->svc_sreg_support) +- return mlxbf_pmc_secure_read(addr, command, result); +- +- if (command == MLXBF_PMC_READ_REG_32) +- *result = readl(addr); +- else +- *result = readq(addr); +- +- return 0; ++ if (pmc->svc_sreg_support) { ++ if (mlxbf_pmc_secure_read(addr, size, result)) ++ return -EINVAL; ++ else ++ return 0; ++ } else { ++ switch (size) { ++ case SIZE_32: ++ *result = (uint64_t)readl(addr); ++ return 0; ++ case SIZE_64: ++ *result = readq(addr); ++ return 0; ++ default: ++ dev_err(pmc->hwmon_dev, ++ "%s: invalid size: %d\n", __func__, size); ++ return -EINVAL; ++ } ++ } + } + + /* Convenience function for 32-bit reads */ +-static int mlxbf_pmc_readl(void __iomem *addr, uint32_t *result) ++static int mlxbf_pmc_readl(uint32_t *result, void *addr) + { + uint64_t read_out; + int status; + +- status = mlxbf_pmc_read(addr, MLXBF_PMC_READ_REG_32, &read_out); ++ status = mlxbf_pmc_read(addr, SIZE_32, &read_out); + if (status) + return status; + *result = (uint32_t)read_out; +@@ -484,231 +113,274 @@ static int mlxbf_pmc_readl(void __iomem *addr, uint32_t *result) + return 0; + } + ++/* Convenience function for 64-bit reads */ ++static int mlxbf_pmc_readq(uint64_t *result, void *addr) ++{ ++ return mlxbf_pmc_read(addr, SIZE_64, result); ++} ++ + /* Calls an SMC to access a performance register */ +-static int mlxbf_pmc_secure_write(void __iomem *addr, uint32_t command, +- uint64_t value) ++static int mlxbf_pmc_secure_write(uint64_t value, void *addr, int size) + { + struct arm_smccc_res res; +- int status, err = 0; ++ uint32_t command; ++ int status; + +- arm_smccc_smc(command, pmc->sreg_tbl_perf, value, (uintptr_t)addr, 0, 0, +- 0, 0, &res); ++ switch (size) { ++ case SIZE_32: ++ command = MLNX_WRITE_REG_32; ++ break; ++ case SIZE_64: ++ command = MLNX_WRITE_REG_64; ++ break; ++ default: ++ dev_err(pmc->hwmon_dev, ++ "%s: invalid size: %d\n", __func__, size); ++ return -EINVAL; ++ } ++ ++ arm_smccc_smc( ++ command, ++ pmc->sreg_tbl_perf, ++ value, ++ (uintptr_t) addr, ++ 0, 0, 0, 0, &res); + + status = res.a0; + + switch (status) { + case PSCI_RET_NOT_SUPPORTED: +- err = -EINVAL; +- break; +- case MLXBF_PMC_SMCCC_ACCESS_VIOLATION: +- err = -EACCES; +- break; ++ dev_err(pmc->hwmon_dev, ++ "%s: required SMC unsupported", __func__); ++ return -EINVAL; ++ case SMCCC_ACCESS_VIOLATION: ++ dev_err(pmc->hwmon_dev, ++ "%s: could not write register %p. Is it perf?", ++ __func__, ++ addr); ++ return -EACCES; ++ default: ++ return 0; + } +- +- return err; + } + + /* Write to a performance counter */ +-static int mlxbf_pmc_write(void __iomem *addr, int command, uint64_t value) ++static int mlxbf_pmc_write(uint64_t value, void *addr, int size) + { + if (pmc->svc_sreg_support) +- return mlxbf_pmc_secure_write(addr, command, value); ++ return mlxbf_pmc_secure_write(value, addr, size); + +- if (command == MLXBF_PMC_WRITE_REG_32) +- writel(value, addr); +- else ++ switch (size) { ++ case SIZE_32: ++ writel((uint32_t)value, addr); ++ return 0; ++ case SIZE_64: + writeq(value, addr); ++ return 0; ++ default: ++ dev_err(pmc->hwmon_dev, ++ "%s: invalid size: %d\n", __func__, size); ++ return -EINVAL; ++ } ++} + +- return 0; ++/* Convenience function for 32-bit writes */ ++static int mlxbf_pmc_writel(uint32_t value, void *addr) ++{ ++ return mlxbf_pmc_write((uint64_t) value, addr, SIZE_32); ++} ++ ++/* Convenience function for 64-bit writes */ ++static int mlxbf_pmc_writeq(uint64_t value, void *addr) ++{ ++ return mlxbf_pmc_write(value, addr, SIZE_64); + } + + /* Check if the register offset is within the mapped region for the block */ + static bool mlxbf_pmc_valid_range(int blk_num, uint32_t offset) + { +- if ((offset >= 0) && !(offset % MLXBF_PMC_REG_SIZE) && +- (offset + MLXBF_PMC_REG_SIZE <= pmc->block[blk_num].blk_size)) +- return true; /* inside the mapped PMC space */ ++ if (offset % 8 != 0) ++ return false; /* unaligned */ ++ if (offset >= 0 && offset + 8 <= pmc->block[blk_num].blk_size) ++ return true; /* inside the mapped PMC space */ + + return false; + } + ++/* Get the block number using the name */ ++static int mlxbf_pmc_get_block_num(const char *name) ++{ ++ int i; ++ ++ for (i = 0; i < pmc->total_blocks; ++i) ++ if (strcmp((char *)name, pmc->block_name[i]) == 0) ++ return i; ++ ++ return -ENODEV; ++} ++ + /* Get the event list corresponding to a certain block */ +-static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk, +- int *size) ++struct mlxbf_pmc_events *mlxbf_pmc_event_list(char *blk) + { +- const struct mlxbf_pmc_events *events; +- +- if (strstr(blk, "tilenet")) { +- events = mlxbf_pmc_hnfnet_events; +- *size = ARRAY_SIZE(mlxbf_pmc_hnfnet_events); +- } else if (strstr(blk, "tile")) { +- events = mlxbf_pmc_hnf_events; +- *size = ARRAY_SIZE(mlxbf_pmc_hnf_events); +- } else if (strstr(blk, "triogen")) { +- events = mlxbf_pmc_smgen_events; +- *size = ARRAY_SIZE(mlxbf_pmc_smgen_events); +- } else if (strstr(blk, "trio")) { ++ struct mlxbf_pmc_events *events; ++ ++ if (strstr(blk, "tilenet")) ++ events = mlxbf2_hnfnet_events; ++ else if (strstr(blk, "tile")) ++ events = mlxbf_hnf_events; ++ else if (strstr(blk, "triogen")) ++ events = mlxbf_smgen_events; ++ else if (strstr(blk, "trio")) + switch (pmc->event_set) { +- case MLXBF_PMC_EVENT_SET_BF1: +- events = mlxbf_pmc_trio_events_1; +- *size = ARRAY_SIZE(mlxbf_pmc_trio_events_1); ++ case MLNX_EVENT_SET_BF1: ++ events = mlxbf1_trio_events; + break; +- case MLXBF_PMC_EVENT_SET_BF2: +- events = mlxbf_pmc_trio_events_2; +- *size = ARRAY_SIZE(mlxbf_pmc_trio_events_2); ++ case MLNX_EVENT_SET_BF2: ++ events = mlxbf2_trio_events; + break; + default: + events = NULL; +- *size = 0; + break; + } +- } else if (strstr(blk, "mss")) { +- events = mlxbf_pmc_mss_events; +- *size = ARRAY_SIZE(mlxbf_pmc_mss_events); +- } else if (strstr(blk, "ecc")) { +- events = mlxbf_pmc_ecc_events; +- *size = ARRAY_SIZE(mlxbf_pmc_ecc_events); +- } else if (strstr(blk, "pcie")) { +- events = mlxbf_pmc_pcie_events; +- *size = ARRAY_SIZE(mlxbf_pmc_pcie_events); +- } else if (strstr(blk, "l3cache")) { +- events = mlxbf_pmc_l3c_events; +- *size = ARRAY_SIZE(mlxbf_pmc_l3c_events); +- } else if (strstr(blk, "gic")) { +- events = mlxbf_pmc_smgen_events; +- *size = ARRAY_SIZE(mlxbf_pmc_smgen_events); +- } else if (strstr(blk, "smmu")) { +- events = mlxbf_pmc_smgen_events; +- *size = ARRAY_SIZE(mlxbf_pmc_smgen_events); +- } else { ++ else if (strstr(blk, "mss")) ++ events = mlxbf_mss_events; ++ else if (strstr(blk, "ecc")) ++ events = mlxbf_ecc_events; ++ else if (strstr(blk, "pcie")) ++ events = mlxbf_pcie_events; ++ else if (strstr(blk, "l3cache")) ++ events = mlxbf_l3cache_events; ++ else if (strstr(blk, "gic")) ++ events = mlxbf_smgen_events; ++ else if (strstr(blk, "smmu")) ++ events = mlxbf_smgen_events; ++ else + events = NULL; +- *size = 0; +- } + + return events; + } + + /* Get the event number given the name */ +-static int mlxbf_pmc_get_event_num(const char *blk, const char *evt) ++static int mlxbf_pmc_get_event_num(char *blk, char *evt) + { +- const struct mlxbf_pmc_events *events; +- int i, size; ++ struct mlxbf_pmc_events *events; ++ int i = 0; + +- events = mlxbf_pmc_event_list(blk, &size); +- if (!events) ++ events = mlxbf_pmc_event_list(blk); ++ if (events == NULL) + return -EINVAL; + +- for (i = 0; i < size; ++i) { +- if (!strcmp(evt, events[i].evt_name)) ++ while (events[i].evt_name != NULL) { ++ if (strcmp(evt, events[i].evt_name) == 0) + return events[i].evt_num; ++ ++i; + } + + return -ENODEV; + } + + /* Get the event number given the name */ +-static char *mlxbf_pmc_get_event_name(const char *blk, int evt) ++static char *mlxbf_pmc_get_event_name(char *blk, int evt) + { +- const struct mlxbf_pmc_events *events; +- int i, size; ++ struct mlxbf_pmc_events *events; ++ int i = 0; + +- events = mlxbf_pmc_event_list(blk, &size); +- if (!events) ++ events = mlxbf_pmc_event_list(blk); ++ if (events == NULL) + return NULL; + +- for (i = 0; i < size; ++i) { ++ while (events[i].evt_name != NULL) { + if (evt == events[i].evt_num) + return events[i].evt_name; ++ ++i; + } + + return NULL; + } + + /* Method to enable/disable/reset l3cache counters */ +-static int mlxbf_pmc_config_l3_counters(int blk_num, bool enable, bool reset) ++int mlxbf_config_l3_counters(int blk_num, bool enable, bool reset) + { + uint32_t perfcnt_cfg = 0; + + if (enable) +- perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_EN; ++ perfcnt_cfg |= MLXBF_L3C_PERF_CNT_CFG__EN; + if (reset) +- perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_RST; ++ perfcnt_cfg |= MLXBF_L3C_PERF_CNT_CFG__RST; + +- return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_CFG, +- MLXBF_PMC_WRITE_REG_32, perfcnt_cfg); ++ return mlxbf_pmc_writel(perfcnt_cfg, pmc->block[blk_num].mmio_base + ++ MLXBF_L3C_PERF_CNT_CFG); + } + ++ + /* Method to handle l3cache counter programming */ +-static int mlxbf_pmc_program_l3_counter(int blk_num, uint32_t cnt_num, +- uint32_t evt) ++int mlxbf_program_l3_counter(int blk_num, uint32_t cnt_num, uint32_t evt) + { + uint32_t perfcnt_sel_1 = 0; + uint32_t perfcnt_sel = 0; + uint32_t *wordaddr; +- void __iomem *pmcaddr; ++ void *pmcaddr; + int ret; + + /* Disable all counters before programming them */ +- if (mlxbf_pmc_config_l3_counters(blk_num, false, false)) ++ if (mlxbf_config_l3_counters(blk_num, false, false)) + return -EINVAL; + + /* Select appropriate register information */ + switch (cnt_num) { +- case 0 ... 3: ++ case 0: ++ case 1: ++ case 2: ++ case 3: + pmcaddr = pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_SEL; ++ MLXBF_L3C_PERF_CNT_SEL; + wordaddr = &perfcnt_sel; + break; + case 4: + pmcaddr = pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_SEL_1; ++ MLXBF_L3C_PERF_CNT_SEL_1; + wordaddr = &perfcnt_sel_1; + break; + default: + return -EINVAL; + } + +- ret = mlxbf_pmc_readl(pmcaddr, wordaddr); ++ ret = mlxbf_pmc_readl(wordaddr, pmcaddr); + if (ret) + return ret; + + switch (cnt_num) { + case 0: +- perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0; +- perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, +- evt); ++ perfcnt_sel &= ~MLXBF_L3C_PERF_CNT_SEL__CNT_0; ++ perfcnt_sel |= FIELD_PREP(MLXBF_L3C_PERF_CNT_SEL__CNT_0, evt); + break; + case 1: +- perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1; +- perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, +- evt); ++ perfcnt_sel &= ~MLXBF_L3C_PERF_CNT_SEL__CNT_1; ++ perfcnt_sel |= FIELD_PREP(MLXBF_L3C_PERF_CNT_SEL__CNT_1, evt); + break; + case 2: +- perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2; +- perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, +- evt); ++ perfcnt_sel &= ~MLXBF_L3C_PERF_CNT_SEL__CNT_2; ++ perfcnt_sel |= FIELD_PREP(MLXBF_L3C_PERF_CNT_SEL__CNT_2, evt); + break; + case 3: +- perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3; +- perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, +- evt); ++ perfcnt_sel &= ~MLXBF_L3C_PERF_CNT_SEL__CNT_3; ++ perfcnt_sel |= FIELD_PREP(MLXBF_L3C_PERF_CNT_SEL__CNT_3, evt); + break; + case 4: +- perfcnt_sel_1 &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4; +- perfcnt_sel_1 |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4, ++ perfcnt_sel_1 &= ~MLXBF_L3C_PERF_CNT_SEL_1__CNT_4; ++ perfcnt_sel_1 |= FIELD_PREP(MLXBF_L3C_PERF_CNT_SEL_1__CNT_4, + evt); + break; + default: + return -EINVAL; + } + +- return mlxbf_pmc_write(pmcaddr, MLXBF_PMC_WRITE_REG_32, *wordaddr); ++ return mlxbf_pmc_writel(*wordaddr, pmcaddr); + } + + /* Method to program a counter to monitor an event */ +-static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num, +- uint32_t evt, bool is_l3) ++int mlxbf_program_counter(int blk_num, uint32_t cnt_num, uint32_t evt, ++ bool is_l3) + { + uint64_t perfctl, perfevt, perfmon_cfg; + +@@ -716,76 +388,73 @@ static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num, + return -ENODEV; + + if (is_l3) +- return mlxbf_pmc_program_l3_counter(blk_num, cnt_num, evt); ++ return mlxbf_program_l3_counter(blk_num, cnt_num, evt); + + /* Configure the counter */ +- perfctl = FIELD_PREP(MLXBF_PMC_PERFCTL_EN0, 1); +- perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_EB0, 0); +- perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ETRIG0, 1); +- perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_AD0, 0); +- perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ACCM0, 0); +- perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_MS0, 0); +- perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_FM0, 0); +- +- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfctl); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, +- MLXBF_PMC_PERFCTL); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); +- +- if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + +- cnt_num * MLXBF_PMC_REG_SIZE, +- MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ perfctl = 0; ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__EN0, 1); ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__EB0, 0); ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__ETRIG0, 1); ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__AD0, 0); ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__ACCM0, 0); ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__MS0, 0); ++ perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__FM0, 0); ++ ++ perfmon_cfg = 0; ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WDATA, perfctl); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, ++ MLXBF_PERFCTL); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 1); ++ ++ if (mlxbf_pmc_writeq(perfmon_cfg, ++ pmc->block[blk_num].mmio_base + cnt_num * 8)) + return -EFAULT; + + /* Select the event */ +- perfevt = FIELD_PREP(MLXBF_PMC_PERFEVT_EVTSEL, evt); +- +- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfevt); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, +- MLXBF_PMC_PERFEVT); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); +- +- if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + +- cnt_num * MLXBF_PMC_REG_SIZE, +- MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ perfevt = 0; ++ perfevt |= FIELD_PREP(MLXBF_GEN_PERFEVT__EVTSEL, evt); ++ ++ perfmon_cfg = 0; ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WDATA, perfevt); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, ++ MLXBF_PERFEVT); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 1); ++ ++ if (mlxbf_pmc_writeq(perfmon_cfg, ++ pmc->block[blk_num].mmio_base + cnt_num * 8)) + return -EFAULT; + + /* Clear the accumulator */ +- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, +- MLXBF_PMC_PERFACC0); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); +- +- if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + +- cnt_num * MLXBF_PMC_REG_SIZE, +- MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ perfmon_cfg = 0; ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, ++ MLXBF_PERFACC0); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 1); ++ ++ if (mlxbf_pmc_writeq(perfmon_cfg, pmc->block[blk_num].mmio_base ++ + cnt_num * 8)) + return -EFAULT; + + return 0; + } + + /* Method to handle l3 counter reads */ +-static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num, +- uint64_t *result) ++int mlxbf_read_l3_counter(int blk_num, uint32_t cnt_num, uint64_t *result) + { + uint32_t perfcnt_low = 0, perfcnt_high = 0; + uint64_t value; + int status = 0; + +- status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_LOW + +- cnt_num * MLXBF_PMC_L3C_REG_SIZE, +- &perfcnt_low); ++ status = mlxbf_pmc_readl(&perfcnt_low, pmc->block[blk_num].mmio_base + ++ MLXBF_L3C_PERF_CNT_LOW + cnt_num * 4); + + if (status) + return status; + +- status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_HIGH + +- cnt_num * MLXBF_PMC_L3C_REG_SIZE, +- &perfcnt_high); ++ status = mlxbf_pmc_readl(&perfcnt_high, pmc->block[blk_num].mmio_base + ++ MLXBF_L3C_PERF_CNT_HIGH + cnt_num * 4); + + if (status) + return status; +@@ -799,8 +468,8 @@ static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num, + } + + /* Method to read the counter value */ +-static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3, +- uint64_t *result) ++int mlxbf_read_counter(int blk_num, uint32_t cnt_num, bool is_l3, ++ uint64_t *result) + { + uint32_t perfcfg_offset, perfval_offset; + uint64_t perfmon_cfg; +@@ -810,73 +479,74 @@ static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3, + return -EINVAL; + + if (is_l3) +- return mlxbf_pmc_read_l3_counter(blk_num, cnt_num, result); ++ return mlxbf_read_l3_counter(blk_num, cnt_num, result); + +- perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE; +- perfval_offset = perfcfg_offset + +- pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE; ++ perfcfg_offset = cnt_num * 8; ++ perfval_offset = perfcfg_offset + pmc->block[blk_num].counters * 8; + + /* Set counter in "read" mode */ +- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, +- MLXBF_PMC_PERFACC0); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); ++ perfmon_cfg = 0; ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, ++ MLXBF_PERFACC0); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 0); + +- status = mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, +- MLXBF_PMC_WRITE_REG_64, perfmon_cfg); ++ status = mlxbf_pmc_writeq(perfmon_cfg, pmc->block[blk_num].mmio_base + ++ perfcfg_offset); + + if (status) + return status; + + /* Get the counter value */ +- return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, +- MLXBF_PMC_READ_REG_64, result); ++ return mlxbf_pmc_readq(result, ++ pmc->block[blk_num].mmio_base + perfval_offset); + } + +-/* Method to read L3 block event */ +-static int mlxbf_pmc_read_l3_event(int blk_num, uint32_t cnt_num, +- uint64_t *result) ++int mlxbf_read_l3_event(int blk_num, uint32_t cnt_num, uint64_t *result) + { + uint32_t perfcnt_sel = 0, perfcnt_sel_1 = 0; + uint32_t *wordaddr; +- void __iomem *pmcaddr; ++ void *pmcaddr; + uint64_t evt; + + /* Select appropriate register information */ + switch (cnt_num) { +- case 0 ... 3: ++ case 0: ++ case 1: ++ case 2: ++ case 3: + pmcaddr = pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_SEL; ++ MLXBF_L3C_PERF_CNT_SEL; + wordaddr = &perfcnt_sel; + break; + case 4: + pmcaddr = pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_SEL_1; ++ MLXBF_L3C_PERF_CNT_SEL_1; + wordaddr = &perfcnt_sel_1; + break; + default: + return -EINVAL; + } + +- if (mlxbf_pmc_readl(pmcaddr, wordaddr)) ++ if (mlxbf_pmc_readl(wordaddr, pmcaddr)) + return -EINVAL; + + /* Read from appropriate register field for the counter */ + switch (cnt_num) { + case 0: +- evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, perfcnt_sel); ++ evt = FIELD_GET(MLXBF_L3C_PERF_CNT_SEL__CNT_0, perfcnt_sel); + break; + case 1: +- evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, perfcnt_sel); ++ evt = FIELD_GET(MLXBF_L3C_PERF_CNT_SEL__CNT_1, perfcnt_sel); + break; + case 2: +- evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, perfcnt_sel); ++ evt = FIELD_GET(MLXBF_L3C_PERF_CNT_SEL__CNT_2, perfcnt_sel); + break; + case 3: +- evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, perfcnt_sel); ++ evt = FIELD_GET(MLXBF_L3C_PERF_CNT_SEL__CNT_3, perfcnt_sel); + break; + case 4: +- evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4, ++ evt = FIELD_GET(MLXBF_L3C_PERF_CNT_SEL_1__CNT_4, + perfcnt_sel_1); + break; + default: +@@ -888,8 +558,8 @@ static int mlxbf_pmc_read_l3_event(int blk_num, uint32_t cnt_num, + } + + /* Method to find the event currently being monitored by a counter */ +-static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3, +- uint64_t *result) ++int mlxbf_read_event(int blk_num, uint32_t cnt_num, bool is_l3, ++ uint64_t *result) + { + uint32_t perfcfg_offset, perfval_offset; + uint64_t perfmon_cfg, perfevt, perfctl; +@@ -898,112 +568,115 @@ static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3, + return -EINVAL; + + if (is_l3) +- return mlxbf_pmc_read_l3_event(blk_num, cnt_num, result); ++ return mlxbf_read_l3_event(blk_num, cnt_num, result); + +- perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE; +- perfval_offset = perfcfg_offset + +- pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE; ++ perfcfg_offset = cnt_num * 8; ++ perfval_offset = perfcfg_offset + pmc->block[blk_num].counters * 8; + + /* Set counter in "read" mode */ +- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, +- MLXBF_PMC_PERFCTL); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); +- +- if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, +- MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ perfmon_cfg = 0; ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, ++ MLXBF_PERFCTL); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 0); ++ ++ if (mlxbf_pmc_writeq(perfmon_cfg, ++ pmc->block[blk_num].mmio_base + perfcfg_offset)) + return -EFAULT; + + /* Check if the counter is enabled */ + +- if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, +- MLXBF_PMC_READ_REG_64, &perfctl)) ++ if (mlxbf_pmc_readq(&perfctl, ++ pmc->block[blk_num].mmio_base + perfval_offset)) + return -EFAULT; + +- if (!FIELD_GET(MLXBF_PMC_PERFCTL_EN0, perfctl)) ++ if (FIELD_GET(MLXBF_GEN_PERFCTL__EN0, perfctl) == 0) + return -EINVAL; + + /* Set counter in "read" mode */ +- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, +- MLXBF_PMC_PERFEVT); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); +- +- if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, +- MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) ++ perfmon_cfg = 0; ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, ++ MLXBF_PERFEVT); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); ++ perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 0); ++ ++ if (mlxbf_pmc_writeq(perfmon_cfg, pmc->block[blk_num].mmio_base + ++ perfcfg_offset)) + return -EFAULT; + + /* Get the event number */ +- if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, +- MLXBF_PMC_READ_REG_64, &perfevt)) ++ if (mlxbf_pmc_readq(&perfevt, pmc->block[blk_num].mmio_base + ++ perfval_offset)) + return -EFAULT; + +- *result = FIELD_GET(MLXBF_PMC_PERFEVT_EVTSEL, perfevt); ++ *result = FIELD_GET(MLXBF_GEN_PERFEVT__EVTSEL, perfevt); + + return 0; + } + + /* Method to read a register */ +-static int mlxbf_pmc_read_reg(int blk_num, uint32_t offset, uint64_t *result) ++int mlxbf_read_reg(int blk_num, uint32_t offset, uint64_t *result) + { + uint32_t ecc_out; + + if (strstr(pmc->block_name[blk_num], "ecc")) { +- if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + offset, +- &ecc_out)) ++ if (mlxbf_pmc_readl(&ecc_out, ++ pmc->block[blk_num].mmio_base + offset)) + return -EFAULT; + +- *result = ecc_out; ++ *result = (uint64_t) ecc_out; + return 0; + } + + if (mlxbf_pmc_valid_range(blk_num, offset)) +- return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + offset, +- MLXBF_PMC_READ_REG_64, result); ++ return mlxbf_pmc_readq(result, ++ pmc->block[blk_num].mmio_base + offset); + + return -EINVAL; + } + + /* Method to write to a register */ +-static int mlxbf_pmc_write_reg(int blk_num, uint32_t offset, uint64_t data) ++int mlxbf_write_reg(int blk_num, uint32_t offset, uint64_t data) + { + if (strstr(pmc->block_name[blk_num], "ecc")) { +- return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, +- MLXBF_PMC_WRITE_REG_32, data); ++ return mlxbf_pmc_writel((uint32_t)data, ++ pmc->block[blk_num].mmio_base + offset); + } + + if (mlxbf_pmc_valid_range(blk_num, offset)) +- return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, +- MLXBF_PMC_WRITE_REG_64, data); ++ return mlxbf_pmc_writeq(data, ++ pmc->block[blk_num].mmio_base + offset); + + return -EINVAL; + } + + /* Show function for "counter" sysfs files */ +-static ssize_t mlxbf_pmc_counter_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t mlxbf_counter_read(struct kobject *ko, ++ struct kobj_attribute *attr, char *buf) + { +- struct mlxbf_pmc_attribute *attr_counter = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); +- int blk_num, cnt_num, offset; ++ int blk_num, cnt_num, offset, err; + bool is_l3 = false; + uint64_t value; + +- blk_num = attr_counter->nr; +- cnt_num = attr_counter->index; ++ blk_num = mlxbf_pmc_get_block_num(ko->name); ++ if (blk_num < 0) ++ return -EINVAL; + +- if (strstr(pmc->block_name[blk_num], "l3cache")) ++ if (strstr(ko->name, "l3cache")) + is_l3 = true; + +- if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) { +- if (mlxbf_pmc_read_counter(blk_num, cnt_num, is_l3, &value)) ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) { ++ err = sscanf(attr->attr.name, "counter%d", &cnt_num); ++ if (err < 0) ++ return -EINVAL; ++ if (mlxbf_read_counter(blk_num, cnt_num, is_l3, &value)) + return -EINVAL; +- } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) { +- offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], +- attr->attr.name); ++ } else if (pmc->block[blk_num].type == MLXBF_PERFTYPE_REGISTER) { ++ offset = mlxbf_pmc_get_event_num((char *)ko->name, ++ (char *)attr->attr.name); + if (offset < 0) + return -EINVAL; +- if (mlxbf_pmc_read_reg(blk_num, offset, &value)) ++ if (mlxbf_read_reg(blk_num, offset, &value)) + return -EINVAL; + } else + return -EINVAL; +@@ -1012,47 +685,47 @@ static ssize_t mlxbf_pmc_counter_show(struct device *dev, + } + + /* Store function for "counter" sysfs files */ +-static ssize_t mlxbf_pmc_counter_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) ++static ssize_t mlxbf_counter_clear(struct kobject *ko, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) + { +- struct mlxbf_pmc_attribute *attr_counter = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); + int blk_num, cnt_num, offset, err, data; + bool is_l3 = false; + uint64_t evt_num; + +- blk_num = attr_counter->nr; +- cnt_num = attr_counter->index; ++ blk_num = mlxbf_pmc_get_block_num(ko->name); ++ if (blk_num < 0) ++ return -EINVAL; + +- err = kstrtoint(buf, 0, &data); ++ err = sscanf(buf, "%x\n", &data); + if (err < 0) +- return err; ++ return -EINVAL; + + /* Allow non-zero writes only to the ecc regs */ +- if (!(strstr(pmc->block_name[blk_num], "ecc")) && data) ++ if (!(strstr(ko->name, "ecc")) && (data != 0)) + return -EINVAL; + +- /* Do not allow writes to the L3C regs */ +- if (strstr(pmc->block_name[blk_num], "l3cache")) ++ if (strstr(ko->name, "l3cache")) + return -EINVAL; + +- if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) { +- err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num); +- if (err) +- return err; +- err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, +- is_l3); +- if (err) +- return err; +- } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) { +- offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], +- attr->attr.name); ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) { ++ err = sscanf(attr->attr.name, "counter%d", &cnt_num); ++ if (err < 0) ++ return -EINVAL; ++ err = mlxbf_read_event(blk_num, cnt_num, is_l3, &evt_num); ++ if (err < 0) ++ return -EINVAL; ++ err = mlxbf_program_counter(blk_num, cnt_num, evt_num, is_l3); ++ if (err < 0) ++ return -EINVAL; ++ } else if (pmc->block[blk_num].type == MLXBF_PERFTYPE_REGISTER) { ++ offset = mlxbf_pmc_get_event_num((char *)ko->name, ++ (char *)attr->attr.name); + if (offset < 0) + return -EINVAL; +- err = mlxbf_pmc_write_reg(blk_num, offset, data); +- if (err) +- return err; ++ err = mlxbf_write_reg(blk_num, offset, data); ++ if (err < 0) ++ return -EINVAL; + } else + return -EINVAL; + +@@ -1060,141 +733,140 @@ static ssize_t mlxbf_pmc_counter_store(struct device *dev, + } + + /* Show function for "event" sysfs files */ +-static ssize_t mlxbf_pmc_event_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t mlxbf_event_find(struct kobject *ko, ++ struct kobj_attribute *attr, char *buf) + { +- struct mlxbf_pmc_attribute *attr_event = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); + int blk_num, cnt_num, err; + bool is_l3 = false; + uint64_t evt_num; + char *evt_name; + +- blk_num = attr_event->nr; +- cnt_num = attr_event->index; ++ blk_num = mlxbf_pmc_get_block_num(ko->name); ++ if (blk_num < 0) ++ return -EINVAL; + +- if (strstr(pmc->block_name[blk_num], "l3cache")) ++ if (strstr(ko->name, "l3cache")) + is_l3 = true; + +- err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num); +- if (err) +- return sprintf(buf, "No event being monitored\n"); ++ err = sscanf(attr->attr.name, "event%d", &cnt_num); ++ if (err < 0) ++ return -EINVAL; + +- evt_name = mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num); +- if (!evt_name) ++ err = mlxbf_read_event(blk_num, cnt_num, is_l3, &evt_num); ++ if (err < 0) + return -EINVAL; + ++ evt_name = mlxbf_pmc_get_event_name((char *)ko->name, evt_num); ++ + return sprintf(buf, "0x%llx: %s\n", evt_num, evt_name); + } + + /* Store function for "event" sysfs files */ +-static ssize_t mlxbf_pmc_event_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) ++static ssize_t mlxbf_event_set(struct kobject *ko, struct kobj_attribute *attr, ++ const char *buf, size_t count) + { +- struct mlxbf_pmc_attribute *attr_event = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); + int blk_num, cnt_num, evt_num, err; + bool is_l3 = false; + +- blk_num = attr_event->nr; +- cnt_num = attr_event->index; +- + if (isalpha(buf[0])) { +- evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], +- buf); ++ evt_num = mlxbf_pmc_get_event_num((char *)ko->name, ++ (char *)buf); + if (evt_num < 0) + return -EINVAL; + } else { +- err = kstrtoint(buf, 0, &evt_num); ++ err = sscanf(buf, "%x\n", &evt_num); + if (err < 0) +- return err; ++ return -EINVAL; + } + +- if (strstr(pmc->block_name[blk_num], "l3cache")) ++ blk_num = mlxbf_pmc_get_block_num(ko->name); ++ if (blk_num < 0) ++ return -EINVAL; ++ ++ err = sscanf(attr->attr.name, "event%d", &cnt_num); ++ if (err < 0) ++ return -EINVAL; ++ ++ if (strstr(ko->name, "l3cache")) + is_l3 = true; + +- err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, is_l3); +- if (err) +- return err; ++ err = mlxbf_program_counter(blk_num, cnt_num, evt_num, is_l3); ++ if (err < 0) ++ return -EINVAL; + + return count; + } + + /* Show function for "event_list" sysfs files */ +-static ssize_t mlxbf_pmc_event_list_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) ++static ssize_t mlxbf_print_event_list(struct kobject *ko, ++ struct kobj_attribute *attr, char *buf) + { +- struct mlxbf_pmc_attribute *attr_event_list = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); +- int blk_num, i, size, len = 0, ret = 0; +- const struct mlxbf_pmc_events *events; +- char e_info[MLXBF_PMC_EVENT_INFO_LEN]; +- +- blk_num = attr_event_list->nr; ++ struct mlxbf_pmc_events *events; ++ int i = 0, size = 0, ret = 0; ++ char e_info[100]; + +- events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &size); +- if (!events) ++ events = mlxbf_pmc_event_list((char *)ko->name); ++ if (events == NULL) + return -EINVAL; + +- for (i = 0, buf[0] = '\0'; i < size; ++i) { +- len += sprintf(e_info, "0x%x: %s\n", events[i].evt_num, +- events[i].evt_name); +- if (len > PAGE_SIZE) ++ buf[0] = '\0'; ++ while (events[i].evt_name != NULL) { ++ size += sprintf(e_info, "%x: %s\n", events[i].evt_num, ++ events[i].evt_name); ++ if (size > PAGE_SIZE) + break; + strcat(buf, e_info); +- ret = len; ++ ret = size; ++ ++i; + } + + return ret; + } + + /* Show function for "enable" sysfs files - only for l3cache */ +-static ssize_t mlxbf_pmc_enable_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t mlxbf_show_counter_state(struct kobject *ko, ++ struct kobj_attribute *attr, char *buf) + { +- struct mlxbf_pmc_attribute *attr_enable = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); + uint32_t perfcnt_cfg; + int blk_num, value; + +- blk_num = attr_enable->nr; ++ blk_num = mlxbf_pmc_get_block_num(ko->name); ++ if (blk_num < 0) ++ return -EINVAL; + +- if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + +- MLXBF_PMC_L3C_PERF_CNT_CFG, +- &perfcnt_cfg)) ++ if (mlxbf_pmc_readl(&perfcnt_cfg, ++ pmc->block[blk_num].mmio_base + MLXBF_L3C_PERF_CNT_CFG)) + return -EINVAL; + +- value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg); ++ value = FIELD_GET(MLXBF_L3C_PERF_CNT_CFG__EN, perfcnt_cfg); + + return sprintf(buf, "%d\n", value); + } + + /* Store function for "enable" sysfs files - only for l3cache */ +-static ssize_t mlxbf_pmc_enable_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) ++static ssize_t mlxbf_enable_counters(struct kobject *ko, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) + { +- struct mlxbf_pmc_attribute *attr_enable = container_of( +- attr, struct mlxbf_pmc_attribute, dev_attr); + int err, en, blk_num; + +- blk_num = attr_enable->nr; ++ blk_num = mlxbf_pmc_get_block_num(ko->name); ++ if (blk_num < 0) ++ return -EINVAL; + +- err = kstrtoint(buf, 0, &en); ++ err = sscanf(buf, "%x\n", &en); + if (err < 0) + return err; + +- if (!en) { +- err = mlxbf_pmc_config_l3_counters(blk_num, false, false); ++ if (en == 0) { ++ err = mlxbf_config_l3_counters(blk_num, false, false); + if (err) + return err; + } else if (en == 1) { +- err = mlxbf_pmc_config_l3_counters(blk_num, false, true); ++ err = mlxbf_config_l3_counters(blk_num, false, true); + if (err) + return err; +- err = mlxbf_pmc_config_l3_counters(blk_num, true, false); ++ err = mlxbf_config_l3_counters(blk_num, true, false); + if (err) + return err; + } else +@@ -1203,277 +875,379 @@ static ssize_t mlxbf_pmc_enable_store(struct device *dev, + return count; + } + +-/* Populate attributes for blocks with counters to monitor performance */ +-static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num) ++/* Helper to create the bfperf sysfs sub-directories and files */ ++int mlxbf_pmc_create_sysfs(struct device *dev, struct kobject *ko, int blk_num) + { +- struct mlxbf_pmc_attribute *attr; +- int i = 0, j = 0; +- +- /* "event_list" sysfs to list events supported by the block */ +- attr = &pmc->block[blk_num].attr_event_list; +- attr->dev_attr.attr.mode = 0444; +- attr->dev_attr.show = mlxbf_pmc_event_list_show; +- attr->nr = blk_num; +- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list"); +- pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr; +- attr = NULL; +- +- /* "enable" sysfs to start/stop the counters. Only in L3C blocks */ +- if (strstr(pmc->block_name[blk_num], "l3cache")) { +- attr = &pmc->block[blk_num].attr_enable; +- attr->dev_attr.attr.mode = 0644; +- attr->dev_attr.show = mlxbf_pmc_enable_show; +- attr->dev_attr.store = mlxbf_pmc_enable_store; +- attr->nr = blk_num; +- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, +- "enable"); +- pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; +- attr = NULL; ++ int err = 0, j = 0; ++ ++ pmc->block[blk_num].block_dir = ++ kobject_create_and_add(pmc->block_name[blk_num], ko); ++ if (pmc->block[blk_num].block_dir == NULL) { ++ dev_err(dev, ++ "PMC: Error creating subdirectories\n"); ++ return -EFAULT; + } + +- pmc->block[blk_num].attr_counter = devm_kcalloc( +- dev, pmc->block[blk_num].counters, +- sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); +- if (!pmc->block[blk_num].attr_counter) +- return -ENOMEM; ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) { ++ pmc->block[blk_num].attr_event_list.attr.mode = 0444; ++ pmc->block[blk_num].attr_event_list.show = ++ mlxbf_print_event_list; ++ pmc->block[blk_num].attr_event_list.attr.name = ++ kzalloc(20, GFP_KERNEL); ++ snprintf((char *)pmc->block[blk_num].attr_event_list.attr.name, ++ 20, "event_list"); ++ ++ err = sysfs_create_file(pmc->block[blk_num].block_dir, ++ &pmc->block[blk_num].attr_event_list.attr); ++ if (err < 0) { ++ dev_err(dev, ++ "PMC: Error creating sysfs entries\n"); ++ return err; ++ } + +- pmc->block[blk_num].attr_event = devm_kcalloc( +- dev, pmc->block[blk_num].counters, +- sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); +- if (!pmc->block[blk_num].attr_event) +- return -ENOMEM; ++ if (strstr(pmc->block_name[blk_num], "l3cache")) { ++ pmc->block[blk_num].attr_enable.attr.mode = ++ 0644; ++ pmc->block[blk_num].attr_enable.show = ++ mlxbf_show_counter_state; ++ pmc->block[blk_num].attr_enable.store = ++ mlxbf_enable_counters; ++ pmc->block[blk_num].attr_enable.attr.name = ++ kzalloc(20, GFP_KERNEL); ++ snprintf((char *) ++ pmc->block[blk_num].attr_enable.attr.name, ++ 20, "enable"); ++ ++ err = sysfs_create_file( ++ pmc->block[blk_num].block_dir, ++ &pmc->block[blk_num].attr_enable.attr); ++ if (err < 0) { ++ dev_err(dev, ++ "PMC: Error creating sysfs entries\n"); ++ return err; ++ } + +- /* "eventX" and "counterX" sysfs to program and read counter values */ +- for (j = 0; j < pmc->block[blk_num].counters; ++j) { +- attr = &pmc->block[blk_num].attr_counter[j]; +- attr->dev_attr.attr.mode = 0644; +- attr->dev_attr.show = mlxbf_pmc_counter_show; +- attr->dev_attr.store = mlxbf_pmc_counter_store; +- attr->index = j; +- attr->nr = blk_num; +- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, +- "counter%d", j); +- pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; +- attr = NULL; +- +- attr = &pmc->block[blk_num].attr_event[j]; +- attr->dev_attr.attr.mode = 0644; +- attr->dev_attr.show = mlxbf_pmc_event_show; +- attr->dev_attr.store = mlxbf_pmc_event_store; +- attr->index = j; +- attr->nr = blk_num; +- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, +- "event%d", j); +- pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; +- attr = NULL; +- } ++ } + +- return 0; ++ pmc->block[blk_num].attr_counter = ++ kcalloc(pmc->block[blk_num].counters, ++ sizeof(struct kobj_attribute), GFP_KERNEL); ++ if (!pmc->block[blk_num].attr_counter) ++ return -ENOMEM; ++ pmc->block[blk_num].attr_event = ++ kcalloc(pmc->block[blk_num].counters, ++ sizeof(struct kobj_attribute), GFP_KERNEL); ++ if (!pmc->block[blk_num].attr_event) ++ return -ENOMEM; ++ pmc->block[blk_num].sysfs_event_cnt = ++ pmc->block[blk_num].counters; ++ ++ for (j = 0; j < pmc->block[blk_num].counters; ++j) { ++ pmc->block[blk_num].attr_counter[j].attr.mode = 0644; ++ pmc->block[blk_num].attr_counter[j].show = ++ mlxbf_counter_read; ++ pmc->block[blk_num].attr_counter[j].store = ++ mlxbf_counter_clear; ++ pmc->block[blk_num].attr_counter[j].attr.name = ++ kzalloc(20, GFP_KERNEL); ++ snprintf((char *) ++ pmc->block[blk_num].attr_counter[j].attr.name, ++ 20, "counter%d", j); ++ ++ err = sysfs_create_file( ++ pmc->block[blk_num].block_dir, ++ &pmc->block[blk_num].attr_counter[j].attr); ++ if (err < 0) { ++ dev_err(dev, ++ "PMC: Error creating sysfs entries\n"); ++ return err; ++ } ++ ++ pmc->block[blk_num].attr_event[j].attr.mode = 0644; ++ pmc->block[blk_num].attr_event[j].show = ++ mlxbf_event_find; ++ pmc->block[blk_num].attr_event[j].store = ++ mlxbf_event_set; ++ pmc->block[blk_num].attr_event[j].attr.name = ++ kzalloc(20, GFP_KERNEL); ++ snprintf((char *) ++ pmc->block[blk_num].attr_event[j].attr.name, ++ 20, "event%d", j); ++ ++ err = sysfs_create_file( ++ pmc->block[blk_num].block_dir, ++ &pmc->block[blk_num].attr_event[j].attr); ++ if (err < 0) { ++ dev_err(dev, ++ "PMC: Error creating sysfs entries\n"); ++ return err; ++ } ++ } ++ } else if (pmc->block[blk_num].type == MLXBF_PERFTYPE_REGISTER) { ++ struct mlxbf_pmc_events *events; ++ ++ events = mlxbf_pmc_event_list((char *)pmc->block_name[blk_num]); ++ if (events == NULL) ++ return -EINVAL; ++ ++ while (events[j].evt_name != NULL) ++ ++j; ++ ++ pmc->block[blk_num].sysfs_event_cnt = j; ++ pmc->block[blk_num].attr_event = ++ kcalloc(j, sizeof(struct kobj_attribute), GFP_KERNEL); ++ if (!pmc->block[blk_num].attr_event) ++ return -ENOMEM; ++ ++ while (j > 0) { ++ --j; ++ pmc->block[blk_num].attr_event[j].attr.mode = 0644; ++ pmc->block[blk_num].attr_event[j].show = ++ mlxbf_counter_read; ++ pmc->block[blk_num].attr_event[j].store = ++ mlxbf_counter_clear; ++ pmc->block[blk_num].attr_event[j].attr.name = ++ kzalloc(30, GFP_KERNEL); ++ strcpy((char *) ++ pmc->block[blk_num].attr_event[j].attr.name, ++ events[j].evt_name); ++ ++ err = sysfs_create_file( ++ pmc->block[blk_num].block_dir, ++ &pmc->block[blk_num].attr_event[j].attr); ++ if (err < 0) { ++ dev_err(dev, ++ "PMC: Error creating sysfs entries\n"); ++ return err; ++ } ++ } ++ } else ++ err = -EINVAL; ++ ++ return err; + } + +-/* Populate attributes for blocks with registers to monitor performance */ +-static int mlxbf_pmc_init_perftype_reg(struct device *dev, int blk_num) ++void mlxbf_pmc_delete(void) + { +- struct mlxbf_pmc_attribute *attr; +- const struct mlxbf_pmc_events *events; +- int i = 0, j = 0; ++ hwmon_device_unregister(pmc->hwmon_dev); ++ kfree(pmc); ++} + +- events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &j); +- if (!events) +- return -EINVAL; ++static int mlxbf_pmc_probe(struct platform_device *pdev) ++{ ++ struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev); ++ const char *hid = acpi_device_hid(acpi_dev); ++ int i, version, err = 0, ret = 0; ++ struct device *dev = &pdev->dev; ++ struct arm_smccc_res res; ++ uint64_t info[4]; + +- pmc->block[blk_num].attr_event = devm_kcalloc( +- dev, j, sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); +- if (!pmc->block[blk_num].attr_event) ++ /* ++ * Ensure we have the UUID we expect for the Mellanox service. ++ */ ++ arm_smccc_smc(MLNX_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0 != 0x89c036b4 || res.a1 != 0x11e6e7d7 || ++ res.a2 != 0x1a009787 || res.a3 != 0xc4bf00ca) ++ return -ENODEV; ++ ++ pmc = kzalloc(sizeof(struct mlxbf_pmc_context), GFP_KERNEL); ++ if (!pmc) + return -ENOMEM; + +- while (j > 0) { +- --j; +- attr = &pmc->block[blk_num].attr_event[j]; +- attr->dev_attr.attr.mode = 0644; +- attr->dev_attr.show = mlxbf_pmc_counter_show; +- attr->dev_attr.store = mlxbf_pmc_counter_store; +- attr->nr = blk_num; +- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, +- events[j].evt_name); +- pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr; +- attr = NULL; +- i++; +- } ++ platform_set_drvdata(pdev, pmc); ++ pmc->pdev = pdev; + +- return 0; +-} ++ pmc->hwmon_dev = hwmon_device_register_with_info(dev, "bfperf", pmc, ++ NULL, NULL); ++ pmc->ko = &pmc->hwmon_dev->kobj; + +-/* Helper to create the bfperf sysfs sub-directories and files */ +-static int mlxbf_pmc_create_groups(struct device *dev, int blk_num) +-{ +- int err; ++ /* ++ * ACPI indicates whether we use SMCs to access registers or not. ++ * If sreg_tbl_perf is not present, just assume we're not using SMCs. ++ */ ++ if (device_property_read_u32(dev, ++ "sec_reg_block", &pmc->sreg_tbl_perf)) { ++ pmc->svc_sreg_support = false; ++ } else { ++ /* ++ * Check service version to see if we actually do support the ++ * needed SMCs. If we have the calls we need, mark support for ++ * them in the pmc struct. ++ */ ++ arm_smccc_smc(MLNX_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0 == MLNX_PMC_SVC_REQ_MAJOR && ++ res.a1 >= MLNX_PMC_SVC_MIN_MINOR) ++ pmc->svc_sreg_support = true; ++ else { ++ dev_err(dev, "Required SMCs are not supported.\n"); + +- /* Populate attributes based on counter type */ +- if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) +- err = mlxbf_pmc_init_perftype_counter(dev, blk_num); +- else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) +- err = mlxbf_pmc_init_perftype_reg(dev, blk_num); +- else +- err = -EINVAL; ++ err = -EINVAL; ++ goto error; ++ } ++ } + +- if (err) +- return err; ++ if (pmc->ko == NULL) { ++ dev_err(dev, "Sysfs creation failed\n"); ++ err = -EFAULT; ++ goto error; ++ } + +- /* Add a new attribute_group for the block */ +- pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr; +- pmc->block[blk_num].block_attr_grp.name = devm_kasprintf( +- dev, GFP_KERNEL, pmc->block_name[blk_num]); +- pmc->groups[blk_num] = &pmc->block[blk_num].block_attr_grp; ++ if (device_property_read_u32(dev, "version", &version)) { ++ dev_err(dev, "Version Info not found\n"); ++ err = -EINVAL; ++ goto error; ++ } + +- return 0; +-} ++ if (version != (int)DRIVER_VERSION) { ++ dev_err(dev, "Version Mismatch. Expected %d Returned %d\n", ++ (int)DRIVER_VERSION, version); ++ err = -EINVAL; ++ goto error; ++ } + +-static bool mlxbf_pmc_guid_match(const guid_t *guid, +- const struct arm_smccc_res *res) +-{ +- guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16, res->a2, +- res->a2 >> 8, res->a2 >> 16, res->a2 >> 24, +- res->a3, res->a3 >> 8, res->a3 >> 16, +- res->a3 >> 24); ++ if (strcmp(hid, "MLNXBFD0") == 0) ++ pmc->event_set = MLNX_EVENT_SET_BF1; ++ else if (strcmp(hid, "MLNXBFD1") == 0) ++ pmc->event_set = MLNX_EVENT_SET_BF2; ++ else { ++ dev_err(dev, "Invalid device ID %s\n", hid); ++ err = -ENODEV; ++ goto error; ++ } + +- return guid_equal(guid, &id); +-} ++ if (device_property_read_u32(dev, "block_num", &pmc->total_blocks)) { ++ dev_err(dev, "Number of performance blocks undefined\n"); ++ err = -EINVAL; ++ goto error; ++ } + +-/* Helper to map the Performance Counters from the varios blocks */ +-static int mlxbf_pmc_map_counters(struct device *dev) +-{ +- uint64_t info[MLXBF_PMC_INFO_SZ]; +- int i, tile_num, ret; ++ ret = device_property_read_string_array(dev, "block_name", ++ pmc->block_name, pmc->total_blocks); ++ if (ret != pmc->total_blocks) { ++ dev_err(dev, ++ "Block count mismatch. Expected %d Returned %d\n", ++ pmc->total_blocks, ret); ++ err = -EFAULT; ++ goto error; ++ } ++ ++ if (device_property_read_u32(dev, "tile_num", &pmc->tile_count)) { ++ dev_err(dev, "Number of tiles undefined\n"); ++ err = -EINVAL; ++ goto error; ++ } + ++ /* Map the Performance Counters from the varios blocks */ + for (i = 0; i < pmc->total_blocks; ++i) { + if (strstr(pmc->block_name[i], "tile")) { +- ret = sscanf(pmc->block_name[i], "tile%d", &tile_num); +- if (ret < 0) +- return ret; ++ int tile_num; + ++ ret = sscanf(pmc->block_name[i], "tile%d", &tile_num); ++ if (ret < 0) { ++ err = -EINVAL; ++ goto error; ++ } + if (tile_num >= pmc->tile_count) + continue; + } +- ret = device_property_read_u64_array(dev, pmc->block_name[i], +- info, MLXBF_PMC_INFO_SZ); +- if (ret) +- return ret; ++ err = device_property_read_u64_array(dev, pmc->block_name[i], ++ info, 4); ++ if (err) { ++ dev_err(dev, "Failed to find %s block info\n", ++ pmc->block_name[i]); ++ goto error; ++ } + + /* + * Do not remap if the proper SMC calls are supported, + * since the SMC calls expect physical addresses. + */ + if (pmc->svc_sreg_support) +- pmc->block[i].mmio_base = (void __iomem *)info[0]; ++ pmc->block[i].mmio_base = (void *)info[0]; + else +- pmc->block[i].mmio_base = +- devm_ioremap(dev, info[0], info[1]); ++ pmc->block[i].mmio_base = ioremap(info[0], info[1]); + + pmc->block[i].blk_size = info[1]; + pmc->block[i].counters = info[2]; + pmc->block[i].type = info[3]; + +- if (!pmc->block[i].mmio_base) +- return -ENOMEM; ++ if (IS_ERR(pmc->block[i].mmio_base)) { ++ dev_err(dev, "%s: ioremap failed base %llx err %p\n", ++ __func__, info[0], pmc->block[i].mmio_base); ++ err = PTR_ERR(pmc->block[i].mmio_base); ++ goto error; ++ } + +- ret = mlxbf_pmc_create_groups(dev, i); +- if (ret) +- return ret; ++ err = mlxbf_pmc_create_sysfs(dev, pmc->ko, i); + } + ++ dev_info(&pdev->dev, "v%d probed\n", (int)DRIVER_VERSION); + return 0; ++ ++error: ++ mlxbf_pmc_delete(); ++ return err; + } + +-static int mlxbf_pmc_probe(struct platform_device *pdev) ++static int mlxbf_pmc_remove(struct platform_device *pdev) + { +- struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev); +- const char *hid = acpi_device_hid(acpi_dev); +- struct device *dev = &pdev->dev; +- struct arm_smccc_res res; +- guid_t guid; +- int ret; +- +- /* Ensure we have the UUID we expect for this service. */ +- arm_smccc_smc(MLXBF_PMC_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); +- guid_parse(mlxbf_pmc_svc_uuid_str, &guid); +- if (!mlxbf_pmc_guid_match(&guid, &res)) +- return -ENODEV; +- +- pmc = devm_kzalloc(dev, sizeof(struct mlxbf_pmc_context), GFP_KERNEL); +- if (!pmc) +- return -ENOMEM; +- +- /* +- * ACPI indicates whether we use SMCs to access registers or not. +- * If sreg_tbl_perf is not present, just assume we're not using SMCs. +- */ +- ret = device_property_read_u32(dev, "sec_reg_block", +- &pmc->sreg_tbl_perf); +- if (ret) { +- pmc->svc_sreg_support = false; +- } else { +- /* +- * Check service version to see if we actually do support the +- * needed SMCs. If we have the calls we need, mark support for +- * them in the pmc struct. +- */ +- arm_smccc_smc(MLXBF_PMC_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, +- &res); +- if (res.a0 == MLXBF_PMC_SVC_REQ_MAJOR && +- res.a1 >= MLXBF_PMC_SVC_MIN_MINOR) +- pmc->svc_sreg_support = true; +- else +- return -EINVAL; +- } ++ struct mlxbf_pmc_context *pmc = platform_get_drvdata(pdev); ++ int i, j, err; + +- if (!strcmp(hid, "MLNXBFD0")) +- pmc->event_set = MLXBF_PMC_EVENT_SET_BF1; +- else if (!strcmp(hid, "MLNXBFD1")) +- pmc->event_set = MLXBF_PMC_EVENT_SET_BF2; +- else +- return -ENODEV; +- +- ret = device_property_read_u32(dev, "block_num", &pmc->total_blocks); +- if (ret) +- return ret; +- +- ret = device_property_read_string_array(dev, "block_name", +- pmc->block_name, +- pmc->total_blocks); +- if (ret != pmc->total_blocks) +- return -EFAULT; ++ for (i = 0; i < pmc->total_blocks; ++i) { ++ if (strstr(pmc->block_name[i], "tile")) { ++ int tile_num; + +- ret = device_property_read_u32(dev, "tile_num", &pmc->tile_count); +- if (ret) +- return ret; ++ err = sscanf(pmc->block_name[i], "tile%d", &tile_num); ++ if (err < 0) ++ return -EINVAL; ++ if (tile_num >= pmc->tile_count) ++ continue; ++ } ++ kfree(pmc->block[i].attr_event_list.attr.name); ++ if (pmc->block[i].type == MLXBF_PERFTYPE_COUNTER) { ++ for (j = 0; j < pmc->block[i].counters; ++j) { ++ kfree(pmc->block[i].attr_counter[j].attr.name); ++ kfree(pmc->block[i].attr_event[j].attr.name); ++ } ++ } else if (pmc->block[i].type == MLXBF_PERFTYPE_REGISTER) { ++ for (j = 0; j < pmc->block[i].sysfs_event_cnt; ++j) ++ kfree(pmc->block[i].attr_event[j].attr.name); ++ } + +- pmc->pdev = pdev; ++ /* Unmap if SMCs weren't used for access */ ++ if (pmc->block[i].mmio_base && !(pmc->svc_sreg_support)) ++ iounmap(pmc->block[i].mmio_base); + +- ret = mlxbf_pmc_map_counters(dev); +- if (ret) +- return ret; ++ kobject_put(pmc->block[i].block_dir); ++ kfree(pmc->block[i].attr_event); ++ kfree(pmc->block[i].attr_counter); ++ } + +- pmc->hwmon_dev = devm_hwmon_device_register_with_groups( +- dev, "bfperf", pmc, pmc->groups); +- platform_set_drvdata(pdev, pmc); ++ mlxbf_pmc_delete(); + + return 0; + } + +-static const struct acpi_device_id mlxbf_pmc_acpi_ids[] = { { "MLNXBFD0", 0 }, +- { "MLNXBFD1", 0 }, +- {}, }; ++static const struct acpi_device_id pmc_acpi_ids[] = { ++ {"MLNXBFD0", 0}, ++ {"MLNXBFD1", 0}, ++ {}, ++}; + +-MODULE_DEVICE_TABLE(acpi, mlxbf_pmc_acpi_ids); ++MODULE_DEVICE_TABLE(acpi, pmc_acpi_ids); + static struct platform_driver pmc_driver = { +- .driver = { .name = "mlxbf-pmc", +- .acpi_match_table = ACPI_PTR(mlxbf_pmc_acpi_ids), }, ++ .driver = { ++ .name = "mlxbf-pmc", ++ .acpi_match_table = ACPI_PTR(pmc_acpi_ids), ++ }, + .probe = mlxbf_pmc_probe, ++ .remove = mlxbf_pmc_remove, + }; + + module_platform_driver(pmc_driver); + +-MODULE_AUTHOR("Shravan Kumar Ramani "); ++MODULE_AUTHOR("Shravan Kumar Ramani "); + MODULE_DESCRIPTION("Mellanox PMC driver"); + MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(__stringify(DRIVER_VERSION)); +diff --git a/drivers/platform/mellanox/mlxbf-pmc.h b/drivers/platform/mellanox/mlxbf-pmc.h +new file mode 100644 +index 000000000..b15614e90 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf-pmc.h +@@ -0,0 +1,428 @@ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause ++ ++#ifndef __MLXBF_PMC_H__ ++#define __MLXBF_PMC_H__ ++ ++#define MLNX_WRITE_REG_32 (0x82000009) ++#define MLNX_READ_REG_32 (0x8200000A) ++#define MLNX_WRITE_REG_64 (0x8200000B) ++#define MLNX_READ_REG_64 (0x8200000C) ++#define MLNX_SIP_SVC_UID (0x8200ff01) ++#define MLNX_SIP_SVC_VERSION (0x8200ff03) ++ ++#define SMCCC_INVALID_PARAMETERS (-2) ++#define SMCCC_OUT_OF_RANGE (-3) ++#define SMCCC_ACCESS_VIOLATION (-4) ++ ++#define MLNX_EVENT_SET_BF1 0 ++#define MLNX_EVENT_SET_BF2 1 ++ ++#define MLNX_PMC_SVC_REQ_MAJOR 0 ++#define MLNX_PMC_SVC_MIN_MINOR 3 ++ ++#define MLXBF_PMC_MAX_BLOCKS 30 ++ ++/** ++ * Structure to hold info for each HW block ++ * ++ * @mmio_base: The VA at which the PMC block is mapped ++ * @blk_size: Size of each mapped region ++ * @counters: Number of counters in the block ++ * @type: Type of counters in the block ++ * @block_dir: Kobjects to create sub-directories ++ * @attr_counter: Attributes for "counter" sysfs files ++ * @attr_event: Attributes for "event" sysfs files ++ * @attr_event_list: Attributes for "event_list" sysfs files ++ * @attr_enable: Attributes for "enable" sysfs files ++ * @sysfs_event_cnt: Number of sysfs event files in the block ++ */ ++struct mlxbf_pmc_block_info { ++ void *mmio_base; ++ size_t blk_size; ++ size_t counters; ++ int type; ++ struct kobject *block_dir; ++ struct kobj_attribute *attr_counter; ++ struct kobj_attribute *attr_event; ++ struct kobj_attribute attr_event_list; ++ struct kobj_attribute attr_enable; ++ int sysfs_event_cnt; ++}; ++ ++/** ++ * Structure to hold PMC context info ++ * ++ * @pdev: The kernel structure representing the device ++ * @total_blocks: Total number of blocks ++ * @tile_count: Number of tiles in the system ++ * @hwmon_dev: Hwmon device for bfperf ++ * @ko: Kobject for bfperf ++ * @block_name: Block name ++ * @block_name: Block info ++ * @sv_sreg_support: Whether SMCs are used to access performance registers ++ * @sreg_tbl_perf: Secure register access table number ++ * @event_set: Event set to use ++ */ ++struct mlxbf_pmc_context { ++ struct platform_device *pdev; ++ uint32_t total_blocks; ++ uint32_t tile_count; ++ struct device *hwmon_dev; ++ struct kobject *ko; ++ const char *block_name[MLXBF_PMC_MAX_BLOCKS]; ++ struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS]; ++ bool svc_sreg_support; ++ uint32_t sreg_tbl_perf; ++ unsigned int event_set; ++}; ++ ++#define MLXBF_PERFTYPE_COUNTER 1 ++#define MLXBF_PERFTYPE_REGISTER 0 ++ ++#define MLXBF_PERFCTL 0 ++#define MLXBF_PERFEVT 1 ++#define MLXBF_PERFVALEXT 2 ++#define MLXBF_PERFACC0 4 ++#define MLXBF_PERFACC1 5 ++#define MLXBF_PERFMVAL0 6 ++#define MLXBF_PERFMVAL1 7 ++ ++#define MLXBF_GEN_PERFMON_CONFIG__WR_R_B BIT(0) ++#define MLXBF_GEN_PERFMON_CONFIG__STROBE BIT(1) ++#define MLXBF_GEN_PERFMON_CONFIG__ADDR GENMASK_ULL(4, 2) ++#define MLXBF_GEN_PERFMON_CONFIG__WDATA GENMASK_ULL(60, 5) ++ ++#define MLXBF_GEN_PERFCTL__FM1 GENMASK_ULL(2, 0) ++#define MLXBF_GEN_PERFCTL__MS1 GENMASK_ULL(5, 4) ++#define MLXBF_GEN_PERFCTL__ACCM1 GENMASK_ULL(10, 8) ++#define MLXBF_GEN_PERFCTL__AD1 BIT(11) ++#define MLXBF_GEN_PERFCTL__ETRIG1 GENMASK_ULL(13, 12) ++#define MLXBF_GEN_PERFCTL__EB1 BIT(14) ++#define MLXBF_GEN_PERFCTL__EN1 BIT(15) ++#define MLXBF_GEN_PERFCTL__FM0 GENMASK_ULL(18, 16) ++#define MLXBF_GEN_PERFCTL__MS0 GENMASK_ULL(21, 20) ++#define MLXBF_GEN_PERFCTL__ACCM0 GENMASK_ULL(26, 24) ++#define MLXBF_GEN_PERFCTL__AD0 BIT(27) ++#define MLXBF_GEN_PERFCTL__ETRIG0 GENMASK_ULL(29, 28) ++#define MLXBF_GEN_PERFCTL__EB0 BIT(30) ++#define MLXBF_GEN_PERFCTL__EN0 BIT(31) ++ ++#define MLXBF_GEN_PERFEVT__PVALSEL GENMASK_ULL(19, 16) ++#define MLXBF_GEN_PERFEVT__MODSEL GENMASK_ULL(23, 20) ++#define MLXBF_GEN_PERFEVT__EVTSEL GENMASK_ULL(31, 24) ++ ++#define MLXBF_L3C_PERF_CNT_CFG 0x0 ++#define MLXBF_L3C_PERF_CNT_CFG_1 0x4 ++#define MLXBF_L3C_PERF_CNT_CFG_2 0x8 ++#define MLXBF_L3C_PERF_CNT_SEL 0x10 ++#define MLXBF_L3C_PERF_CNT_SEL_1 0x14 ++#define MLXBF_L3C_PERF_CNT_LOW 0x40 ++#define MLXBF_L3C_PERF_CNT_HIGH 0x60 ++ ++#define MLXBF_L3C_PERF_CNT_CFG__EN BIT(0) ++#define MLXBF_L3C_PERF_CNT_CFG__RST BIT(1) ++#define MLXBF_L3C_PERF_CNT_CFG__SRCID_SEL GENMASK(14, 8) ++#define MLXBF_L3C_PERF_CNT_CFG__SRCID_MASK GENMASK(22, 16) ++#define MLXBF_L3C_PERF_CNT_CFG__PRF_SEL GENMASK(27, 24) ++#define MLXBF_L3C_PERF_CNT_CFG__PRF_MASK GENMASK(31, 28) ++ ++#define MLXBF_L3C_PERF_CNT_CFG_1__SET_SEL GENMASK(10,0) ++#define MLXBF_L3C_PERF_CNT_CFG_1__SET_MASK GENMASK(22,12) ++#define MLXBF_L3C_PERF_CNT_CFG_1__EMEM_USAGE_TH GENMASK(30, 24) ++ ++#define MLXBF_L3C_PERF_CNT_CFG_2__STRM_SEL GENMASK(7, 0) ++#define MLXBF_L3C_PERF_CNT_CFG_2__STRM_MASK GENMASK(15, 8) ++ ++#define MLXBF_L3C_PERF_CNT_SEL__CNT_0 GENMASK(5, 0) ++#define MLXBF_L3C_PERF_CNT_SEL__CNT_1 GENMASK(13, 8) ++#define MLXBF_L3C_PERF_CNT_SEL__CNT_2 GENMASK(21, 16) ++#define MLXBF_L3C_PERF_CNT_SEL__CNT_3 GENMASK(29, 24) ++ ++#define MLXBF_L3C_PERF_CNT_SEL_1__CNT_4 GENMASK(5, 0) ++ ++#define MLXBF_L3C_PERF_CNT_LOW__VAL GENMASK(31, 0) ++#define MLXBF_L3C_PERF_CNT_HIGH__VAL GENMASK(24, 0) ++ ++struct mlxbf_pmc_events { ++ uint32_t evt_num; ++ char *evt_name; ++}; ++ ++struct mlxbf_pmc_events mlxbf_pcie_events[] = { ++{0x0, "IN_P_PKT_CNT"}, ++{0x10, "IN_NP_PKT_CNT"}, ++{0x18, "IN_C_PKT_CNT"}, ++{0x20, "OUT_P_PKT_CNT"}, ++{0x28, "OUT_NP_PKT_CNT"}, ++{0x30, "OUT_C_PKT_CNT"}, ++{0x38, "IN_P_BYTE_CNT"}, ++{0x40, "IN_NP_BYTE_CNT"}, ++{0x48, "IN_C_BYTE_CNT"}, ++{0x50, "OUT_P_BYTE_CNT"}, ++{0x58, "OUT_NP_BYTE_CNT"}, ++{0x60, "OUT_C_BYTE_CNT"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf_smgen_events[] = { ++{0x0, "AW_REQ"}, ++{0x1, "AW_BEATS"}, ++{0x2, "AW_TRANS"}, ++{0x3, "AW_RESP"}, ++{0x4, "AW_STL"}, ++{0x5, "AW_LAT"}, ++{0x6, "AW_REQ_TBU"}, ++{0x8, "AR_REQ"}, ++{0x9, "AR_BEATS"}, ++{0xa, "AR_TRANS"}, ++{0xb, "AR_STL"}, ++{0xc, "AR_LAT"}, ++{0xd, "AR_REQ_TBU"}, ++{0xe, "TBU_MISS"}, ++{0xf, "TX_DAT_AF"}, ++{0x10, "RX_DAT_AF"}, ++{0x11, "RETRYQ_CRED"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf1_trio_events[] = { ++{0xa0, "TPIO_DATA_BEAT"}, ++{0xa1, "TDMA_DATA_BEAT"}, ++{0xa2, "MAP_DATA_BEAT"}, ++{0xa3, "TXMSG_DATA_BEAT"}, ++{0xa4, "TPIO_DATA_PACKET"}, ++{0xa5, "TDMA_DATA_PACKET"}, ++{0xa6, "MAP_DATA_PACKET"}, ++{0xa7, "TXMSG_DATA_PACKET"}, ++{0xa8, "TDMA_RT_AF"}, ++{0xa9, "TDMA_PBUF_MAC_AF"}, ++{0xaa, "TRIO_MAP_WRQ_BUF_EMPTY"}, ++{0xab, "TRIO_MAP_CPL_BUF_EMPTY"}, ++{0xac, "TRIO_MAP_RDQ0_BUF_EMPTY"}, ++{0xad, "TRIO_MAP_RDQ1_BUF_EMPTY"}, ++{0xae, "TRIO_MAP_RDQ2_BUF_EMPTY"}, ++{0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY"}, ++{0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY"}, ++{0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY"}, ++{0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY"}, ++{0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf2_trio_events[] = { ++{0xa0, "TPIO_DATA_BEAT"}, ++{0xa1, "TDMA_DATA_BEAT"}, ++{0xa2, "MAP_DATA_BEAT"}, ++{0xa3, "TXMSG_DATA_BEAT"}, ++{0xa4, "TPIO_DATA_PACKET"}, ++{0xa5, "TDMA_DATA_PACKET"}, ++{0xa6, "MAP_DATA_PACKET"}, ++{0xa7, "TXMSG_DATA_PACKET"}, ++{0xa8, "TDMA_RT_AF"}, ++{0xa9, "TDMA_PBUF_MAC_AF"}, ++{0xaa, "TRIO_MAP_WRQ_BUF_EMPTY"}, ++{0xab, "TRIO_MAP_CPL_BUF_EMPTY"}, ++{0xac, "TRIO_MAP_RDQ0_BUF_EMPTY"}, ++{0xad, "TRIO_MAP_RDQ1_BUF_EMPTY"}, ++{0xae, "TRIO_MAP_RDQ2_BUF_EMPTY"}, ++{0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY"}, ++{0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY"}, ++{0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY"}, ++{0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY"}, ++{0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY"}, ++{0xb4, "TRIO_RING_TX_FLIT_CH0"}, ++{0xb5, "TRIO_RING_TX_FLIT_CH1"}, ++{0xb6, "TRIO_RING_TX_FLIT_CH2"}, ++{0xb7, "TRIO_RING_TX_FLIT_CH3"}, ++{0xb8, "TRIO_RING_TX_FLIT_CH4"}, ++{0xb9, "TRIO_RING_RX_FLIT_CH0"}, ++{0xba, "TRIO_RING_RX_FLIT_CH1"}, ++{0xbb, "TRIO_RING_RX_FLIT_CH2"}, ++{0xbc, "TRIO_RING_RX_FLIT_CH3"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf_ecc_events[] = { ++{0x100, "ECC_SINGLE_ERROR_CNT"}, ++{0x104, "ECC_DOUBLE_ERROR_CNT"}, ++{0x114, "SERR_INJ"}, ++{0x118, "DERR_INJ"}, ++{0x124, "ECC_SINGLE_ERROR_0"}, ++{0x164, "ECC_DOUBLE_ERROR_0"}, ++{0x340, "DRAM_ECC_COUNT"}, ++{0x344, "DRAM_ECC_INJECT"}, ++{0x348, "DRAM_ECC_ERROR",}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf_mss_events[] = { ++{0xc0, "RXREQ_MSS"}, ++{0xc1, "RXDAT_MSS"}, ++{0xc2, "TXRSP_MSS"}, ++{0xc3, "TXDAT_MSS"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf_hnf_events[] = { ++{0x45, "HNF_REQUESTS"}, ++{0x46, "HNF_REJECTS"}, ++{0x47, "ALL_BUSY"}, ++{0x48, "MAF_BUSY"}, ++{0x49, "MAF_REQUESTS"}, ++{0x4a, "RNF_REQUESTS"}, ++{0x4b, "REQUEST_TYPE"}, ++{0x4c, "MEMORY_READS"}, ++{0x4d, "MEMORY_WRITES"}, ++{0x4e, "VICTIM_WRITE"}, ++{0x4f, "POC_FULL"}, ++{0x50, "POC_FAIL"}, ++{0x51, "POC_SUCCESS"}, ++{0x52, "POC_WRITES"}, ++{0x53, "POC_READS"}, ++{0x54, "FORWARD"}, ++{0x55, "RXREQ_HNF"}, ++{0x56, "RXRSP_HNF"}, ++{0x57, "RXDAT_HNF"}, ++{0x58, "TXREQ_HNF"}, ++{0x59, "TXRSP_HNF"}, ++{0x5a, "TXDAT_HNF"}, ++{0x5b, "TXSNP_HNF"}, ++{0x5c, "INDEX_MATCH"}, ++{0x5d, "A72_ACCESS"}, ++{0x5e, "IO_ACCESS"}, ++{0x5f, "TSO_WRITE"}, ++{0x60, "TSO_CONFLICT"}, ++{0x61, "DIR_HIT"}, ++{0x62, "HNF_ACCEPTS"}, ++{0x63, "REQ_BUF_EMPTY"}, ++{0x64, "REQ_BUF_IDLE_MAF"}, ++{0x65, "TSO_NOARB"}, ++{0x66, "TSO_NOARB_CYCLES"}, ++{0x67, "MSS_NO_CREDIT"}, ++{0x68, "TXDAT_NO_LCRD"}, ++{0x69, "TXSNP_NO_LCRD"}, ++{0x6a, "TXRSP_NO_LCRD"}, ++{0x6b, "TXREQ_NO_LCRD"}, ++{0x6c, "TSO_CL_MATCH"}, ++{0x6d, "MEMORY_READS_BYPASS"}, ++{0x6e, "TSO_NOARB_TIMEOUT"}, ++{0x6f, "ALLOCATE"}, ++{0x70, "VICTIM"}, ++{0x71, "A72_WRITE"}, ++{0x72, "A72_Read"}, ++{0x73, "IO_WRITE"}, ++{0x74, "IO_READ"}, ++{0x75, "TSO_REJECT"}, ++{0x80, "TXREQ_RN"}, ++{0x81, "TXRSP_RN"}, ++{0x82, "TXDAT_RN"}, ++{0x83, "RXSNP_RN"}, ++{0x84, "RXRSP_RN"}, ++{0x85, "RXDAT_RN"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf2_hnfnet_events[] = { ++{0x12, "CDN_REQ"}, ++{0x13, "DDN_REQ"}, ++{0x14, "NDN_REQ"}, ++{0x15, "CDN_DIAG_N_OUT_OF_CRED"}, ++{0x16, "CDN_DIAG_S_OUT_OF_CRED"}, ++{0x17, "CDN_DIAG_E_OUT_OF_CRED"}, ++{0x18, "CDN_DIAG_W_OUT_OF_CRED"}, ++{0x19, "CDN_DIAG_C_OUT_OF_CRED"}, ++{0x1a, "CDN_DIAG_N_EGRESS"}, ++{0x1b, "CDN_DIAG_S_EGRESS"}, ++{0x1c, "CDN_DIAG_E_EGRESS"}, ++{0x1d, "CDN_DIAG_W_EGRESS"}, ++{0x1e, "CDN_DIAG_C_EGRESS"}, ++{0x1f, "CDN_DIAG_N_INGRESS"}, ++{0x20, "CDN_DIAG_S_INGRESS"}, ++{0x21, "CDN_DIAG_E_INGRESS"}, ++{0x22, "CDN_DIAG_W_INGRESS"}, ++{0x23, "CDN_DIAG_C_INGRESS"}, ++{0x24, "CDN_DIAG_CORE_SENT"}, ++{0x25, "DDN_DIAG_N_OUT_OF_CRED"}, ++{0x26, "DDN_DIAG_S_OUT_OF_CRED"}, ++{0x27, "DDN_DIAG_E_OUT_OF_CRED"}, ++{0x28, "DDN_DIAG_W_OUT_OF_CRED"}, ++{0x29, "DDN_DIAG_C_OUT_OF_CRED"}, ++{0x2a, "DDN_DIAG_N_EGRESS"}, ++{0x2b, "DDN_DIAG_S_EGRESS"}, ++{0x2c, "DDN_DIAG_E_EGRESS"}, ++{0x2d, "DDN_DIAG_W_EGRESS"}, ++{0x2e, "DDN_DIAG_C_EGRESS"}, ++{0x2f, "DDN_DIAG_N_INGRESS"}, ++{0x30, "DDN_DIAG_S_INGRESS"}, ++{0x31, "DDN_DIAG_E_INGRESS"}, ++{0x32, "DDN_DIAG_W_INGRESS"}, ++{0x33, "DDN_DIAG_C_INGRESS"}, ++{0x34, "DDN_DIAG_CORE_SENT"}, ++{0x35, "NDN_DIAG_S_OUT_OF_CRED"}, ++{0x36, "NDN_DIAG_S_OUT_OF_CRED"}, ++{0x37, "NDN_DIAG_E_OUT_OF_CRED"}, ++{0x38, "NDN_DIAG_W_OUT_OF_CRED"}, ++{0x39, "NDN_DIAG_C_OUT_OF_CRED"}, ++{0x3a, "NDN_DIAG_N_EGRESS"}, ++{0x3b, "NDN_DIAG_S_EGRESS"}, ++{0x3c, "NDN_DIAG_E_EGRESS"}, ++{0x3d, "NDN_DIAG_W_EGRESS"}, ++{0x3e, "NDN_DIAG_C_EGRESS"}, ++{0x3f, "NDN_DIAG_N_INGRESS"}, ++{0x40, "NDN_DIAG_S_INGRESS"}, ++{0x41, "NDN_DIAG_E_INGRESS"}, ++{0x42, "NDN_DIAG_W_INGRESS"}, ++{0x43, "NDN_DIAG_C_INGRESS"}, ++{0x44, "NDN_DIAG_CORE_SENT"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf_l3cache_events[] = { ++{0x00, "DISABLE"}, ++{0x01, "CYCLES"}, ++{0x02, "TOTAL_RD_REQ_IN"}, ++{0x03, "TOTAL_WR_REQ_IN"}, ++{0x04, "TOTAL_WR_DBID_ACK"}, ++{0x05, "TOTAL_WR_DATA_IN"}, ++{0x06, "TOTAL_WR_COMP"}, ++{0x07, "TOTAL_RD_DATA_OUT"}, ++{0x08, "TOTAL_CDN_REQ_IN_BANK0"}, ++{0x09, "TOTAL_CDN_REQ_IN_BANK1"}, ++{0x0a, "TOTAL_DDN_REQ_IN_BANK0"}, ++{0x0b, "TOTAL_DDN_REQ_IN_BANK1"}, ++{0x0c, "TOTAL_EMEM_RD_RES_IN_BANK0"}, ++{0x0d, "TOTAL_EMEM_RD_RES_IN_BANK1"}, ++{0x0e, "TOTAL_CACHE_RD_RES_IN_BANK0"}, ++{0x0f, "TOTAL_CACHE_RD_RES_IN_BANK1"}, ++{0x10, "TOTAL_EMEM_RD_REQ_BANK0"}, ++{0x11, "TOTAL_EMEM_RD_REQ_BANK1"}, ++{0x12, "TOTAL_EMEM_WR_REQ_BANK0"}, ++{0x13, "TOTAL_EMEM_WR_REQ_BANK1"}, ++{0x14, "TOTAL_RD_REQ_OUT"}, ++{0x15, "TOTAL_WR_REQ_OUT"}, ++{0x16, "TOTAL_RD_RES_IN"}, ++{0x17, "HITS_BANK0"}, ++{0x18, "HITS_BANK1"}, ++{0x19, "MISSES_BANK0"}, ++{0x1a, "MISSES_BANK1"}, ++{0x1b, "ALLOCATIONS_BANK0"}, ++{0x1c, "ALLOCATIONS_BANK1"}, ++{0x1d, "EVICTIONS_BANK0"}, ++{0x1e, "EVICTIONS_BANK1"}, ++{0x1f, "DBID_REJECT"}, ++{0x20, "WRDB_REJECT_BANK0"}, ++{0x21, "WRDB_REJECT_BANK1"}, ++{0x22, "CMDQ_REJECT_BANK0"}, ++{0x23, "CMDQ_REJECT_BANK1"}, ++{0x24, "COB_REJECT_BANK0"}, ++{0x25, "COB_REJECT_BANK1"}, ++{0x26, "TRB_REJECT_BANK0"}, ++{0x27, "TRB_REJECT_BANK1"}, ++{0x28, "TAG_REJECT_BANK0"}, ++{0x29, "TAG_REJECT_BANK1"}, ++{0x2a, "ANY_REJECT_BANK0"}, ++{0x2b, "ANY_REJECT_BANK1"}, ++{-1, NULL} ++}; ++ ++#endif /* __MLXBF_PMC_H__ */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0216-UBUNTU-SAUCE-mlxbf_pmc-Fix-references-to-sprintf.patch b/platform/mellanox/non-upstream-patches/patches/0216-UBUNTU-SAUCE-mlxbf_pmc-Fix-references-to-sprintf.patch new file mode 100644 index 0000000000..8aa9cf2917 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0216-UBUNTU-SAUCE-mlxbf_pmc-Fix-references-to-sprintf.patch @@ -0,0 +1,69 @@ +From 597a665f88fd16c595dd804c7567ccd5aab34ad9 Mon Sep 17 00:00:00 2001 +From: Jitendra Lanka +Date: Tue, 16 Aug 2022 16:18:39 -0400 +Subject: [PATCH backport 5.10 17/63] UBUNTU: SAUCE: mlxbf_pmc: Fix references + to sprintf + +BugLink: https://bugs.launchpad.net/bugs/1986849 + +Replace sprintf with snprintf with a defined upper boundary of +PAGE_SIZE for sysfs store/show functions and max array size defined +otherwise. + +Change-Id: If586302684d60a435abc9f5aaf28b08de9b2df16 +Signed-off-by: Jitendra Lanka +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/mlxbf-pmc.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index a9debcdf9..3305d2a5d 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -681,7 +681,7 @@ static ssize_t mlxbf_counter_read(struct kobject *ko, + } else + return -EINVAL; + +- return sprintf(buf, "0x%llx\n", value); ++ return snprintf(buf, PAGE_SIZE, "0x%llx\n", value); + } + + /* Store function for "counter" sysfs files */ +@@ -758,7 +758,7 @@ static ssize_t mlxbf_event_find(struct kobject *ko, + + evt_name = mlxbf_pmc_get_event_name((char *)ko->name, evt_num); + +- return sprintf(buf, "0x%llx: %s\n", evt_num, evt_name); ++ return snprintf(buf, PAGE_SIZE, "0x%llx: %s\n", evt_num, evt_name); + } + + /* Store function for "event" sysfs files */ +@@ -811,9 +811,12 @@ static ssize_t mlxbf_print_event_list(struct kobject *ko, + + buf[0] = '\0'; + while (events[i].evt_name != NULL) { +- size += sprintf(e_info, "%x: %s\n", events[i].evt_num, +- events[i].evt_name); +- if (size > PAGE_SIZE) ++ size += snprintf(e_info, ++ sizeof(e_info), ++ "%x: %s\n", ++ events[i].evt_num, ++ events[i].evt_name); ++ if (size >= PAGE_SIZE) + break; + strcat(buf, e_info); + ret = size; +@@ -840,7 +843,7 @@ static ssize_t mlxbf_show_counter_state(struct kobject *ko, + + value = FIELD_GET(MLXBF_L3C_PERF_CNT_CFG__EN, perfcnt_cfg); + +- return sprintf(buf, "%d\n", value); ++ return snprintf(buf, PAGE_SIZE, "%d\n", value); + } + + /* Store function for "enable" sysfs files - only for l3cache */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0217-UBUNTU-SAUCE-mlxbf-pmc-Fix-error-when-reading-unprog.patch b/platform/mellanox/non-upstream-patches/patches/0217-UBUNTU-SAUCE-mlxbf-pmc-Fix-error-when-reading-unprog.patch new file mode 100644 index 0000000000..3607501b54 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0217-UBUNTU-SAUCE-mlxbf-pmc-Fix-error-when-reading-unprog.patch @@ -0,0 +1,140 @@ +From f88fbeabee18fbd15de2e717fe45d9bf2c287468 Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Fri, 9 Sep 2022 05:31:43 -0400 +Subject: [PATCH backport 5.10 18/63] UBUNTU: SAUCE: mlxbf-pmc: Fix error when + reading unprogrammed events + +BugLink: https://bugs.launchpad.net/bugs/1989172 + +Firstly, all events have a reset value of 0, which is not a valid +event as per the event_list for most blocks and hence seen as an +error. Add a "disable" event with event_number 0 for all blocks. +Second, the enable bit for each counter need not be checked before +reading the event info, and hence removed. + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/mlxbf-pmc.c | 32 +++++---------------------- + drivers/platform/mellanox/mlxbf-pmc.h | 6 +++++ + 2 files changed, 12 insertions(+), 26 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 3305d2a5d..106acea8c 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -19,7 +19,7 @@ + + #include "mlxbf-pmc.h" + +-#define DRIVER_VERSION 2.2 ++#define DRIVER_VERSION 2.3 + + static struct mlxbf_pmc_context *pmc; + +@@ -562,7 +562,7 @@ int mlxbf_read_event(int blk_num, uint32_t cnt_num, bool is_l3, + uint64_t *result) + { + uint32_t perfcfg_offset, perfval_offset; +- uint64_t perfmon_cfg, perfevt, perfctl; ++ uint64_t perfmon_cfg, perfevt; + + if (cnt_num >= pmc->block[blk_num].counters) + return -EINVAL; +@@ -573,26 +573,6 @@ int mlxbf_read_event(int blk_num, uint32_t cnt_num, bool is_l3, + perfcfg_offset = cnt_num * 8; + perfval_offset = perfcfg_offset + pmc->block[blk_num].counters * 8; + +- /* Set counter in "read" mode */ +- perfmon_cfg = 0; +- perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, +- MLXBF_PERFCTL); +- perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__STROBE, 1); +- perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__WR_R_B, 0); +- +- if (mlxbf_pmc_writeq(perfmon_cfg, +- pmc->block[blk_num].mmio_base + perfcfg_offset)) +- return -EFAULT; +- +- /* Check if the counter is enabled */ +- +- if (mlxbf_pmc_readq(&perfctl, +- pmc->block[blk_num].mmio_base + perfval_offset)) +- return -EFAULT; +- +- if (FIELD_GET(MLXBF_GEN_PERFCTL__EN0, perfctl) == 0) +- return -EINVAL; +- + /* Set counter in "read" mode */ + perfmon_cfg = 0; + perfmon_cfg |= FIELD_PREP(MLXBF_GEN_PERFMON_CONFIG__ADDR, +@@ -812,10 +792,10 @@ static ssize_t mlxbf_print_event_list(struct kobject *ko, + buf[0] = '\0'; + while (events[i].evt_name != NULL) { + size += snprintf(e_info, +- sizeof(e_info), +- "%x: %s\n", +- events[i].evt_num, +- events[i].evt_name); ++ sizeof(e_info), ++ "%x: %s\n", ++ events[i].evt_num, ++ events[i].evt_name); + if (size >= PAGE_SIZE) + break; + strcat(buf, e_info); +diff --git a/drivers/platform/mellanox/mlxbf-pmc.h b/drivers/platform/mellanox/mlxbf-pmc.h +index b15614e90..894c3cc88 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.h ++++ b/drivers/platform/mellanox/mlxbf-pmc.h +@@ -186,6 +186,7 @@ struct mlxbf_pmc_events mlxbf_smgen_events[] = { + }; + + struct mlxbf_pmc_events mlxbf1_trio_events[] = { ++{0x00, "DISABLE"}, + {0xa0, "TPIO_DATA_BEAT"}, + {0xa1, "TDMA_DATA_BEAT"}, + {0xa2, "MAP_DATA_BEAT"}, +@@ -210,6 +211,7 @@ struct mlxbf_pmc_events mlxbf1_trio_events[] = { + }; + + struct mlxbf_pmc_events mlxbf2_trio_events[] = { ++{0x00, "DISABLE"}, + {0xa0, "TPIO_DATA_BEAT"}, + {0xa1, "TDMA_DATA_BEAT"}, + {0xa2, "MAP_DATA_BEAT"}, +@@ -243,6 +245,7 @@ struct mlxbf_pmc_events mlxbf2_trio_events[] = { + }; + + struct mlxbf_pmc_events mlxbf_ecc_events[] = { ++{0x00, "DISABLE"}, + {0x100, "ECC_SINGLE_ERROR_CNT"}, + {0x104, "ECC_DOUBLE_ERROR_CNT"}, + {0x114, "SERR_INJ"}, +@@ -256,6 +259,7 @@ struct mlxbf_pmc_events mlxbf_ecc_events[] = { + }; + + struct mlxbf_pmc_events mlxbf_mss_events[] = { ++{0x00, "DISABLE"}, + {0xc0, "RXREQ_MSS"}, + {0xc1, "RXDAT_MSS"}, + {0xc2, "TXRSP_MSS"}, +@@ -264,6 +268,7 @@ struct mlxbf_pmc_events mlxbf_mss_events[] = { + }; + + struct mlxbf_pmc_events mlxbf_hnf_events[] = { ++{0x00, "DISABLE"}, + {0x45, "HNF_REQUESTS"}, + {0x46, "HNF_REJECTS"}, + {0x47, "ALL_BUSY"}, +@@ -323,6 +328,7 @@ struct mlxbf_pmc_events mlxbf_hnf_events[] = { + }; + + struct mlxbf_pmc_events mlxbf2_hnfnet_events[] = { ++{0x00, "DISABLE"}, + {0x12, "CDN_REQ"}, + {0x13, "DDN_REQ"}, + {0x14, "NDN_REQ"}, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0218-UBUNTU-SAUCE-platform-mellanox-Add-mlx-trio-driver.patch b/platform/mellanox/non-upstream-patches/patches/0218-UBUNTU-SAUCE-platform-mellanox-Add-mlx-trio-driver.patch new file mode 100644 index 0000000000..104c33198c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0218-UBUNTU-SAUCE-platform-mellanox-Add-mlx-trio-driver.patch @@ -0,0 +1,955 @@ +From 15bbb9ee03e015587b9bd704f36c85177fba563a Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Tue, 5 Jul 2022 11:11:45 -0400 +Subject: [PATCH backport 5.10 19/63] UBUNTU: SAUCE: platform/mellanox: Add + mlx-trio driver + +BugLink: https://bugs.launchpad.net/bugs/1980754 + +The mlx-trio driver allows users to configure the TRIO PCIe root +complex of Mellanox BlueField SoCs to select an L3 cache profile. +It also handles TRIO IRQs and prints debug info. + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/Kconfig | 7 + + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/mellanox/mlx-trio.c | 651 ++++++++++++++++++++++++++ + drivers/platform/mellanox/trio_regs.h | 236 ++++++++++ + 4 files changed, 895 insertions(+) + create mode 100644 drivers/platform/mellanox/mlx-trio.c + create mode 100644 drivers/platform/mellanox/trio_regs.h + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index b0d2c3343..5d329350a 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -90,6 +90,13 @@ config MLXBF_PMC + to performance monitoring counters within various blocks in the + Mellanox BlueField SoC via a sysfs interface. + ++config MLXBF_TRIO ++ tristate "Mellanox TRIO driver" ++ depends on ARM64 ++ help ++ This driver supports the TRIO PCIe root complex interface on ++ Mellanox BlueField SoCs. ++ + config NVSW_SN2201 + tristate "Nvidia SN2201 platform driver support" + depends on REGMAP +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index ba56485cb..161fad566 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o + obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o + obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o + obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o ++obj-$(CONFIG_MLXBF_TRIO) += mlx-trio.o + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o + obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o +diff --git a/drivers/platform/mellanox/mlx-trio.c b/drivers/platform/mellanox/mlx-trio.c +new file mode 100644 +index 000000000..849006e9c +--- /dev/null ++++ b/drivers/platform/mellanox/mlx-trio.c +@@ -0,0 +1,651 @@ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause ++/* ++ * TRIO driver for Mellanox BlueField SoC ++ * ++ * Copyright (c) 2018, Mellanox Technologies. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "trio_regs.h" ++ ++#define DRIVER_NAME "mlx-trio" ++#define DRIVER_VERSION "0.4" ++#define DRIVER_DESCRIPTION "Mellanox TRIO PCIe host controller driver" ++ ++/* SMC return codes */ ++#define SMCCC_ACCESS_VIOLATION (-4) ++ ++/* SMC function identifiers */ ++#define MLNX_WRITE_REG_64 (0x8200000B) ++#define MLNX_READ_REG_64 (0x8200000C) ++#define MLNX_SIP_SVC_UID (0x8200ff01) ++#define MLNX_SIP_SVC_VERSION (0x8200ff03) ++ ++#define MLNX_TRIO_SVC_REQ_MAJOR 0 ++#define MLNX_TRIO_SVC_MIN_MINOR 4 ++ ++#define TRIO_NUM_IRQS 17 ++#define L3_PROFILE_NUM (L3C_PROF_RD_MISS__LENGTH / L3C_PROF_RD_MISS__STRIDE) ++ ++/* The PUSH_DMA_EVT_CTR wrapped. */ ++#define TRIO_PUSH_DMA_EVT_CTR_INT_BIT 10 ++ ++/* The MAP_EVT_CTR wrapped. */ ++#define TRIO_MAP_EVT_CTR_INT_BIT 11 ++ ++enum trio_int_events { ++ TRIO_MAC_INT = 0, ++ TRIO_RSH_FULL_ERR_INT, ++ TRIO_MSG_Q_FULL_ERR_INT, ++ TRIO_MSG_Q_ARRIVED_INT, ++ TRIO_MMIO_ERR_INT, ++ TRIO_MAP_UNCLAIMED_INT, ++ TRIO_RSH_SIZE_ERR_INT, ++ TRIO_PIO_ECAM_ERR_INT, ++ TRIO_PIO_CPL_ERR_INT, ++ TRIO_MMIO_PROT_ERR_INT, ++ TRIO_PUSH_DMA_EVT_CTR_INT, ++ TRIO_MAP_EVT_CTR_INT, ++ TRIO_PIO_DISABLED_INT, ++ TRIO_REM_MMIO_ERR_INT, ++ TRIO_ERR_MSG_COR_INT, ++ TRIO_ERR_MSG_NONFATAL_INT, ++ TRIO_ERR_MSG_FATAL_INT, ++}; ++ ++struct trio_event_info { ++ const char *name; ++ int additional_info; ++}; ++ ++static const struct trio_event_info trio_events[TRIO_NUM_IRQS] = { ++ [TRIO_MAC_INT] = { ++ .name = "MAC Interrupt", ++ .additional_info = -1, ++ }, ++ [TRIO_RSH_FULL_ERR_INT] = { ++ .name = "RShim Full Error", ++ .additional_info = -1, ++ }, ++ [TRIO_MSG_Q_FULL_ERR_INT] = { ++ .name = "Msg Queue Full Error", ++ .additional_info = -1, ++ }, ++ [TRIO_MSG_Q_ARRIVED_INT] = { ++ .name = "Msg Arrived Interrupt", ++ .additional_info = -1, ++ }, ++ [TRIO_MMIO_ERR_INT] = { ++ .name = "MMIO Error", ++ .additional_info = TRIO_MMIO_ERROR_INFO, ++ }, ++ [TRIO_MAP_UNCLAIMED_INT] = { ++ .name = "Packet Unclaimed Error", ++ .additional_info = TRIO_MAP_ERR_STS, ++ }, ++ [TRIO_RSH_SIZE_ERR_INT] = { ++ .name = "RShim Size Error", ++ .additional_info = -1, ++ }, ++ [TRIO_PIO_ECAM_ERR_INT] = { ++ .name = "PIO ECAM Error", ++ .additional_info = -1, ++ }, ++ [TRIO_PIO_CPL_ERR_INT] = { ++ .name = "PIO Completion Error", ++ .additional_info = TRIO_TILE_PIO_CPL_ERR_STS, ++ }, ++ [TRIO_MMIO_PROT_ERR_INT] = { ++ .name = "MMIO Protection level Violation", ++ .additional_info = -1, ++ }, ++ [TRIO_PUSH_DMA_EVT_CTR_INT] = { ++ .name = "PUSH_DMA_CTR wrapped", ++ .additional_info = -1, ++ }, ++ [TRIO_MAP_EVT_CTR_INT] = { ++ .name = "MAP_EVT_CTR wrapped", ++ .additional_info = -1, ++ }, ++ [TRIO_PIO_DISABLED_INT] = { ++ .name = "Access to disabled PIO region", ++ .additional_info = -1, ++ }, ++ [TRIO_REM_MMIO_ERR_INT] = { ++ .name = "Remote Buffer MMIO Error", ++ .additional_info = -1, ++ }, ++ [TRIO_ERR_MSG_COR_INT] = { ++ .name = "Correctable error message received", ++ .additional_info = -1, ++ }, ++ [TRIO_ERR_MSG_NONFATAL_INT] = { ++ .name = "Nonfatal error message received", ++ .additional_info = -1, ++ }, ++ [TRIO_ERR_MSG_FATAL_INT] = { ++ .name = "Fatal error message received", ++ .additional_info = -1, ++ }, ++}; ++ ++enum l3_profile_type { ++ LRU_PROFILE = 0, /* 0 is the default behavior. */ ++ NVME_PROFILE, ++ L3_PROFILE_TYPE_NUM, ++}; ++ ++static const char *l3_profiles[L3_PROFILE_TYPE_NUM] = { ++ [LRU_PROFILE] = "Strict_LRU", ++ [NVME_PROFILE] = "NVMeOF_suitable" ++}; ++ ++/* ++ * The default profile each L3 profile would get. ++ * The current setting would make profile 1 the NVMe suitable profile ++ * and the rest of the profiles LRU profile. ++ * Note that profile 0 should be configured as LRU as this is the ++ * default profile. ++ */ ++static const enum l3_profile_type default_profile[L3_PROFILE_NUM] = { ++ [1] = NVME_PROFILE, ++}; ++ ++struct event_context { ++ int event_num; ++ int irq; ++ struct trio_context *trio; ++}; ++ ++struct trio_context { ++ /* The kernel structure representing the device. */ ++ struct platform_device *pdev; ++ ++ /* Argument to be passed back to the IRQ handler */ ++ struct event_context *events; ++ ++ /* ++ * Reg base addr, will be memmapped if sreg_use_smcs is false. ++ * Otherwise, this is a physical address. ++ */ ++ void __iomem *mmio_base; ++ ++ int trio_index; ++ ++ /* Name of the bus this TRIO corresponds to */ ++ const char *bus; ++ ++ /* The PCI device this TRIO corresponds to */ ++ struct pci_dev *trio_pci; ++ ++ /* Number of platform_irqs for this device */ ++ uint32_t num_irqs; ++ ++ /* Access regs with smcs if true */ ++ bool sreg_use_smcs; ++ ++ /* verification table for trio */ ++ uint32_t sreg_trio_tbl; ++}; ++ ++static int secure_writeq(struct trio_context *trio, uint64_t value, ++ void __iomem *addr) ++{ ++ struct arm_smccc_res res; ++ int status; ++ ++ arm_smccc_smc(MLNX_WRITE_REG_64, trio->sreg_trio_tbl, value, ++ (uintptr_t) addr, 0, 0, 0, 0, &res); ++ ++ status = res.a0; ++ ++ switch (status) { ++ /* ++ * Note: PSCI_RET_NOT_SUPPORTED is used here to maintain compatibility ++ * with older kernels that do not have SMCCC_RET_NOT_SUPPORTED ++ */ ++ case PSCI_RET_NOT_SUPPORTED: ++ dev_err(&trio->pdev->dev, ++ "%s: required SMC unsupported\n", ++ __func__); ++ return -1; ++ case SMCCC_ACCESS_VIOLATION: ++ dev_err(&trio->pdev->dev, ++ "%s: could not access register at %px\n", ++ __func__, ++ addr); ++ return -1; ++ default: ++ return 0; ++ } ++} ++ ++static int trio_writeq(struct trio_context *trio, uint64_t value, ++ void __iomem *addr) ++{ ++ if (trio->sreg_use_smcs) ++ return secure_writeq(trio, value, addr); ++ else { ++ writeq(value, addr); ++ return 0; ++ } ++} ++ ++static int secure_readq(struct trio_context *trio, void __iomem *addr, ++ uint64_t *result) ++{ ++ struct arm_smccc_res res; ++ int status; ++ ++ arm_smccc_smc(MLNX_READ_REG_64, trio->sreg_trio_tbl, (uintptr_t) addr, ++ 0, 0, 0, 0, 0, &res); ++ ++ status = res.a0; ++ ++ switch (status) { ++ /* ++ * Note: PSCI_RET_NOT_SUPPORTED is used here to maintain compatibility ++ * with older kernels that do not have SMCCC_RET_NOT_SUPPORTED ++ */ ++ case PSCI_RET_NOT_SUPPORTED: ++ dev_err(&trio->pdev->dev, ++ "%s: required SMC unsupported\n", __func__); ++ return -1; ++ case SMCCC_ACCESS_VIOLATION: ++ dev_err(&trio->pdev->dev, ++ "%s: could not read register %px\n", ++ __func__, ++ addr); ++ return -1; ++ default: ++ *result = (uint64_t)res.a1; ++ return 0; ++ } ++} ++ ++static int trio_readq(struct trio_context *trio, void __iomem *addr, ++ uint64_t *result) ++{ ++ if (trio->sreg_use_smcs) ++ return secure_readq(trio, addr, result); ++ else { ++ *result = readq(addr); ++ return 0; ++ } ++} ++ ++static irqreturn_t trio_irq_handler(int irq, void *arg) ++{ ++ struct event_context *ctx = (struct event_context *)arg; ++ struct trio_context *trio = ctx->trio; ++ ++ pr_debug("mlx_trio: TRIO %d received IRQ %d event %d (%s)\n", ++ trio->trio_index, irq, ctx->event_num, ++ trio_events[ctx->event_num].name); ++ ++ if (trio_events[ctx->event_num].additional_info != -1) { ++ uint64_t info; ++ trio_readq(trio, trio->mmio_base + ++ trio_events[ctx->event_num].additional_info, ++ &info); ++ pr_debug("mlx_trio: Addition IRQ info: %llx\n", info); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static ssize_t current_profile_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int profile_num; ++ struct trio_context *trio; ++ struct platform_device *pdev; ++ ++ TRIO_DEV_CTL_t tdc; ++ ++ pdev = to_platform_device(dev); ++ trio = platform_get_drvdata(pdev); ++ ++ if (trio_readq(trio, trio->mmio_base + TRIO_DEV_CTL, &tdc.word)) { ++ return -EIO; ++ } ++ ++ if (tdc.l3_profile_ovd == 0) ++ profile_num = -1; ++ else ++ profile_num = tdc.l3_profile_val; ++ ++ return sprintf(buf, "%d\n", profile_num); ++} ++ ++static int set_l3cache_profile(struct trio_context *trio, long profile_num) ++{ ++ TRIO_DEV_CTL_t tdc; ++ ++ if (trio_readq(trio, trio->mmio_base + TRIO_DEV_CTL, &tdc.word)) { ++ return -EIO; ++ } ++ ++ if (profile_num == -1) { ++ dev_info(&trio->pdev->dev, "Unlink %s profile\n", trio->bus); ++ ++ tdc.l3_profile_ovd = 0; ++ } else if (profile_num < L3_PROFILE_NUM && profile_num >= 0) { ++ dev_info(&trio->pdev->dev, "Change %s to profile %ld\n", ++ trio->bus, profile_num); ++ ++ tdc.l3_profile_ovd = 1; ++ tdc.l3_profile_val = profile_num; ++ } else { ++ dev_err(&trio->pdev->dev, "Profile number out of range."); ++ return -EINVAL; ++ } ++ ++ if (trio_writeq(trio, tdc.word, trio->mmio_base + TRIO_DEV_CTL)) { ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static ssize_t current_profile_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err; ++ long profile_num; ++ struct trio_context *trio; ++ struct platform_device *pdev; ++ ++ pdev = container_of(dev, struct platform_device, dev); ++ trio = platform_get_drvdata(pdev); ++ ++ err = kstrtol(buf, 10, &profile_num); ++ if (err) ++ return err; ++ ++ err = set_l3cache_profile(trio, profile_num); ++ if (err) ++ return err; ++ ++ return count; ++} ++ ++static DEVICE_ATTR_RW(current_profile); ++ ++static ssize_t available_profiles_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int i; ++ ssize_t line_size; ++ ssize_t len = 0; ++ ++ for (i = 0; i < L3_PROFILE_NUM; i++) { ++ line_size = sprintf(buf, "%d %s\n", i, ++ l3_profiles[default_profile[i]]); ++ buf += line_size; ++ len += line_size; ++ } ++ return len; ++} ++ ++static DEVICE_ATTR_RO(available_profiles); ++ ++static int trio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct trio_context *trio; ++ int i, j, ret, irq; ++ int trio_bus, trio_device, trio_function; ++ struct resource *res; ++ struct arm_smccc_res smc_res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_warn(dev, "%s: failed to find reg resource 0\n", __func__); ++ return -ENODEV; ++ } ++ ++ trio = kzalloc(sizeof(struct trio_context), GFP_KERNEL); ++ if (!trio) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, trio); ++ trio->pdev = pdev; ++ ++ /* Determine whether to use SMCs or not. */ ++ if (device_property_read_u32(&pdev->dev, "sec_reg_block", ++ &trio->sreg_trio_tbl)) { ++ trio->sreg_use_smcs = false; ++ } else { ++ /* ++ * Ensure we have the UUID we expect for the Mellanox service. ++ */ ++ arm_smccc_smc(MLNX_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &smc_res); ++ if (smc_res.a0 != 0x89c036b4 || smc_res.a1 != 0x11e6e7d7 || ++ smc_res.a2 != 0x1a009787 || smc_res.a3 != 0xc4bf00ca) { ++ dev_err(&pdev->dev, ++ "Mellanox SMC service not available\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * Check service version to see if we actually do support the ++ * needed SMCs. If we have the calls we need, mark support for ++ * them in the trio struct. ++ */ ++ arm_smccc_smc(MLNX_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, ++ &smc_res); ++ if (smc_res.a0 == MLNX_TRIO_SVC_REQ_MAJOR && ++ smc_res.a1 >= MLNX_TRIO_SVC_MIN_MINOR) { ++ trio->sreg_use_smcs = true; ++ } else { ++ dev_err(&pdev->dev, ++ "Required SMCs are not supported.\n"); ++ ++ return -EINVAL; ++ } ++ } ++ ++ if (device_property_read_string(dev, "bus_number", &trio->bus)) { ++ dev_warn(dev, "%s: failed to retrieve Trio bus name\n", ++ __func__); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (device_property_read_u32(dev, "num_irqs", &trio->num_irqs)) ++ trio->num_irqs = TRIO_NUM_IRQS; ++ trio->events = kzalloc(sizeof(struct event_context) * trio->num_irqs, ++ GFP_KERNEL); ++ if (!trio->events) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ /* Map registers */ ++ if (!trio->sreg_use_smcs) { ++ trio->mmio_base = devm_ioremap_resource(&pdev->dev, res); ++ ++ if (IS_ERR(trio->mmio_base)) { ++ dev_warn(dev, "%s: ioremap failed for mmio_base %llx err %p\n", ++ __func__, res->start, trio->mmio_base); ++ ret = PTR_ERR(trio->mmio_base); ++ goto err; ++ } ++ } else ++ trio->mmio_base = (void __iomem *) res->start; ++ ++ for (i = 0; i < trio->num_irqs; ++i) { ++ struct event_context *ctx = &trio->events[i]; ++ int dri_ret; ++ ++ switch (i) { ++ case TRIO_PUSH_DMA_EVT_CTR_INT_BIT: ++ case TRIO_MAP_EVT_CTR_INT_BIT: ++ /* ++ * These events are not errors, they just indicate ++ * that a performance counter wrapped. We may want ++ * the performance counter driver to register for them. ++ */ ++ continue; ++ default: ++ break; ++ } ++ ++ irq = platform_get_irq(pdev, i); ++ if (irq < 0) { ++ dev_warn(dev, "%s: failed to get plat irq %d ret %d\n", ++ __func__, i, irq); ++ for (j = i - 1; j >= 0; j--) { ++ ctx = &trio->events[j]; ++ devm_free_irq(&pdev->dev, ctx->irq, ctx); ++ } ++ ret = -ENXIO; ++ goto err; ++ } ++ ctx->event_num = i; ++ ctx->trio = trio; ++ ctx->irq = irq; ++ dri_ret = devm_request_irq(&pdev->dev, irq, trio_irq_handler, 0, ++ dev_name(dev), ctx); ++ ++ dev_dbg(dev, "%s: request_irq returns %d %d->%d\n", __func__, ++ dri_ret, i, irq); ++ } ++ ++ /* Create the L3 cache profile on this device */ ++ device_create_file(dev, &dev_attr_current_profile); ++ device_create_file(dev, &dev_attr_available_profiles); ++ ++ /* ++ * Get the corresponding PCI device this trio maps to. ++ * If the bus number can't be read properly, no symlinks are created. ++ */ ++ if (sscanf(trio->bus, "%d:%d.%d", &trio_bus, &trio_device, ++ &trio_function) != 3) { ++ dev_warn(dev, "Device [%s] not valid\n", trio->bus); ++ return 0; ++ } ++ ++ /* trio_device is also the index of the TRIO */ ++ trio->trio_index = trio_device; ++ ++ /* The PCI domain/segment would always be 0 here. */ ++ trio->trio_pci = ++ pci_get_domain_bus_and_slot(0, trio_bus, ++ (trio_device << 3) + trio_function); ++ ++ /* Add the symlink from the TRIO to the PCI device */ ++ if (trio->trio_pci != NULL) { ++ if (sysfs_create_link(&dev->kobj, &trio->trio_pci->dev.kobj, ++ "pcie_slot")) { ++ pci_dev_put(trio->trio_pci); ++ trio->trio_pci = NULL; ++ dev_warn(dev, "Failed to create symblink for %s\n", ++ trio->bus); ++ } ++ } else ++ dev_warn(dev, "Device %s not found\n", trio->bus); ++ ++ dev_info(dev, "v" DRIVER_VERSION " probed\n"); ++ return 0; ++err: ++ dev_warn(dev, "Error probing trio\n"); ++ if (trio->events) ++ kfree(trio->events); ++ kfree(trio); ++ platform_set_drvdata(pdev, NULL); ++ return ret; ++} ++ ++static int trio_remove(struct platform_device *pdev) ++{ ++ struct trio_context *trio = platform_get_drvdata(pdev); ++ struct device *dev = &pdev->dev; ++ int i; ++ ++ for (i = 0; i < trio->num_irqs; ++i) { ++ struct event_context *ctx = &trio->events[i]; ++ ++ if (ctx->irq) ++ devm_free_irq(&pdev->dev, ctx->irq, ctx); ++ } ++ device_remove_file(dev, &dev_attr_current_profile); ++ device_remove_file(dev, &dev_attr_available_profiles); ++ ++ /* Delete the symlink and decrement the reference count. */ ++ if (trio->trio_pci != NULL) { ++ sysfs_remove_link(&dev->kobj, "pcie_slot"); ++ pci_dev_put(trio->trio_pci); ++ } ++ platform_set_drvdata(pdev, NULL); ++ kfree(trio->events); ++ kfree(trio); ++ ++ return 0; ++} ++ ++static const struct acpi_device_id trio_acpi_ids[] = { ++ {"MLNXBF06", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(acpi, trio_acpi_ids); ++static struct platform_driver mlx_trio_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .acpi_match_table = ACPI_PTR(trio_acpi_ids), ++ }, ++ .probe = trio_probe, ++ .remove = trio_remove, ++}; ++ ++static int __init trio_init(void) ++{ ++ int ret; ++ ++ ret = platform_driver_register(&mlx_trio_driver); ++ if (ret) ++ pr_err("Failed to register trio driver.\n"); ++ ++ return ret; ++} ++ ++static void __exit trio_exit(void) ++{ ++ platform_driver_unregister(&mlx_trio_driver); ++} ++ ++module_init(trio_init); ++module_exit(trio_exit); ++ ++MODULE_DESCRIPTION(DRIVER_DESCRIPTION); ++MODULE_AUTHOR("Shravan Kumar Ramani "); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/platform/mellanox/trio_regs.h b/drivers/platform/mellanox/trio_regs.h +new file mode 100644 +index 000000000..cc2f2003d +--- /dev/null ++++ b/drivers/platform/mellanox/trio_regs.h +@@ -0,0 +1,236 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2019, Mellanox Technologies. All rights reserved. ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __TRIO_REGS_H__ ++#define __TRIO_REGS_H__ ++ ++#ifdef __ASSEMBLER__ ++#define _64bit(x) x ++#else /* __ASSEMBLER__ */ ++#define _64bit(x) x ## ULL ++#endif /* __ASSEMBLER */ ++ ++#include ++ ++#define L3C_PROF_RD_MISS__FIRST_WORD 0x0600 ++#define L3C_PROF_RD_MISS__LAST_WORD 0x063c ++#define L3C_PROF_RD_MISS__LENGTH 0x0040 ++#define L3C_PROF_RD_MISS__STRIDE 0x0004 ++ ++#define L3C_PROF_RD_MISS__LOW_ORDER_SHIFT 0 ++#define L3C_PROF_RD_MISS__LOW_ORDER_WIDTH 5 ++#define L3C_PROF_RD_MISS__LOW_ORDER_RESET_VAL 11 ++#define L3C_PROF_RD_MISS__LOW_ORDER_RMASK 0x1f ++#define L3C_PROF_RD_MISS__LOW_ORDER_MASK 0x1f ++ ++#define L3C_PROF_RD_MISS__HIGH_ORDER_SHIFT 5 ++#define L3C_PROF_RD_MISS__HIGH_ORDER_WIDTH 5 ++#define L3C_PROF_RD_MISS__HIGH_ORDER_RESET_VAL 0 ++#define L3C_PROF_RD_MISS__HIGH_ORDER_RMASK 0x1f ++#define L3C_PROF_RD_MISS__HIGH_ORDER_MASK 0x3e0 ++ ++#define L3C_PROF_RD_MISS__ALLOC_STATE_SHIFT 12 ++#define L3C_PROF_RD_MISS__ALLOC_STATE_WIDTH 1 ++#define L3C_PROF_RD_MISS__ALLOC_STATE_RESET_VAL 0 ++#define L3C_PROF_RD_MISS__ALLOC_STATE_RMASK 0x1 ++#define L3C_PROF_RD_MISS__ALLOC_STATE_MASK 0x1000 ++ ++#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_SHIFT 13 ++#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_WIDTH 1 ++#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_RESET_VAL 0 ++#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_RMASK 0x1 ++#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_MASK 0x2000 ++ ++#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_SHIFT 14 ++#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_WIDTH 1 ++#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_RESET_VAL 0 ++#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_RMASK 0x1 ++#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_MASK 0x4000 ++ ++#define L3C_PROF_RD_MISS__PROB_SHIFT 16 ++#define L3C_PROF_RD_MISS__PROB_WIDTH 16 ++#define L3C_PROF_RD_MISS__PROB_RESET_VAL 0 ++#define L3C_PROF_RD_MISS__PROB_RMASK 0xffff ++#define L3C_PROF_RD_MISS__PROB_MASK 0xffff0000 ++ ++#define TRIO_DEV_CTL 0x0008 ++#define TRIO_DEV_CTL__LENGTH 0x0001 ++ ++#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_SHIFT 0 ++#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_WIDTH 1 ++#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_RESET_VAL 0 ++#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_RMASK 0x1 ++#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_MASK 0x1 ++ ++#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_SHIFT 1 ++#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_WIDTH 1 ++#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_RESET_VAL 1 ++#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_RMASK 0x1 ++#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_MASK 0x2 ++ ++#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_SHIFT 2 ++#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_WIDTH 1 ++#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_RESET_VAL 1 ++#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_RMASK 0x1 ++#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_MASK 0x4 ++ ++#define TRIO_DEV_CTL__DMA_RD_CA_ENA_SHIFT 3 ++#define TRIO_DEV_CTL__DMA_RD_CA_ENA_WIDTH 1 ++#define TRIO_DEV_CTL__DMA_RD_CA_ENA_RESET_VAL 1 ++#define TRIO_DEV_CTL__DMA_RD_CA_ENA_RMASK 0x1 ++#define TRIO_DEV_CTL__DMA_RD_CA_ENA_MASK 0x8 ++ ++#define TRIO_DEV_CTL__L3_PROFILE_OVD_SHIFT 4 ++#define TRIO_DEV_CTL__L3_PROFILE_OVD_WIDTH 1 ++#define TRIO_DEV_CTL__L3_PROFILE_OVD_RESET_VAL 0 ++#define TRIO_DEV_CTL__L3_PROFILE_OVD_RMASK 0x1 ++#define TRIO_DEV_CTL__L3_PROFILE_OVD_MASK 0x10 ++ ++#define TRIO_DEV_CTL__L3_PROFILE_VAL_SHIFT 5 ++#define TRIO_DEV_CTL__L3_PROFILE_VAL_WIDTH 4 ++#define TRIO_DEV_CTL__L3_PROFILE_VAL_RESET_VAL 0 ++#define TRIO_DEV_CTL__L3_PROFILE_VAL_RMASK 0xf ++#define TRIO_DEV_CTL__L3_PROFILE_VAL_MASK 0x1e0 ++ ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_SHIFT 9 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_WIDTH 2 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_RESET_VAL 2 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_RMASK 0x3 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_MASK 0x600 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_VAL_OKAY 0x0 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_VAL_DATAERROR 0x2 ++#define TRIO_DEV_CTL__WR_SLVERR_MAP_VAL_NONDATAERROR 0x3 ++ ++#define TRIO_DEV_CTL__WR_DECERR_MAP_SHIFT 11 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_WIDTH 2 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_RESET_VAL 3 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_RMASK 0x3 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_MASK 0x1800 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_VAL_OKAY 0x0 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_VAL_DATAERROR 0x2 ++#define TRIO_DEV_CTL__WR_DECERR_MAP_VAL_NONDATAERROR 0x3 ++ ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_SHIFT 13 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_WIDTH 2 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_RESET_VAL 2 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_RMASK 0x3 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_MASK 0x6000 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_VAL_OKAY 0x0 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_VAL_DATAERROR 0x2 ++#define TRIO_DEV_CTL__RD_SLVERR_MAP_VAL_NONDATAERROR 0x3 ++ ++#define TRIO_DEV_CTL__RD_DECERR_MAP_SHIFT 15 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_WIDTH 2 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_RESET_VAL 3 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_RMASK 0x3 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_MASK 0x18000 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_VAL_OKAY 0x0 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_VAL_DATAERROR 0x2 ++#define TRIO_DEV_CTL__RD_DECERR_MAP_VAL_NONDATAERROR 0x3 ++ ++#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_SHIFT 17 ++#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_WIDTH 1 ++#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_RESET_VAL 1 ++#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_RMASK 0x1 ++#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_MASK 0x20000 ++ ++#define TRIO_DEV_CTL__DMA_WRQ_HWM_SHIFT 20 ++#define TRIO_DEV_CTL__DMA_WRQ_HWM_WIDTH 8 ++#define TRIO_DEV_CTL__DMA_WRQ_HWM_RESET_VAL 255 ++#define TRIO_DEV_CTL__DMA_WRQ_HWM_RMASK 0xff ++#define TRIO_DEV_CTL__DMA_WRQ_HWM_MASK 0xff00000 ++ ++#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_SHIFT 28 ++#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_WIDTH 4 ++#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_RESET_VAL 0 ++#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_RMASK 0xf ++#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_MASK 0xf0000000 ++ ++#ifndef __ASSEMBLER__ ++__extension__ ++typedef union { ++ struct { ++ /* ++ * When 1, packets sent on the NDN will be routed x-first. ++ * When 0, packets will be routed y-first. This setting must ++ * match the setting in the Tiles. Devices may have ++ * additional interfaces with customized route-order settings ++ * used in addition to or instead of this field. ++ */ ++ u64 ndn_route_order : 1; ++ /* ++ * When 1, packets sent on the CDN will be routed x-first. ++ * When 0, packets will be routed y-first. This setting must ++ * match the setting in the Tiles. Devices may have ++ * additional interfaces with customized route-order settings ++ * used in addition to or instead of this field. ++ */ ++ u64 cdn_route_order : 1; ++ /* ++ * When 1, packets sent on the DDN will be routed x-first. ++ * When 0, packets will be routed y-first. This setting must ++ * match the setting in the Tiles. Devices may have ++ * additional interfaces with customized route-order settings ++ * used in addition to or instead of this field. ++ */ ++ u64 ddn_route_order : 1; ++ /* ++ * When 1, the ExpCompAck flow will be used on DMA reads ++ * which allows read-data-bypass for lower latency. Must only ++ * be changed if no DMA read traffic is inflight. ++ */ ++ u64 dma_rd_ca_ena : 1; ++ /* ++ * For devices with DMA. When 1, the L3 cache profile will be ++ * forced to L3_PROFILE_VAL. When 0, the L3 profile is ++ * selected by the device. ++ */ ++ u64 l3_profile_ovd : 1; ++ /* ++ * For devices with DMA. L3 cache profile to be used when ++ * L3_PROFILE_OVD is 1. ++ */ ++ u64 l3_profile_val : 4; ++ /* Write response mapping for MMIO slave errors */ ++ u64 wr_slverr_map : 2; ++ /* Write response mapping for MMIO decode errors */ ++ u64 wr_decerr_map : 2; ++ /* Read response mapping for MMIO slave errors */ ++ u64 rd_slverr_map : 2; ++ /* Read response mapping for MMIO decode errors */ ++ u64 rd_decerr_map : 2; ++ /* ++ * When 1, the CDN sync FIFO is allowed to back pressure ++ * until full to avoid retries and improve performance ++ */ ++ u64 cdn_req_buf_ena : 1; ++ /* Reserved. */ ++ u64 __reserved_0 : 2; ++ /* ++ * For diagnostics only. Block new traffic when WRQ_INFL ++ * count exceeds this threshold. This register field does not ++ * exist in the PKA or Tile or MSS. ++ */ ++ u64 dma_wrq_hwm : 8; ++ /* For diagnostics only. Adjust packet gather delay on RNF */ ++ u64 gthr_delay_adj : 4; ++ /* Reserved. */ ++ u64 __reserved_1 : 32; ++ }; ++ ++ u64 word; ++} TRIO_DEV_CTL_t; ++#endif /* !defined(__ASSEMBLER__) */ ++ ++#define TRIO_MMIO_ERROR_INFO 0x0608 ++ ++#define TRIO_MAP_ERR_STS 0x0810 ++ ++#define TRIO_TILE_PIO_CPL_ERR_STS 0x09f0 ++ ++#endif /* !defined(__TRIO_REGS_H__) */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0219-UBUNTU-SAUCE-platform-mellanox-mlxbf-tmfifo-Add-Blue.patch b/platform/mellanox/non-upstream-patches/patches/0219-UBUNTU-SAUCE-platform-mellanox-mlxbf-tmfifo-Add-Blue.patch new file mode 100644 index 0000000000..2ca8f8617f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0219-UBUNTU-SAUCE-platform-mellanox-mlxbf-tmfifo-Add-Blue.patch @@ -0,0 +1,245 @@ +From 9a21e6cf3c87954516a7933539fbcb5b373f9fa2 Mon Sep 17 00:00:00 2001 +From: Liming Sun +Date: Sun, 26 Jun 2022 01:10:07 -0400 +Subject: [PATCH backport 5.10 20/63] UBUNTU: SAUCE: platform/mellanox: + mlxbf-tmfifo: Add BlueField-3 support + +BugLink: https://launchpad.net/bugs/1980847 + +This commit adds BlueField-3 support which has different resource +mapping and is identified by the ACPI UID. + +Signed-off-by: Liming Sun +Change-Id: I104472a89741c1083168bacb4a7652c7767cceff +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/mlxbf-tmfifo-regs.h | 10 +++ + drivers/platform/mellanox/mlxbf-tmfifo.c | 82 ++++++++++++++----- + 2 files changed, 70 insertions(+), 22 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-tmfifo-regs.h b/drivers/platform/mellanox/mlxbf-tmfifo-regs.h +index e4f0d2eda..1358dad0c 100644 +--- a/drivers/platform/mellanox/mlxbf-tmfifo-regs.h ++++ b/drivers/platform/mellanox/mlxbf-tmfifo-regs.h +@@ -60,4 +60,14 @@ + #define MLXBF_TMFIFO_RX_CTL__MAX_ENTRIES_RMASK GENMASK_ULL(8, 0) + #define MLXBF_TMFIFO_RX_CTL__MAX_ENTRIES_MASK GENMASK_ULL(40, 32) + ++/* BF3 resource 0 register offset. */ ++#define MLXBF_TMFIFO_RX_DATA_BF3 0x0000 ++#define MLXBF_TMFIFO_TX_DATA_BF3 0x1000 ++ ++/* BF3 resource 1 register offset. */ ++#define MLXBF_TMFIFO_RX_STS_BF3 0x0000 ++#define MLXBF_TMFIFO_RX_CTL_BF3 0x0008 ++#define MLXBF_TMFIFO_TX_STS_BF3 0x0100 ++#define MLXBF_TMFIFO_TX_CTL_BF3 0x0108 ++ + #endif /* !defined(__MLXBF_TMFIFO_REGS_H__) */ +diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c +index 38800e86e..f401bbbd0 100644 +--- a/drivers/platform/mellanox/mlxbf-tmfifo.c ++++ b/drivers/platform/mellanox/mlxbf-tmfifo.c +@@ -47,6 +47,9 @@ + /* Message with data needs at least two words (for header & data). */ + #define MLXBF_TMFIFO_DATA_MIN_WORDS 2 + ++/* ACPI chip identifier for BlueField-3. */ ++#define MLXBF_TMFIFO_BF3_UID "1" ++ + struct mlxbf_tmfifo; + + /** +@@ -140,8 +143,14 @@ struct mlxbf_tmfifo_irq_info { + * mlxbf_tmfifo - Structure of the TmFifo + * @vdev: array of the virtual devices running over the TmFifo + * @lock: lock to protect the TmFifo access +- * @rx_base: mapped register base address for the Rx FIFO +- * @tx_base: mapped register base address for the Tx FIFO ++ * @res0: mapped register base for resource 0 ++ * @res1: mapped register base for resource 1 ++ * @rx_ctl: TMFIFO_RX_CTL register ++ * @rx_sts: TMFIFO_RX_STS register ++ * @rx_data: TMFIFO_RX_DATA register ++ * @tx_ctl: TMFIFO_TX_CTL register ++ * @tx_sts: TMFIFO_TX_STS register ++ * @tx_data: TMFIFO_TX_DATA register + * @rx_fifo_size: number of entries of the Rx FIFO + * @tx_fifo_size: number of entries of the Tx FIFO + * @pend_events: pending bits for deferred events +@@ -155,8 +164,14 @@ struct mlxbf_tmfifo_irq_info { + struct mlxbf_tmfifo { + struct mlxbf_tmfifo_vdev *vdev[MLXBF_TMFIFO_VDEV_MAX]; + struct mutex lock; /* TmFifo lock */ +- void __iomem *rx_base; +- void __iomem *tx_base; ++ void __iomem *res0; ++ void __iomem *res1; ++ void __iomem *rx_ctl; ++ void __iomem *rx_sts; ++ void __iomem *rx_data; ++ void __iomem *tx_ctl; ++ void __iomem *tx_sts; ++ void __iomem *tx_data; + int rx_fifo_size; + int tx_fifo_size; + unsigned long pend_events; +@@ -472,7 +487,7 @@ static int mlxbf_tmfifo_get_rx_avail(struct mlxbf_tmfifo *fifo) + { + u64 sts; + +- sts = readq(fifo->rx_base + MLXBF_TMFIFO_RX_STS); ++ sts = readq(fifo->rx_sts); + return FIELD_GET(MLXBF_TMFIFO_RX_STS__COUNT_MASK, sts); + } + +@@ -489,7 +504,7 @@ static int mlxbf_tmfifo_get_tx_avail(struct mlxbf_tmfifo *fifo, int vdev_id) + else + tx_reserve = 1; + +- sts = readq(fifo->tx_base + MLXBF_TMFIFO_TX_STS); ++ sts = readq(fifo->tx_sts); + count = FIELD_GET(MLXBF_TMFIFO_TX_STS__COUNT_MASK, sts); + return fifo->tx_fifo_size - tx_reserve - count; + } +@@ -525,7 +540,7 @@ static void mlxbf_tmfifo_console_tx(struct mlxbf_tmfifo *fifo, int avail) + /* Write header. */ + hdr.type = VIRTIO_ID_CONSOLE; + hdr.len = htons(size); +- writeq(*(u64 *)&hdr, fifo->tx_base + MLXBF_TMFIFO_TX_DATA); ++ writeq(*(u64 *)&hdr, fifo->tx_data); + + /* Use spin-lock to protect the 'cons->tx_buf'. */ + spin_lock_irqsave(&fifo->spin_lock[0], flags); +@@ -542,7 +557,7 @@ static void mlxbf_tmfifo_console_tx(struct mlxbf_tmfifo *fifo, int avail) + memcpy((u8 *)&data + seg, cons->tx_buf.buf, + sizeof(u64) - seg); + } +- writeq(data, fifo->tx_base + MLXBF_TMFIFO_TX_DATA); ++ writeq(data, fifo->tx_data); + + if (size >= sizeof(u64)) { + cons->tx_buf.tail = (cons->tx_buf.tail + sizeof(u64)) % +@@ -573,7 +588,7 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring, + + /* Read a word from FIFO for Rx. */ + if (is_rx) +- data = readq(fifo->rx_base + MLXBF_TMFIFO_RX_DATA); ++ data = readq(fifo->rx_data); + + if (vring->cur_len + sizeof(u64) <= len) { + /* The whole word. */ +@@ -595,7 +610,7 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring, + + /* Write the word into FIFO for Tx. */ + if (!is_rx) +- writeq(data, fifo->tx_base + MLXBF_TMFIFO_TX_DATA); ++ writeq(data, fifo->tx_data); + } + + /* +@@ -617,7 +632,7 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring, + /* Read/Write packet header. */ + if (is_rx) { + /* Drain one word from the FIFO. */ +- *(u64 *)&hdr = readq(fifo->rx_base + MLXBF_TMFIFO_RX_DATA); ++ *(u64 *)&hdr = readq(fifo->rx_data); + + /* Skip the length 0 packets (keepalive). */ + if (hdr.len == 0) +@@ -661,7 +676,7 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring, + hdr.type = (vring->vdev_id == VIRTIO_ID_NET) ? + VIRTIO_ID_NET : VIRTIO_ID_CONSOLE; + hdr.len = htons(vring->pkt_len - hdr_len); +- writeq(*(u64 *)&hdr, fifo->tx_base + MLXBF_TMFIFO_TX_DATA); ++ writeq(*(u64 *)&hdr, fifo->tx_data); + } + + vring->cur_len = hdr_len; +@@ -1155,7 +1170,7 @@ static void mlxbf_tmfifo_set_threshold(struct mlxbf_tmfifo *fifo) + u64 ctl; + + /* Get Tx FIFO size and set the low/high watermark. */ +- ctl = readq(fifo->tx_base + MLXBF_TMFIFO_TX_CTL); ++ ctl = readq(fifo->tx_ctl); + fifo->tx_fifo_size = + FIELD_GET(MLXBF_TMFIFO_TX_CTL__MAX_ENTRIES_MASK, ctl); + ctl = (ctl & ~MLXBF_TMFIFO_TX_CTL__LWM_MASK) | +@@ -1164,17 +1179,17 @@ static void mlxbf_tmfifo_set_threshold(struct mlxbf_tmfifo *fifo) + ctl = (ctl & ~MLXBF_TMFIFO_TX_CTL__HWM_MASK) | + FIELD_PREP(MLXBF_TMFIFO_TX_CTL__HWM_MASK, + fifo->tx_fifo_size - 1); +- writeq(ctl, fifo->tx_base + MLXBF_TMFIFO_TX_CTL); ++ writeq(ctl, fifo->tx_ctl); + + /* Get Rx FIFO size and set the low/high watermark. */ +- ctl = readq(fifo->rx_base + MLXBF_TMFIFO_RX_CTL); ++ ctl = readq(fifo->rx_ctl); + fifo->rx_fifo_size = + FIELD_GET(MLXBF_TMFIFO_RX_CTL__MAX_ENTRIES_MASK, ctl); + ctl = (ctl & ~MLXBF_TMFIFO_RX_CTL__LWM_MASK) | + FIELD_PREP(MLXBF_TMFIFO_RX_CTL__LWM_MASK, 0); + ctl = (ctl & ~MLXBF_TMFIFO_RX_CTL__HWM_MASK) | + FIELD_PREP(MLXBF_TMFIFO_RX_CTL__HWM_MASK, 1); +- writeq(ctl, fifo->rx_base + MLXBF_TMFIFO_RX_CTL); ++ writeq(ctl, fifo->rx_ctl); + } + + static void mlxbf_tmfifo_cleanup(struct mlxbf_tmfifo *fifo) +@@ -1194,9 +1209,15 @@ static int mlxbf_tmfifo_probe(struct platform_device *pdev) + { + struct virtio_net_config net_config; + struct device *dev = &pdev->dev; ++ struct acpi_device *device; + struct mlxbf_tmfifo *fifo; ++ const char *uid; + int i, rc; + ++ device = ACPI_COMPANION(dev); ++ if (!device) ++ return -ENODEV; ++ + fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL); + if (!fifo) + return -ENOMEM; +@@ -1207,14 +1228,31 @@ static int mlxbf_tmfifo_probe(struct platform_device *pdev) + mutex_init(&fifo->lock); + + /* Get the resource of the Rx FIFO. */ +- fifo->rx_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(fifo->rx_base)) +- return PTR_ERR(fifo->rx_base); ++ fifo->res0 = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(fifo->res0)) ++ return PTR_ERR(fifo->res0); + + /* Get the resource of the Tx FIFO. */ +- fifo->tx_base = devm_platform_ioremap_resource(pdev, 1); +- if (IS_ERR(fifo->tx_base)) +- return PTR_ERR(fifo->tx_base); ++ fifo->res1 = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(fifo->res1)) ++ return PTR_ERR(fifo->res1); ++ ++ uid = acpi_device_uid(device); ++ if (uid && !strcmp(uid, MLXBF_TMFIFO_BF3_UID)) { ++ fifo->rx_data = fifo->res0 + MLXBF_TMFIFO_RX_DATA_BF3; ++ fifo->tx_data = fifo->res0 + MLXBF_TMFIFO_TX_DATA_BF3; ++ fifo->rx_sts = fifo->res1 + MLXBF_TMFIFO_RX_STS_BF3; ++ fifo->rx_ctl = fifo->res1 + MLXBF_TMFIFO_RX_CTL_BF3; ++ fifo->tx_sts = fifo->res1 + MLXBF_TMFIFO_TX_STS_BF3; ++ fifo->tx_ctl = fifo->res1 + MLXBF_TMFIFO_TX_CTL_BF3; ++ } else { ++ fifo->rx_ctl = fifo->res0 + MLXBF_TMFIFO_RX_CTL; ++ fifo->rx_sts = fifo->res0 + MLXBF_TMFIFO_RX_STS; ++ fifo->rx_data = fifo->res0 + MLXBF_TMFIFO_RX_DATA; ++ fifo->tx_ctl = fifo->res1 + MLXBF_TMFIFO_TX_CTL; ++ fifo->tx_sts = fifo->res1 + MLXBF_TMFIFO_TX_STS; ++ fifo->tx_data = fifo->res1 + MLXBF_TMFIFO_TX_DATA; ++ } + + platform_set_drvdata(pdev, fifo); + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0220-UBUNTU-SAUCE-pka-Add-pka-driver.patch b/platform/mellanox/non-upstream-patches/patches/0220-UBUNTU-SAUCE-pka-Add-pka-driver.patch new file mode 100644 index 0000000000..875083ea02 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0220-UBUNTU-SAUCE-pka-Add-pka-driver.patch @@ -0,0 +1,10216 @@ +From c1e48283efef4faeee6b601fc679ea228bd8d6ef Mon Sep 17 00:00:00 2001 +From: Mahantesh Salimath +Date: Thu, 30 Jun 2022 16:46:50 -0400 +Subject: [PATCH backport 5.10 21/63] UBUNTU: SAUCE: pka: Add pka driver. + +BugLink: https://bugs.launchpad.net/bugs/1980415 + +* This driver is picked from internal linux repo;bfdev-5.4.60 branch. + For commit history, please refer to above repo and branch. + +Signed-off-by: Mahantesh Salimath +Reviewed-by: Khalil Blaiech +Signed-off-by: Mahantesh Salimath +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/Kconfig | 2 + + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/mellanox/mlxbf_pka/Kconfig | 14 + + drivers/platform/mellanox/mlxbf_pka/Makefile | 9 + + .../mellanox/mlxbf_pka/mlxbf_pka_addrs.h | 284 + + .../mellanox/mlxbf_pka/mlxbf_pka_config.h | 226 + + .../mellanox/mlxbf_pka/mlxbf_pka_cpu.h | 72 + + .../mellanox/mlxbf_pka/mlxbf_pka_debug.h | 66 + + .../mellanox/mlxbf_pka/mlxbf_pka_dev.c | 2414 +++++++++ + .../mellanox/mlxbf_pka/mlxbf_pka_dev.h | 310 ++ + .../mellanox/mlxbf_pka/mlxbf_pka_drv.c | 1398 +++++ + .../mellanox/mlxbf_pka/mlxbf_pka_firmware.h | 4823 +++++++++++++++++ + .../mellanox/mlxbf_pka/mlxbf_pka_ioctl.h | 127 + + .../mellanox/mlxbf_pka/mlxbf_pka_mmio.h | 49 + + .../mellanox/mlxbf_pka/mlxbf_pka_ring.h | 276 + + 15 files changed, 10071 insertions(+) + create mode 100644 drivers/platform/mellanox/mlxbf_pka/Kconfig + create mode 100644 drivers/platform/mellanox/mlxbf_pka/Makefile + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_addrs.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_config.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_cpu.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_debug.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.c + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_firmware.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ioctl.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_mmio.h + create mode 100644 drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ring.h + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index 5d329350a..946bc2375 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -97,6 +97,8 @@ config MLXBF_TRIO + This driver supports the TRIO PCIe root complex interface on + Mellanox BlueField SoCs. + ++source "drivers/platform/mellanox/mlxbf_pka/Kconfig" ++ + config NVSW_SN2201 + tristate "Nvidia SN2201 platform driver support" + depends on REGMAP +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index 161fad566..046347d3a 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -12,3 +12,4 @@ obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o + obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o + obj-$(CONFIG_NVSW_SN2201) += nvsw-sn2201.o ++obj-$(CONFIG_MLXBF_PKA) += mlxbf_pka/ +diff --git a/drivers/platform/mellanox/mlxbf_pka/Kconfig b/drivers/platform/mellanox/mlxbf_pka/Kconfig +new file mode 100644 +index 000000000..ebc038ec7 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/Kconfig +@@ -0,0 +1,14 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB ++# ++# Platform support for Mellanox BlueField PKA ++# ++ ++config MLXBF_PKA ++ tristate "Mellanox BlueField Public Key Accelerator driver" ++ depends on ARM64 && IOMMU_API && VFIO_IOMMU_TYPE1 && VFIO_PLATFORM ++ help ++ If you say yes to this option, support will be included for the ++ Public Key Accelerator device on Mellanox BlueField SoCs. ++ ++ This driver can also be built as a module. If so, the module will ++ be called pka-mlxbf. +diff --git a/drivers/platform/mellanox/mlxbf_pka/Makefile b/drivers/platform/mellanox/mlxbf_pka/Makefile +new file mode 100644 +index 000000000..d9f5be4d6 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/Makefile +@@ -0,0 +1,9 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB ++# ++# Makefile for Mellanox BlueField PKA Driver ++# ++ ++obj-m += mlxbf-pka.o ++ ++mlxbf-pka-y := mlxbf_pka_drv.o ++mlxbf-pka-y += mlxbf_pka_dev.o +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_addrs.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_addrs.h +new file mode 100644 +index 000000000..cd2a4d814 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_addrs.h +@@ -0,0 +1,284 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_ADDRS_H__ ++#define __PKA_ADDRS_H__ ++ ++// Define memory size in bytes ++#define MEM_SIZE_4KB 0x1000 ++#define MEM_SIZE_8KB 0x2000 ++#define MEM_SIZE_16KB 0x4000 ++#define MEM_SIZE_32KB 0x8000 ++#define MEM_SIZE_64KB 0x10000 ++ ++// ++// COMMON SPACE ++// ++#define CRYPTO_COMMON_BASE 0x0 ++ ++// Common IO CSR addresses/offsets: These are all addressed as 8-byte registers. ++#define DEV_INFO_ADDR (0x00 | CRYPTO_COMMON_BASE) ++#define DEV_CTL_ADDR (0x08 | CRYPTO_COMMON_BASE) ++#define MMIO_INFO_ADDR (0x10 | CRYPTO_COMMON_BASE) ++#define SCRATCHPAD_ADDR (0x20 | CRYPTO_COMMON_BASE) ++#define SEMAPHORE0_ADDR (0x28 | CRYPTO_COMMON_BASE) ++#define SEMAPHORE1_ADDR (0x30 | CRYPTO_COMMON_BASE) ++#define CLOCK_COUNT_ADDR (0x38 | CRYPTO_COMMON_BASE) ++#define INT_SETUP_ADDR (0x40 | CRYPTO_COMMON_BASE) ++#define CRED_CTL_ADDR (0x50 | CRYPTO_COMMON_BASE) ++#define SAM_CTL_ADDR (0x58 | CRYPTO_COMMON_BASE) ++ ++// ++// CRYPTO SPACE ++// ++ ++// All addresses/offsets herein are BYTE addresses. ++ ++// EIP154 CSRS: ++ ++// Global Control Space CSR addresses/offsets. These are accessed from the ++// ARM as 8 byte reads/writes however only the bottom 32 bits are implemented. ++#define PKA_CLOCK_SWITCH_ADDR 0x11C68 ++#define PKA_CLK_FORCE_ADDR 0x11C80 ++#define MODE_SELECTION_ADDR 0x11C88 ++#define PKA_PROT_STATUS_ADDR 0x11C90 ++#define PKA_OPTIONS_ADDR 0x11DF0 ++#define PKA_VERSION_ADDR 0x11DF8 ++ ++// Advanced Interrupt Controller CSR addresses/offsets. These are accessed ++// from the ARM as 8 byte reads/writes however only the bottom 32 bits are ++// implemented. ++#define AIC_POL_CTRL_ADDR 0x11E00 ++#define AIC_TYPE_CTRL_ADDR 0x11E08 ++#define AIC_ENABLE_CTRL_ADDR 0x11E10 ++#define AIC_RAW_STAT_ADDR 0x11E18 ++#define AIC_ENABLE_SET_ADDR 0x11E18 ++#define AIC_ENABLED_STAT_ADDR 0x11E20 ++#define AIC_ACK_ADDR 0x11E20 ++#define AIC_ENABLE_CLR_ADDR 0x11E28 ++#define AIC_OPTIONS_ADDR 0x11E30 ++#define AIC_VERSION_ADDR 0x11E38 ++ ++// The True Random Number Generator CSR addresses/offsets. These are accessed ++// from the ARM as 8 byte reads/writes however only the bottom 32 bits are ++// implemented. ++#define TRNG_OUTPUT_0_ADDR 0x12000 ++#define TRNG_OUTPUT_1_ADDR 0x12008 ++#define TRNG_OUTPUT_2_ADDR 0x12010 ++#define TRNG_OUTPUT_3_ADDR 0x12018 ++#define TRNG_STATUS_ADDR 0x12020 ++#define TRNG_INTACK_ADDR 0x12020 ++#define TRNG_CONTROL_ADDR 0x12028 ++#define TRNG_CONFIG_ADDR 0x12030 ++#define TRNG_ALARMCNT_ADDR 0x12038 ++#define TRNG_FROENABLE_ADDR 0x12040 ++#define TRNG_FRODETUNE_ADDR 0x12048 ++#define TRNG_ALARMMASK_ADDR 0x12050 ++#define TRNG_ALARMSTOP_ADDR 0x12058 ++#define TRNG_BLOCKCNT_ADDR 0x120E8 ++#define TRNG_OPTIONS_ADDR 0x120F0 ++#define TRNG_TEST_ADDR 0x120E0 ++#define TRNG_RAW_L_ADDR 0x12060 ++#define TRNG_RAW_H_ADDR 0x12068 ++#define TRNG_RUN_CNT_ADDR 0x12080 ++#define TRNG_MONOBITCNT_ADDR 0x120B8 ++#define TRNG_POKER_3_0_ADDR 0x120C0 ++#define TRNG_POKER_7_4 0x120C8 ++#define TRNG_POKER_B_8 0x120D0 ++#define TRNG_POKER_F_C 0x120D8 ++ ++#define TRNG_PS_AI_0_ADDR 0x12080 ++#define TRNG_PS_AI_1_ADDR 0x12088 ++#define TRNG_PS_AI_2_ADDR 0x12090 ++#define TRNG_PS_AI_3_ADDR 0x12098 ++#define TRNG_PS_AI_4_ADDR 0x120A0 ++#define TRNG_PS_AI_5_ADDR 0x120A8 ++#define TRNG_PS_AI_6_ADDR 0x120B0 ++#define TRNG_PS_AI_7_ADDR 0x120B8 ++#define TRNG_PS_AI_8_ADDR 0x120C0 ++#define TRNG_PS_AI_9_ADDR 0x120C8 ++#define TRNG_PS_AI_10_ADDR 0x120D0 ++#define TRNG_PS_AI_11_ADDR 0x120D8 ++ ++// Control register address/offset. This is accessed from the ARM using 8 ++// byte reads/writes however only the bottom 32 bits are implemented. ++#define PKA_MASTER_SEQ_CTRL_ADDR 0x27F90 ++ ++// Ring CSRs: These are all accessed from the ARM using 8 byte reads/writes ++// however only the bottom 32 bits are implemented. ++ ++// Ring 0 CSRS ++#define COMMAND_COUNT_0_ADDR 0x80080 ++#define RESULT_COUNT_0_ADDR 0x80088 ++#define IRQ_THRESH_0_ADDR 0x80090 ++ ++// Ring 1 CSRS: ++#define COMMAND_COUNT_1_ADDR 0x90080 ++#define RESULT_COUNT_1_ADDR 0x90088 ++#define IRQ_THRESH_1_ADDR 0x90090 ++ ++// Ring 2 CSRS: ++#define COMMAND_COUNT_2_ADDR 0xA0080 ++#define RESULT_COUNT_2_ADDR 0xA0088 ++#define IRQ_THRESH_2_ADDR 0xA0090 ++ ++// Ring 3 CSRS: ++#define COMMAND_COUNT_3_ADDR 0xB0080 ++#define RESULT_COUNT_3_ADDR 0xB0088 ++#define IRQ_THRESH_3_ADDR 0xB0090 ++ ++// EIP154 RAM regions: Note that the FARM_PROG_RAM_X address range overlaps ++// with the FARM_DATA_RAM_X and FARM_DATA_RAM_X_EXT address ranges. This ++// conflict is resolved by using the FARM_PROG_RAM_X only when the ++// Sequencer is in SW reset, and the DATA_RAMs are picked only when the ++// engine is operation. ++// ++// Note: ++// The FARM_DATA_RAM_X_EXT RAMs may also be ++// called the LNME FIFO RAMs in some of the documentation. ++// ++// PKA_BUFFER_RAM : 1024 x 64 - 8K bytes ++// PKA_SECURE_RAM : 1536 x 64 - 12K bytes ++// PKA_MASTER_PROG_RAM : 8192 x 32 - 32K bytes ++// FARM_DATA_RAM_X : 1024 x 64 - 8K bytes ++// FARM_DATA_RAM_X_EXT : 256 x 32 - 1K bytes ++// FARM_PROG_RAM_X : 2048 x 32 - 8K bytes ++// ++// Note: ++// *TBD* Since hardware guys multiplied the address per 2, the size of ++// each memory/registers group increased and become two times larger. ++// Memory size should be adjusted accordingly: ++// PKA Buffer RAM size : 8KB --> 16KB ++// PKA Secure RAM size : 8KB --> 16KB ++// PKA Master Program RAM size : 32KB --> 64KB ++// PKA Farm Data RAM size : 4KB --> 8KB ++// PKA Farm Data RAM extension size : 4KB --> 8KB ++// PKA Farm Program RAM size : 8KB --> 16KB ++// ++#define PKA_BUFFER_RAM_BASE 0x00000 ++#define PKA_BUFFER_RAM_SIZE MEM_SIZE_16KB // 0x00000...0x03FFF ++ ++#define PKA_SECURE_RAM_BASE 0x20000 ++#define PKA_SECURE_RAM_SIZE MEM_SIZE_16KB // 0x20000...0x23FFF ++ ++#define PKA_MASTER_PROG_RAM_BASE 0x30000 ++#define PKA_MASTER_PROG_RAM_SIZE MEM_SIZE_64KB // 0x30000...0x3FFFF ++ ++#define FARM_DATA_RAM_0_BASE 0x40000 ++#define FARM_DATA_RAM_0_SIZE MEM_SIZE_8KB // 0x40000...0x41FFF ++#define FARM_DATA_RAM_0_EXT_BASE 0x42000 ++#define FARM_DATA_RAM_0_EXT_SIZE MEM_SIZE_8KB // 0x42000...0x43FFF ++#define FARM_PROG_RAM_0_BASE 0x40000 ++#define FARM_PROG_RAM_0_SIZE MEM_SIZE_16KB // 0x40000...0x43FFF ++#define FARM_DATA_RAM_1_BASE 0x44000 ++#define FARM_DATA_RAM_1_SIZE MEM_SIZE_8KB // 0x44000...0x45FFF ++#define FARM_DATA_RAM_1_EXT_BASE 0x46000 ++#define FARM_DATA_RAM_1_EXT_SIZE MEM_SIZE_8KB // 0x46000...0x47FFF ++#define FARM_PROG_RAM_1_BASE 0x44000 ++#define FARM_PROG_RAM_1_SIZE MEM_SIZE_16KB // 0x44000...0x47FFF ++#define FARM_DATA_RAM_2_BASE 0x48000 ++#define FARM_DATA_RAM_2_SIZE MEM_SIZE_8KB // 0x48000...0x49FFF ++#define FARM_DATA_RAM_2_EXT_BASE 0x4A000 ++#define FARM_DATA_RAM_2_EXT_SIZE MEM_SIZE_8KB // 0x4A000...0x4BFFF ++#define FARM_PROG_RAM_2_BASE 0x48000 ++#define FARM_PROG_RAM_2_SIZE MEM_SIZE_16KB // 0x48000...0x4BFFF ++#define FARM_DATA_RAM_3_BASE 0x4C000 ++#define FARM_DATA_RAM_3_SIZE MEM_SIZE_8KB // 0x4C000...0x4DFFF ++#define FARM_DATA_RAM_3_EXT_BASE 0x4E000 ++#define FARM_DATA_RAM_3_EXT_SIZE MEM_SIZE_8KB // 0x4E000...0x4FFFF ++#define FARM_PROG_RAM_3_BASE 0x4C000 ++#define FARM_PROG_RAM_3_SIZE MEM_SIZE_16KB // 0x4C000...0x4FFFF ++#define FARM_DATA_RAM_4_BASE 0x50000 ++#define FARM_DATA_RAM_4_SIZE MEM_SIZE_8KB // 0x50000...0x51FFF ++#define FARM_DATA_RAM_4_EXT_BASE 0x52000 ++#define FARM_DATA_RAM_4_EXT_SIZE MEM_SIZE_8KB // 0x52000...0x53FFF ++#define FARM_PROG_RAM_4_BASE 0x50000 ++#define FARM_PROG_RAM_4_SIZE MEM_SIZE_16KB // 0x50000...0x53FFF ++#define FARM_DATA_RAM_5_BASE 0x54000 ++#define FARM_DATA_RAM_5_SIZE MEM_SIZE_8KB // 0x54000...0x55FFF ++#define FARM_DATA_RAM_5_EXT_BASE 0x56000 ++#define FARM_DATA_RAM_5_EXT_SIZE MEM_SIZE_8KB // 0x56000...0x57FFF ++#define FARM_PROG_RAM_5_BASE 0x54000 ++#define FARM_PROG_RAM_5_SIZE MEM_SIZE_16KB // 0x54000...0x57FFF ++ ++// PKA Buffer RAM offsets. These are NOT real CSR's but instead are ++// specific offset/addresses within the EIP154 PKA_BUFFER_RAM. ++ ++// Ring 0: ++#define RING_CMMD_BASE_0_ADDR 0x00000 ++#define RING_RSLT_BASE_0_ADDR 0x00010 ++#define RING_SIZE_TYPE_0_ADDR 0x00020 ++#define RING_RW_PTRS_0_ADDR 0x00028 ++#define RING_RW_STAT_0_ADDR 0x00030 ++ ++// Ring 1 ++#define RING_CMMD_BASE_1_ADDR 0x00040 ++#define RING_RSLT_BASE_1_ADDR 0x00050 ++#define RING_SIZE_TYPE_1_ADDR 0x00060 ++#define RING_RW_PTRS_1_ADDR 0x00068 ++#define RING_RW_STAT_1_ADDR 0x00070 ++ ++// Ring 2 ++#define RING_CMMD_BASE_2_ADDR 0x00080 ++#define RING_RSLT_BASE_2_ADDR 0x00090 ++#define RING_SIZE_TYPE_2_ADDR 0x000A0 ++#define RING_RW_PTRS_2_ADDR 0x000A8 ++#define RING_RW_STAT_2_ADDR 0x000B0 ++ ++// Ring 3 ++#define RING_CMMD_BASE_3_ADDR 0x000C0 ++#define RING_RSLT_BASE_3_ADDR 0x000D0 ++#define RING_SIZE_TYPE_3_ADDR 0x000E0 ++#define RING_RW_PTRS_3_ADDR 0x000E8 ++#define RING_RW_STAT_3_ADDR 0x000F0 ++ ++// Ring Options ++#define PKA_RING_OPTIONS_ADDR 0x07FF8 ++ ++// Alternate Window RAM size ++#define PKA_WINDOW_RAM_REGION_SIZE MEM_SIZE_16KB ++ ++// Currently, we do not use these MiCA specific CSRs. ++ ++// The PKI (not EIP154) CSR address/offsets: These are all addressed as ++// 8-byte registers. ++#define PKA_INT_MASK_ADDR 0x00 ++#define PKA_INT_MASK_SET_ADDR 0x08 ++#define PKA_INT_MASK_RESET_ADDR 0x10 ++#define PKA_ZEROIZE_ADDR 0x40 ++#define TST_FRO_ADDR 0x50 ++#define FRO_COUNT_ADDR 0x58 ++#define PKA_PARITY_CTL_ADDR 0x60 ++#define PKA_PARITY_STAT_ADDR 0x68 ++ ++#endif // __PKA_ADDRS_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_config.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_config.h +new file mode 100644 +index 000000000..5b69d55be +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_config.h +@@ -0,0 +1,226 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_CONFIG_H__ ++#define __PKA_CONFIG_H__ ++ ++#include "mlxbf_pka_addrs.h" ++ ++// The maximum number of PKA shims refered to as IO blocks. ++#define PKA_MAX_NUM_IO_BLOCKS 8 ++// The maximum number of Rings supported by IO block (shim). ++#define PKA_MAX_NUM_IO_BLOCK_RINGS 4 ++ ++#define PKA_MAX_NUM_RINGS \ ++ (PKA_MAX_NUM_IO_BLOCK_RINGS * PKA_MAX_NUM_IO_BLOCKS) ++ ++// Resources are regions which include info control/status words, ++// count registers and host window ram. ++#define PKA_MAX_NUM_RING_RESOURCES 3 ++ ++// PKA Ring resources. ++// Define Ring resources parameters including base address, size (in bytes) ++// and ring spacing. ++#define PKA_RING_WORDS_ADDR PKA_BUFFER_RAM_BASE ++#define PKA_RING_CNTRS_ADDR COMMAND_COUNT_0_ADDR ++ ++#define PKA_RING_WORDS_SIZE 0x40 // 64 bytes ++#define PKA_RING_CNTRS_SIZE 0x20 // 32 bytes (3 count registers) ++#define PKA_RING_MEM_SIZE 0x4000 // 16K bytes ++ ++#define PKA_RING_WORDS_SPACING 0x40 // 64 bytes ++#define PKA_RING_CNTRS_SPACING 0x10000 // 64K bytes ++#define PKA_RING_MEM_0_SPACING 0x4000 // 16K bytes ++#define PKA_RING_MEM_1_SPACING 0x10000 // 64K bytes ++ ++// PKA Window RAM parameters. ++// Define whether to split or not Window RAM during PKA device creation phase. ++#define SPLIT_WINDOW_RAM_MODE_ENABLED 1 ++#define SPLIT_WINDOW_RAM_MODE_DISABLED 0 ++#define PKA_SPLIT_WINDOW_RAM_MODE SPLIT_WINDOW_RAM_MODE_DISABLED ++// Defines for Window RAM partition. It is valid for 16K memory. ++#define PKA_WINDOW_RAM_RING_MEM_SIZE 0x0800 // 2KB ++#define PKA_WINDOW_RAM_DATA_MEM_SIZE 0x3800 // 14KB ++ ++// Offset mask, common to both Window and Alternate Window RAM. ++#define PKA_WINDOW_RAM_OFFSET_MASK1 0x730000 ++ ++// Macro for mapping PKA Ring address into Window RAM address. It converts the ++// ring address, either physical address or virtual address, to valid address ++// into the Window RAM. This is done assuming the Window RAM base, size and ++// mask. Here, base is the actual physical address of the Window RAM, with the ++// help of mask it is reduced to Window RAM offset within that PKA block. ++// Further, with the help of addr and size, we arrive at the Window RAM ++// offset address for a PKA Ring within the given Window RAM. ++#define PKA_RING_MEM_ADDR(base, mask, addr, size) \ ++ ((base & mask) | (((addr) & 0xffff) | \ ++ ((((addr) & ~((size) - 1)) & 0xf0000) >> 2))) ++ ++// PKA Master Sequencer Control/Status Register ++// Write '1' to bit [31] puts the Master controller Sequencer in a reset ++// reset state. Resetting the Sequencer (in order to load other firmware) ++// should only be done when the EIP-154 is not performing any operations. ++#define PKA_MASTER_SEQ_CTRL_RESET_VAL 0x80000000 ++// Write '1' to bit [30] will reset all Command and Result counters. This ++// bit is write-only and self clearing and can only be set if the ‘Reset’ ++// bit [31] is ‘1’. ++#define PKA_MASTER_SEQ_CTRL_CLEAR_COUNTERS_VAL 0x40000000 ++// Bit [8] in the PKA Master Sequencer Control/Status Register is tied to ++// the 'pka_master_irq interrupt' on the EIP-154 interrupt controller. ++#define PKA_MASTER_SEQ_CTRL_MASTER_IRQ_BIT 8 ++// Sequencer status bits are used by the Master controller Sequencer to ++// reflect status. Bit [0] is tied to the 'pka_master_irq' interrupt on ++// the EIP-154 interrupt controller. ++#define PKA_MASTER_SEQ_CTRL_STATUS_BYTE 0x01 ++// 'pka_master_irq' mask for the Master controller Sequencer Status Register. ++#define PKA_MASTER_SEQ_CTRL_MASTER_IRQ_MASK 0x100 ++ ++// Advanced Interrupt Controller (AIC) configuration ++// AIC Polarity Control Register is used to set each individual interrupt ++// signal (High Level / Rising Edge) during the initialization phase. ++// '0' = Low level or falling edge. ++// '1' = High level or rising edge. ++#define PKA_AIC_POL_CTRL_REG_VAL 0x000FFFFF ++// AIC Type Control Register is used to set each interrupt to level or edge. ++// '0' = Level. ++// '1' = Edge. ++#define PKA_AIC_TYPE_CTRL_REG_VAL 0x000FFFFF ++// AIC Enable Control Register is used to enable interrupt inputs. ++// '0' = Disabled. ++// '1' = Enabled. ++#define PKA_AIC_ENABLE_CTRL_REG_VAL 0x000F030F ++// AIC Enabled Status Register bits reflect the status of the interrupts ++// gated with the enable bits of the AIC_ENABLE_CTRL Register. ++// '0' = Inactive. ++// '1' = Pending. ++#define PKA_AIC_ENABLE_STAT_REG_VAL 0x000F030F ++ ++// 'pka_master_irq' mask for the AIC Enabled Status Register. ++#define PKA_AIC_ENABLED_STAT_MASTER_IRQ_MASK 0x100 ++ ++// PKA_RING_OPTIONS field to specify the priority in which rings are handled: ++// '00' = full rotating priority, ++// '01' = fixed priority (ring 0 lowest), ++// '10' = ring 0 has the highest priority and the remaining rings have ++// rotating priority, ++// '11' = reserved, do not use. ++#define PKA_FULL_ROTATING_PRIORITY 0x0 ++#define PKA_FIXED_PRIORITY 0x1 ++#define PKA_RING_0_HAS_THE_HIGHEST_PRIORITY 0x2 ++#define PKA_RESERVED 0x3 ++#define PKA_RING_OPTIONS_PRIORITY PKA_FULL_ROTATING_PRIORITY ++ ++// 'Signature' byte used because the ring options are transferred through RAM ++// which does not have a defined reset value. The EIP-154 master controller ++// keeps reading the PKA_RING_OPTIONS word at start-up until the ‘Signature’ ++// byte contains 0x46 and the ‘Reserved’ field contains zero. ++#define PKA_RING_OPTIONS_SIGNATURE_BYTE 0x46 ++ ++// Order of the result reporting: Two schemas are available: ++// InOrder - This means that the results will be reported in the same order ++// as the commands were provided. ++// OutOfOrder - This means that the results are reported as soon as they are ++// available ++#define PKA_RING_TYPE_IN_ORDER_BIT 1 ++#define PKA_RING_TYPE_OUT_OF_ORDER_BIT 0 ++#define PKA_RING_TYPE_IN_ORDER PKA_RING_TYPE_OUT_OF_ORDER_BIT ++ ++// Byte order of the data written/read to/from Rings. ++// Little Endian (LE) - The least significant bytes have the lowest address. ++// Big Endian (BE) - The most significant bytes come first. ++#define PKA_RING_BYTE_ORDER_LE 0 ++#define PKA_RING_BYTE_ORDER_BE 1 ++#define PKA_RING_BYTE_ORDER PKA_RING_BYTE_ORDER_LE ++ ++// 'trng_clk_on' mask for PKA Clock Switch Forcing Register. Turn on the ++// TRNG clock. When the TRNG is controlled via the Host slave interface, ++// this engine needs to be turned on by setting bit 11. ++#define PKA_CLK_FORCE_TRNG_ON 0x800 ++ ++// Number of TRNG Output registers ++#define PKA_TRNG_OUTPUT_CNT 4 ++ ++// TRNG Configuration ++#define PKA_TRNG_CONFIG_REG_VAL 0x00020008 ++// TRNG Alarm Counter Register Value ++#define PKA_TRNG_ALARMCNT_REG_VAL 0x000200FF ++// TRNG FRO Enable Register Value ++#define PKA_TRNG_FROENABLE_REG_VAL 0x00FFFFFF ++// TRNG Control Register Value; Set bit 10 to start the EIP-76 a.k.a TRNG ++// engine, gathering entropy from the FROs. ++#define PKA_TRNG_CONTROL_REG_VAL 0x00000400 ++ ++// TRNG Control bit ++#define PKA_TRNG_CONTROL_TEST_MODE 0x100 ++ ++// TRNG Control Register Value; Set bit 10 and 12 to start the EIP-76 a.k.a TRNG ++// engine with DRBG enabled, gathering entropy from the FROs. ++#define PKA_TRNG_CONTROL_DRBG_REG_VAL 0x00001400 ++ ++// DRBG enabled TRNG 'request_data' value. REQ_DATA_VAL (in accordance with ++// DATA_BLOCK_MASK) requests 256 blocks of 128-bit random output. ++// 4095 blocks is the max number that can be requested for the TRNG(with DRBG) ++// configuration on Bluefield platforms. ++#define PKA_TRNG_CONTROL_REQ_DATA_VAL 0x10010000 ++ ++// Mask for 'Data Block' in TRNG Control Register. ++#define PKA_TRNG_DRBG_DATA_BLOCK_MASK 0xfff00000 ++ ++// Set bit 12 of TRNG Control Register to enable DRBG functionality. ++#define PKA_TRNG_CONTROL_DRBG_ENABLE_VAL 0x00001000 ++ ++// Set bit 8 a.ka 'test_sp_800_90 DRBG' bit in the TRNG Test Register. ++#define PKA_TRNG_TEST_DRBG_VAL 0x00000080 ++ ++// Number of Personalization String/Additional Input Registers ++#define PKA_TRNG_PS_AI_REG_COUNT 12 ++ ++// DRBG Reseed enable ++#define PKA_TRNG_CONTROL_DRBG_RESEED 0x00008000 ++ ++// TRNG Status bits ++#define PKA_TRNG_STATUS_READY 0x1 ++#define PKA_TRNG_STATUS_SHUTDOWN_OFLO 0x2 ++#define PKA_TRNG_STATUS_TEST_READY 0x100 ++#define PKA_TRNG_STATUS_MONOBIT_FAIL 0x80 ++#define PKA_TRNG_STATUS_RUN_FAIL 0x10 ++#define PKA_TRNG_STATUS_POKER_FAIL 0x40 ++ ++// TRNG Alarm Counter bits ++#define PKA_TRNG_ALARMCNT_STALL_RUN_POKER 0x8000 ++ ++// TRNG Test bits ++#define PKA_TRNG_TEST_KNOWN_NOISE 0x20 ++#define PKA_TRNG_TEST_NOISE 0x2000 ++ ++#endif // __PKA_CONFIG_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_cpu.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_cpu.h +new file mode 100644 +index 000000000..12a368c13 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_cpu.h +@@ -0,0 +1,72 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_CPU_H__ ++#define __PKA_CPU_H__ ++ ++#include ++#include ++ ++#define PKA_AARCH_64 ++#define MAX_CPU_NUMBER 16 // BlueField specific ++ ++#define MEGA 1000000 ++#define GIGA 1000000000 ++ ++#define MS_PER_S 1000 ++#define US_PER_S 1000000 ++#define NS_PER_S 1000000000 ++ ++// Initial guess at our CPU speed. We set this to be larger than any ++// possible real speed, so that any calculated delays will be too long, ++// rather than too short. ++// ++//*Warning: use dummy value for frequency ++//#define CPU_HZ_MAX (2 * GIGA) // Cortex A72 : 2 GHz max -> 2.5 GHz max ++#define CPU_HZ_MAX (1255 * MEGA) // CPU Freq for High/Bin Chip ++ ++// YIELD hints the CPU to switch to another thread if possible ++// and executes as a NOP otherwise. ++#define pka_cpu_yield() ({ asm volatile("yield" : : : "memory"); }) ++// ISB flushes the pipeline, then restarts. This is guaranteed to ++// stall the CPU a number of cycles. ++#define pka_cpu_relax() ({ asm volatile("isb" : : : "memory"); }) ++ ++// Processor speed in hertz; used in routines which might be called very ++// early in boot. ++static inline uint64_t pka_early_cpu_speed(void) ++{ ++ return CPU_HZ_MAX; ++} ++ ++#endif // __PKA_CPU_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_debug.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_debug.h +new file mode 100644 +index 000000000..a44af6eb1 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_debug.h +@@ -0,0 +1,66 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_DEBUG_H__ ++#define __PKA_DEBUG_H__ ++ ++// PKA library bitmask. Use those bits to enable debug messages ++#define PKA_DRIVER 0x0001 ++#define PKA_DEV 0x0002 ++#define PKA_RING 0x0004 ++#define PKA_QUEUE 0x0008 ++#define PKA_MEM 0x0010 ++#define PKA_USER 0x0020 ++#define PKA_TESTS 0x0040 ++// PKA debug mask. This indicates the debug/verbosity level. ++#define PKA_DEBUG_LIB_MASK 0x0040 ++ ++#define PKA_PRINT(lib, fmt, args...) \ ++ ({ pr_info(#lib": "fmt, ##args); }) ++ ++#define PKA_ERROR(lib, fmt, args...) \ ++ ({ pr_err(#lib": %s: error: "fmt, __func__, ##args); }) ++ ++#define PKA_DEBUG(lib, fmt, args...) \ ++ ({ \ ++ if (lib & PKA_DEBUG_LIB_MASK) \ ++ pr_debug(#lib": %s: "fmt, __func__, ##args); \ ++ }) ++ ++#define PKA_PANIC(lib, msg, args...) \ ++ ({ \ ++ pr_info(#lib": %s: panic: "msg, __func__, ##args); \ ++ panic(msg, ##args); \ ++ }) ++ ++#endif // __PKA_DEBUG_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.c b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.c +new file mode 100644 +index 000000000..c90c70134 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.c +@@ -0,0 +1,2414 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mlxbf_pka_dev.h" ++ ++#define BYTES_PER_WORD 4 ++#define BYTES_PER_DOUBLE_WORD 8 ++ ++// Personalization string "NVIDIA-MELLANOX-BLUEFIELD-TRUE_RANDOM_NUMBER_GEN" ++uint32_t pka_trng_drbg_ps_str[] = ++{ ++ 0x4e564944, 0x49412d4d, 0x454c4c41, 0x4e4f582d, ++ 0x424c5545, 0x4649454c, 0x442d5452, 0x55455f52, ++ 0x414e444f, 0x4d5f4e55, 0x4d424552, 0x5f47454e ++}; ++ ++// Personalization string for DRBG test ++uint32_t pka_trng_drbg_test_ps_str[] = ++{ ++ 0x64299d83, 0xc34d7098, 0x5bd1f51d, 0xddccfdc1, ++ 0xdd0455b7, 0x166279e5, 0x0974cb1b, 0x2f2cd100, ++ 0x59a5060a, 0xca79940d, 0xd4e29a40, 0x56b7b779 ++}; ++ ++// First Entropy string for DRBG test ++uint32_t pka_trng_drbg_test_etpy_str1[] = ++{ ++ 0xaa6bbcab, 0xef45e339, 0x136ca1e7, 0xbce1c881, ++ 0x9fa37b09, 0x63b53667, 0xb36e0053, 0xa202ed81, ++ 0x4650d90d, 0x8eed6127, 0x666f2402, 0x0dfd3af9 ++}; ++ ++// Second Entropy string for DRBG test ++uint32_t pka_trng_drbg_test_etpy_str2[] = ++{ ++ 0x35c1b7a1, 0x0154c52b, 0xd5777390, 0x226a4fdb, ++ 0x5f16080d, 0x06b68369, 0xd0c93d00, 0x3336e27f, ++ 0x1abf2c37, 0xe6ab006c, 0xa4adc6e1, 0x8e1907a2 ++}; ++ ++// Known answer for DRBG test ++uint32_t pka_trng_drbg_test_output[] = ++{ ++ 0xb663b9f1, 0x24943e13, 0x80f7dce5, 0xaba1a16f ++}; ++ ++pka_dev_gbl_config_t pka_gbl_config; ++ ++// Global PKA shim resource info table ++static pka_dev_gbl_shim_res_info_t pka_gbl_res_tbl[PKA_MAX_NUM_IO_BLOCKS]; ++ ++// Start a PKA device timer. ++static uint64_t pka_dev_timer_start(uint32_t usec) ++{ ++ uint64_t cur_time = get_cycles(); ++ return (cur_time + (pka_early_cpu_speed() * usec) / 1000000ULL); ++} ++ ++// Test a PKA device timer for completion. ++static int pka_dev_timer_done(uint64_t timer) ++{ ++ return (get_cycles() >= timer); ++} ++ ++// Return register base address ++static uint64_t pka_dev_get_register_base(uint64_t base, uint64_t reg_addr) ++{ ++ return (base + reg_addr) & PAGE_MASK; ++} ++ ++// Return register offset ++static uint64_t pka_dev_get_register_offset(uint64_t base, uint64_t reg_addr) ++{ ++ return (base + reg_addr) & ~PAGE_MASK; ++} ++ ++// Return word offset within io memory ++static uint64_t pka_dev_get_word_offset(uint64_t mem_base, uint64_t word_addr, ++ uint64_t mem_size) ++{ ++ return (mem_base + word_addr) & (mem_size - 1); ++} ++ ++static uint64_t pka_dev_io_read(void *mem_ptr, uint64_t mem_off) ++{ ++ uint64_t data; ++ ++ data = pka_mmio_read(mem_ptr + mem_off); ++ ++ return data; ++} ++ ++static void pka_dev_io_write(void *mem_ptr, uint64_t mem_off, uint64_t value) ++{ ++ pka_mmio_write(mem_ptr + mem_off, value); ++} ++ ++// Add the resource to the global resource table ++static int pka_dev_add_resource(pka_dev_res_t *res_ptr, uint32_t shim_idx) ++{ ++ uint8_t res_cnt; ++ ++ res_cnt = pka_gbl_res_tbl[shim_idx].res_cnt; ++ ++ if (res_cnt >= PKA_DEV_SHIM_RES_CNT) ++ return -ENOMEM; ++ ++ pka_gbl_res_tbl[shim_idx].res_tbl[res_cnt] = res_ptr; ++ pka_gbl_res_tbl[shim_idx].res_cnt++; ++ ++ return 0; ++} ++ ++// Remove the resource from the global resource table ++static int pka_dev_put_resource(pka_dev_res_t *res, uint32_t shim_idx) ++{ ++ pka_dev_res_t *res_ptr; ++ uint8_t res_idx; ++ ++ for (res_idx = 0; res_idx < PKA_DEV_SHIM_RES_CNT; res_idx++) ++ { ++ res_ptr = pka_gbl_res_tbl[shim_idx].res_tbl[res_idx]; ++ if (res_ptr && strcmp(res_ptr->name, res->name) == 0) ++ { ++ pka_gbl_res_tbl[shim_idx].res_tbl[res_idx] = NULL; ++ pka_gbl_res_tbl[shim_idx].res_cnt--; ++ break; ++ } ++ } ++ ++ // Check whether the resource shares the same memory map; If so, ++ // the memory map shouldn't be released. ++ for (res_idx = 0; res_idx < PKA_DEV_SHIM_RES_CNT; res_idx++) ++ { ++ res_ptr = pka_gbl_res_tbl[shim_idx].res_tbl[res_idx]; ++ if (res_ptr && (res_ptr->base == res->base)) ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static void* pka_dev_get_resource_ioaddr(uint64_t res_base, uint32_t shim_idx) ++{ ++ pka_dev_res_t *res_ptr; ++ uint8_t res_cnt, res_idx; ++ ++ res_cnt = pka_gbl_res_tbl[shim_idx].res_cnt; ++ ++ if (res_cnt == 0) ++ return NULL; ++ ++ for (res_idx = 0; res_idx < res_cnt; res_idx++) ++ { ++ res_ptr = pka_gbl_res_tbl[shim_idx].res_tbl[res_idx]; ++ if (res_ptr->base == res_base) ++ return res_ptr->ioaddr; ++ } ++ ++ return NULL; ++} ++ ++// Set PKA device resource config - - map io memory if needed. ++static int pka_dev_set_resource_config(pka_dev_shim_t *shim, ++ pka_dev_res_t *res_ptr, ++ uint64_t res_base, ++ uint64_t res_size, ++ uint64_t res_type, ++ char *res_name) ++{ ++ int ret = 0; ++ ++ if (res_ptr->status == PKA_DEV_RES_STATUS_MAPPED) ++ return -EPERM; ++ ++ if (res_type == PKA_DEV_RES_TYPE_REG) ++ res_ptr->base = res_base; ++ ++ if (res_type == PKA_DEV_RES_TYPE_MEM) ++ res_ptr->base = shim->mem_res.eip154_base + res_base; ++ ++ res_ptr->size = res_size; ++ res_ptr->type = res_type; ++ res_ptr->name = res_name; ++ res_ptr->status = PKA_DEV_RES_STATUS_UNMAPPED; ++ res_ptr->ioaddr = pka_dev_get_resource_ioaddr(res_ptr->base, ++ shim->shim_id); ++ if (!res_ptr->ioaddr) ++ { ++ if (!request_mem_region(res_ptr->base, res_ptr->size, res_ptr->name)) ++ { ++ PKA_ERROR(PKA_DEV, "failed to get io memory region\n"); ++ return -EPERM; ++ } ++ ++ res_ptr->ioaddr = ioremap(res_ptr->base, res_ptr->size); ++ } ++ ++ res_ptr->status = PKA_DEV_RES_STATUS_MAPPED; ++ ++ if (!res_ptr->ioaddr || pka_dev_add_resource(res_ptr, shim->shim_id)) ++ { ++ PKA_ERROR(PKA_DEV, "unable to map io memory\n"); ++ release_mem_region(res_ptr->base, res_ptr->size); ++ return -ENOMEM; ++ } ++ return ret; ++} ++ ++// Unset PKA device resource config - unmap io memory if needed. ++static void pka_dev_unset_resource_config(pka_dev_shim_t *shim, ++ pka_dev_res_t *res_ptr) ++{ ++ int ret = -EBUSY; ++ ++ if (res_ptr->status != PKA_DEV_RES_STATUS_MAPPED) ++ return; ++ ++ if (res_ptr->ioaddr && ++ ret != pka_dev_put_resource(res_ptr, shim->shim_id)) ++ { ++ iounmap(res_ptr->ioaddr); ++ release_mem_region(res_ptr->base, res_ptr->size); ++ } ++ ++ res_ptr->status = PKA_DEV_RES_STATUS_UNMAPPED; ++} ++ ++int pka_dev_clear_ring_counters(pka_dev_ring_t *ring) ++{ ++ pka_dev_shim_t *shim; ++ pka_dev_res_t *master_seq_ctrl_ptr; ++ void *master_reg_ptr; ++ uint64_t master_reg_base, master_reg_off; ++ ++ shim = ring->shim; ++ master_seq_ctrl_ptr = &shim->resources.master_seq_ctrl; ++ master_reg_base = master_seq_ctrl_ptr->base; ++ master_reg_ptr = master_seq_ctrl_ptr->ioaddr; ++ master_reg_off = pka_dev_get_register_offset(master_reg_base, ++ PKA_MASTER_SEQ_CTRL_ADDR); ++ ++ // push the EIP-154 master controller into reset. ++ pka_dev_io_write(master_reg_ptr, master_reg_off, ++ PKA_MASTER_SEQ_CTRL_RESET_VAL); ++ ++ // clear counters. ++ pka_dev_io_write(master_reg_ptr, master_reg_off, ++ PKA_MASTER_SEQ_CTRL_CLEAR_COUNTERS_VAL); ++ ++ // take the EIP-154 master controller out of reset. ++ pka_dev_io_write(master_reg_ptr, master_reg_off, 0); ++ ++ return 0; ++} ++ ++// Initialize ring. Set ring parameters and configure ring resources. ++// It returns 0 on success, a negative error code on failure. ++static int pka_dev_init_ring(pka_dev_ring_t *ring, uint32_t ring_id, ++ pka_dev_shim_t *shim) ++{ ++ int ret = 0; ++ ++ pka_dev_res_t *ring_info_words_ptr; ++ pka_dev_res_t *ring_counters_ptr; ++ pka_dev_res_t *ring_window_ram_ptr; ++ ++ uint32_t ring_words_off; ++ uint32_t ring_cntrs_off; ++ uint32_t ring_mem_off; ++ uint32_t ring_mem_base; ++ ++ uint32_t shim_ring_id; ++ uint8_t window_ram_split; ++ ++ if (ring->status != PKA_DEV_RING_STATUS_UNDEFINED) ++ { ++ PKA_ERROR(PKA_DEV, "PKA ring must be undefined\n"); ++ return -EPERM; ++ } ++ ++ if (ring_id > PKA_MAX_NUM_RINGS - 1) ++ { ++ PKA_ERROR(PKA_DEV, "invalid ring identifier\n"); ++ return -EINVAL; ++ } ++ ++ ring->ring_id = ring_id; ++ ring->shim = shim; ++ ring->resources_num = PKA_MAX_NUM_RING_RESOURCES; ++ ++ shim_ring_id = ring_id % PKA_MAX_NUM_IO_BLOCK_RINGS; ++ shim->rings[shim_ring_id] = ring; ++ ++ // Configure ring information control/status words resource ++ ring_info_words_ptr = &ring->resources.info_words; ++ ring_words_off = shim_ring_id * PKA_RING_WORDS_SPACING; ++ ring_info_words_ptr->base = ring_words_off + shim->mem_res.eip154_base + ++ PKA_RING_WORDS_ADDR; ++ ring_info_words_ptr->size = PKA_RING_WORDS_SIZE; ++ ring_info_words_ptr->type = PKA_DEV_RES_TYPE_MEM; ++ ring_info_words_ptr->status = PKA_DEV_RES_STATUS_UNMAPPED; ++ ring_info_words_ptr->name = "PKA_RING_INFO"; ++ ++ // Configure ring counters registers resource ++ ring_counters_ptr = &ring->resources.counters; ++ ring_cntrs_off = shim_ring_id * PKA_RING_CNTRS_SPACING; ++ ring_counters_ptr->base = ring_cntrs_off + shim->mem_res.eip154_base + ++ PKA_RING_CNTRS_ADDR; ++ ring_counters_ptr->size = PKA_RING_CNTRS_SIZE; ++ ring_counters_ptr->type = PKA_DEV_RES_TYPE_REG; ++ ring_counters_ptr->status = PKA_DEV_RES_STATUS_UNMAPPED; ++ ring_counters_ptr->name = "PKA_RING_CNTRS"; ++ ++ // Configure ring window RAM resource ++ window_ram_split = shim->window_ram_split; ++ if (window_ram_split == PKA_SHIM_WINDOW_RAM_SPLIT_ENABLED) ++ { ++ ring_mem_off = shim_ring_id * PKA_RING_MEM_1_SPACING; ++ ring_mem_base = ring_mem_off + shim->mem_res.alt_wndw_ram_0_base; ++ } ++ else ++ { ++ ring_mem_off = shim_ring_id * PKA_RING_MEM_0_SPACING; ++ ring_mem_base = ring_mem_off + shim->mem_res.wndw_ram_base; ++ } ++ ++ ring_window_ram_ptr = &ring->resources.window_ram; ++ ring_window_ram_ptr->base = ring_mem_base; ++ ring_window_ram_ptr->size = PKA_RING_MEM_SIZE; ++ ring_window_ram_ptr->type = PKA_DEV_RES_TYPE_MEM; ++ ring_window_ram_ptr->status = PKA_DEV_RES_STATUS_UNMAPPED; ++ ring_window_ram_ptr->name = "PKA_RING_WINDOW"; ++ ++ ring->ring_info = kzalloc(sizeof(pka_dev_hw_ring_info_t), GFP_KERNEL); ++ if (!ring->ring_info) ++ { ++ PKA_ERROR(PKA_DEV, "unable to kmalloc\n"); ++ kfree(ring->ring_info); ++ return -ENOMEM; ++ } ++ ++ mutex_init(&ring->mutex); ++ ring->status = PKA_DEV_RING_STATUS_INITIALIZED; ++ ++ return ret; ++} ++ ++// Release a given Ring. ++static int pka_dev_release_ring(pka_dev_ring_t *ring) ++{ ++ int ret = 0; ++ ++ pka_dev_shim_t *shim; ++ uint32_t shim_ring_id; ++ ++ if (ring->status == PKA_DEV_RING_STATUS_UNDEFINED) ++ return ret; ++ ++ if (ring->status == PKA_DEV_RING_STATUS_BUSY) ++ { ++ PKA_ERROR(PKA_DEV, "PKA ring is busy\n"); ++ return -EBUSY; ++ } ++ ++ shim = ring->shim; ++ ++ if (shim->status == PKA_SHIM_STATUS_RUNNING) ++ { ++ PKA_ERROR(PKA_DEV, "PKA shim is running\n"); ++ return -EPERM; ++ } ++ ++ pka_dev_unset_resource_config(shim, &ring->resources.info_words); ++ pka_dev_unset_resource_config(shim, &ring->resources.counters); ++ pka_dev_unset_resource_config(shim, &ring->resources.window_ram); ++ ++ kfree(ring->ring_info); ++ ++ ring->status = PKA_DEV_RING_STATUS_UNDEFINED; ++ shim_ring_id = ring->ring_id % PKA_MAX_NUM_IO_BLOCK_RINGS; ++ shim->rings[shim_ring_id] = NULL; ++ shim->rings_num--; ++ ++ return ret; ++} ++ ++// Partition the window RAM for a given PKA ring. Here we statically divide ++// the 16K memory region into three partitions: First partition is reserved ++// for command descriptor ring (1K), second partition is reserved for result ++// descriptor ring (1K), and the remaining 14K are reserved for vector data. ++// Through this memroy partition scheme, command/result descriptor rings hold ++// a total of 1KB/64B = 16 descriptors each. The adresses for the rings start ++// at offset 0x3800. Also note that it is possible to have rings full while ++// the vector data can support more data, the opposite can also happen, but ++// it is not suitable. For instance ECC point multiplication requires 8 input ++// vectors and 2 output vectors, a total of 10 vectors. If each vector has a ++// length of 24 words (24x4B = 96B), we can process 14KB/960B = 14 operations ++// which is close to 16 the total descriptors supported by rings. On the other ++// hand, using 12K vector data region, allows to process only 12 operations, ++// while rings can hold 32 descriptors (ring usage is significantly low). ++// For ECDSA verify, we have 12 vectors which require 1152B, with 14KB we can ++// handle 12 operations, against 10 operations with 12KB vector data memory. ++// We believe that the aformentionned memory partition help us to leverage ++// the trade-off between supported descriptors and required vectors. Note ++// that these examples gives approximative values and does not include buffer ++// word padding across vectors. ++// ++// The function also writes the result descriptor rings base addresses, size ++// and type, and initialize the read and write pointers and statistics. It ++// returns 0 on success, a negative error code on failure. ++// ++// This function must be called once per ring, at initialization before any ++// other fonctions are called. ++static int pka_dev_partition_mem(pka_dev_ring_t *ring) ++{ ++ int ret = 0; ++ ++ pka_dev_shim_t *shim; ++ pka_dev_hw_ring_info_t *ring_info; ++ ++ uint32_t ring_mem_base; ++ uint32_t ring_mem_size; ++ uint32_t data_mem_base; ++ uint32_t data_mem_size; ++ ++ uint64_t cmd_desc_ring_base; ++ uint32_t cmd_desc_ring_size; ++ uint64_t rslt_desc_ring_base; ++ uint32_t rslt_desc_ring_size; ++ ++ uint16_t num_cmd_desc; ++ uint16_t host_desc_size; ++ uint8_t ring_in_order; ++ ++ uint64_t window_ram_base; ++ uint64_t window_ram_size; ++ ++ shim = ring->shim; ++ ++ if (!ring->shim || ++ ring->status != PKA_DEV_RING_STATUS_INITIALIZED) ++ return -EPERM; ++ ++ ring_in_order = shim->ring_type; ++ window_ram_base = ring->resources.window_ram.base; ++ window_ram_size = ring->resources.window_ram.size; ++ // Partition ring memory. Give ring pair (cmmd descriptor ring and rslt ++ // descriptor ring) an equal portion of the memory. The cmmd descriptor ++ // ring and result descriptor ring are used as "non-overlapping" ring. ++ // Currently set aside 1/8 of the window RAM for command/result descriptor ++ // rings - giving a total of 1K/64B = 16 descriptors per ring. ++ // The remaining memory is "Data Memory" - i.e. memory to hold the command ++ // operands and results - also called input/output vectors (in all cases ++ // these vectors are just single large integers - often in the range of ++ // hundreds to thousands of bits long). ++ ring_mem_size = PKA_WINDOW_RAM_RING_MEM_SIZE / 2; ++ data_mem_size = PKA_WINDOW_RAM_DATA_MEM_SIZE; ++ data_mem_base = window_ram_base; ++ ring_mem_base = data_mem_base + data_mem_size; ++ ++ num_cmd_desc = ring_mem_size / CMD_DESC_SIZE; ++ host_desc_size = CMD_DESC_SIZE / BYTES_PER_WORD; ++ ++ cmd_desc_ring_size = num_cmd_desc * CMD_DESC_SIZE; ++ rslt_desc_ring_size = cmd_desc_ring_size; ++ ++ ring->num_cmd_desc = num_cmd_desc; ++ ++ // The command and result descriptor rings may be placed at different ++ // (non-overlapping) locations in Window RAM memory space. PKI command ++ // interface: Most of the functionality is defined by the EIP-154 master ++ // firmware on the EIP-154 master controller Sequencer. ++ cmd_desc_ring_base = ring_mem_base; ++ rslt_desc_ring_base = ring_mem_base + cmd_desc_ring_size; ++ ++ cmd_desc_ring_base = ++ PKA_RING_MEM_ADDR(window_ram_base, shim->mem_res.wndw_ram_off_mask, ++ cmd_desc_ring_base, window_ram_size); ++ rslt_desc_ring_base = ++ PKA_RING_MEM_ADDR(window_ram_base, shim->mem_res.wndw_ram_off_mask, ++ rslt_desc_ring_base, window_ram_size); ++ ++ ring_info = ring->ring_info; ++ // Fill ring information. ++ ring_info->cmmd_base = cmd_desc_ring_base; ++ ring_info->rslt_base = rslt_desc_ring_base; ++ ring_info->size = num_cmd_desc - 1; ++ ring_info->host_desc_size = host_desc_size; ++ ring_info->in_order = ring_in_order; ++ ring_info->cmmd_rd_ptr = 0x0; ++ ring_info->rslt_wr_ptr = 0x0; ++ ring_info->cmmd_rd_stats = 0x0; ++ ring_info->rslt_wr_stats = 0x0; ++ ++ return ret; ++} ++ ++// Write the ring base address, ring size and type, and initialize (clear) ++// the read and write pointers and statistics. ++static int pka_dev_write_ring_info(pka_dev_res_t *buffer_ram_ptr, ++ uint8_t ring_id, ++ uint32_t ring_cmmd_base_val, ++ uint32_t ring_rslt_base_val, ++ uint32_t ring_size_type_val) ++{ ++ uint32_t ring_spacing; ++ uint64_t word_off; ++ int ret = 0; ++ ++ if (buffer_ram_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ buffer_ram_ptr->type != PKA_DEV_RES_TYPE_MEM) ++ return -EPERM; ++ ++ PKA_DEBUG(PKA_DEV, "Writing ring information control/status words\n"); ++ ++ ring_spacing = ring_id * PKA_RING_WORDS_SPACING; ++ ++ // Write the command ring base address that the EIP-154 ++ // master firmware uses with the command ring read pointer ++ // to get command descriptors from the Host ring. After the ++ // initialization, although the word is writeable it should ++ // be regarded as read-only. ++ word_off = pka_dev_get_word_offset(buffer_ram_ptr->base, ++ RING_CMMD_BASE_0_ADDR + ring_spacing, ++ PKA_BUFFER_RAM_SIZE); ++ pka_dev_io_write(buffer_ram_ptr->ioaddr, word_off, ring_cmmd_base_val); ++ ++ // Write the result ring base address that the EIP-154 ++ // master firmware uses with the result ring write pointer ++ // to put the result descriptors in the Host ring. After ++ // the initialization, although the word is writeable it ++ // should be regarded as read-only. ++ word_off = pka_dev_get_word_offset(buffer_ram_ptr->base, ++ RING_RSLT_BASE_0_ADDR + ring_spacing, ++ PKA_BUFFER_RAM_SIZE); ++ pka_dev_io_write(buffer_ram_ptr->ioaddr, word_off, ring_rslt_base_val); ++ ++ // Write the ring size (number of descriptors), the size of ++ // the descriptor and the result reporting scheme. After the ++ // initialization, although the word is writeable it should ++ // be regarded as read-only. ++ word_off = pka_dev_get_word_offset(buffer_ram_ptr->base, ++ RING_SIZE_TYPE_0_ADDR + ring_spacing, ++ PKA_BUFFER_RAM_SIZE); ++ pka_dev_io_write(buffer_ram_ptr->ioaddr, word_off, ring_size_type_val); ++ ++ // Write the command and result ring indices that the EIP-154 ++ // master firmware uses. This word should be written with zero ++ // when the ring information is initialized. After the ++ // initialization, although the word is writeable it should be ++ // regarded as read-only. ++ word_off = pka_dev_get_word_offset(buffer_ram_ptr->base, ++ RING_RW_PTRS_0_ADDR + ring_spacing, ++ PKA_BUFFER_RAM_SIZE); ++ pka_dev_io_write(buffer_ram_ptr->ioaddr, word_off, 0); ++ ++ // Write the ring statistics (two 16-bit counters, one for ++ // commands and one for results) from EIP-154 master firmware ++ // point of view. This word should be written with zero when ++ // the ring information is initialized. After the initializa- ++ // -tion, although the word is writeable it should be regarded ++ // as read-only. ++ word_off = pka_dev_get_word_offset(buffer_ram_ptr->base, ++ RING_RW_STAT_0_ADDR + ring_spacing, ++ PKA_BUFFER_RAM_SIZE); ++ pka_dev_io_write(buffer_ram_ptr->ioaddr, word_off, 0); ++ ++ return ret; ++} ++ ++// Set up the control/status words. Upon a PKI command the EIP-154 master ++// firmware will read and partially update the ring information. ++static int pka_dev_set_ring_info(pka_dev_ring_t *ring) ++{ ++ int ret = 0; ++ ++ pka_dev_shim_t *shim; ++ pka_dev_hw_ring_info_t *ring_info; ++ pka_dev_res_t *buffer_ram_ptr; ++ ++ uint32_t ring_cmmd_base_val; ++ uint32_t ring_rslt_base_val; ++ uint32_t ring_size_type_val; ++ ++ uint8_t ring_id; ++ ++ shim = ring->shim; ++ // Ring info configuration MUST be done when the PKA ring ++ // is initilaized. ++ if ((shim->status != PKA_SHIM_STATUS_INITIALIZED && ++ shim->status != PKA_SHIM_STATUS_RUNNING && ++ shim->status != PKA_SHIM_STATUS_STOPPED) || ++ ring->status != PKA_DEV_RING_STATUS_INITIALIZED) ++ return -EPERM; ++ ++ ring_id = ring->ring_id % PKA_MAX_NUM_IO_BLOCK_RINGS; ++ ++ // Partition ring memory. ++ ret = pka_dev_partition_mem(ring); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to initialize ring memory\n"); ++ return ret; ++ } ++ ++ // Fill ring infomation. ++ ring_info = ring->ring_info; ++ ++ ring_cmmd_base_val = ring_info->cmmd_base; ++ ring_rslt_base_val = ring_info->rslt_base; ++ ++ ring_size_type_val = (ring_info->in_order & 0x0001) << 31; ++ ring_size_type_val |= (ring_info->host_desc_size & 0x03FF) << 18; ++ ring_size_type_val |= (ring->num_cmd_desc - 1) & 0xFFFF; ++ ++ buffer_ram_ptr = &shim->resources.buffer_ram; ++ // Write ring information status/control words in the PKA Buffer RAM ++ ret = pka_dev_write_ring_info(buffer_ram_ptr, ring_id, ring_cmmd_base_val, ++ ring_rslt_base_val, ring_size_type_val); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to wirte ring information\n"); ++ return ret; ++ } ++ ++ ring->status = PKA_DEV_RING_STATUS_READY; ++ ++ return ret; ++} ++ ++// Create shim. Set shim parameters and configure shim resources. ++// It returns 0 on success, a negative error code on failure. ++static int pka_dev_create_shim(pka_dev_shim_t *shim, uint32_t shim_id, ++ uint8_t split, struct pka_dev_mem_res *mem_res) ++{ ++ int ret = 0; ++ ++ uint64_t reg_base; ++ uint64_t reg_size; ++ ++ if (shim->status == PKA_SHIM_STATUS_CREATED) ++ return ret; ++ ++ if (shim->status != PKA_SHIM_STATUS_UNDEFINED) ++ { ++ PKA_ERROR(PKA_DEV, "PKA device must be undefined\n"); ++ return -EPERM; ++ } ++ ++ if (shim_id > PKA_MAX_NUM_IO_BLOCKS - 1) ++ { ++ PKA_ERROR(PKA_DEV, "invalid shim identifier\n"); ++ return -EINVAL; ++ } ++ ++ shim->shim_id = shim_id; ++ shim->mem_res = *mem_res; ++ ++ if (split) ++ shim->window_ram_split = PKA_SHIM_WINDOW_RAM_SPLIT_ENABLED; ++ else ++ shim->window_ram_split = PKA_SHIM_WINDOW_RAM_SPLIT_DISABLED; ++ ++ shim->ring_type = PKA_RING_TYPE_IN_ORDER; ++ shim->ring_priority = PKA_RING_OPTIONS_PRIORITY; ++ shim->rings_num = PKA_MAX_NUM_IO_BLOCK_RINGS; ++ shim->rings = kzalloc(sizeof(pka_dev_ring_t) * shim->rings_num, ++ GFP_KERNEL); ++ if (!shim->rings) ++ { ++ PKA_ERROR(PKA_DEV, "unable to kmalloc\n"); ++ return -ENOMEM; ++ } ++ ++ // Set PKA device Buffer RAM config ++ ret = pka_dev_set_resource_config(shim, &shim->resources.buffer_ram, ++ PKA_BUFFER_RAM_BASE, ++ PKA_BUFFER_RAM_SIZE, ++ PKA_DEV_RES_TYPE_MEM, ++ "PKA_BUFFER_RAM"); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "unable to set Buffer RAM config\n"); ++ return ret; ++ } ++ ++ // Set PKA device Master Program RAM config ++ ret = pka_dev_set_resource_config(shim, &shim->resources.master_prog_ram, ++ PKA_MASTER_PROG_RAM_BASE, ++ PKA_MASTER_PROG_RAM_SIZE, ++ PKA_DEV_RES_TYPE_MEM, ++ "PKA_MASTER_PROG_RAM"); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "unable to set Master Program RAM config\n"); ++ return ret; ++ } ++ ++ // Set PKA device Master Controller register ++ reg_size = PAGE_SIZE; ++ reg_base = pka_dev_get_register_base(shim->mem_res.eip154_base, ++ PKA_MASTER_SEQ_CTRL_ADDR); ++ ret = pka_dev_set_resource_config(shim, &shim->resources.master_seq_ctrl, ++ reg_base, reg_size, ++ PKA_DEV_RES_TYPE_REG, ++ "PKA_MASTER_SEQ_CTRL"); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "unable to set Master Controller register " ++ "config\n"); ++ return ret; ++ } ++ ++ // Set PKA device AIC registers ++ reg_size = PAGE_SIZE; ++ reg_base = pka_dev_get_register_base(shim->mem_res.eip154_base, ++ AIC_POL_CTRL_ADDR); ++ ret = pka_dev_set_resource_config(shim, &shim->resources.aic_csr, ++ reg_base, reg_size, ++ PKA_DEV_RES_TYPE_REG, ++ "PKA_AIC_CSR"); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "unable to set AIC registers config\n"); ++ return ret; ++ } ++ ++ // Set PKA device TRNG registers ++ reg_size = PAGE_SIZE; ++ reg_base = pka_dev_get_register_base(shim->mem_res.eip154_base, ++ TRNG_OUTPUT_0_ADDR); ++ ret = pka_dev_set_resource_config(shim, &shim->resources.trng_csr, ++ reg_base, reg_size, ++ PKA_DEV_RES_TYPE_REG, ++ "PKA_TRNG_CSR"); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "unable to setup the TRNG\n"); ++ return ret; ++ } ++ ++ // Set PKA device 'glue' logic registers ++ reg_size = PAGE_SIZE; ++ reg_base = pka_dev_get_register_base(shim->mem_res.csr_base, ++ PKA_INT_MASK_ADDR); ++ ret = pka_dev_set_resource_config(shim, &shim->resources.ext_csr, ++ reg_base, reg_size, ++ PKA_DEV_RES_TYPE_REG, ++ "PKA_EXT_CSR"); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "unable to setup the MiCA specific registers\n"); ++ return ret; ++ } ++ ++ shim->status = PKA_SHIM_STATUS_CREATED; ++ ++ return ret; ++} ++ ++// Delete shim and unset shim resources. ++static int pka_dev_delete_shim(pka_dev_shim_t *shim) ++{ ++ int ret = 0; ++ pka_dev_res_t *res_buffer_ram, *res_master_prog_ram; ++ pka_dev_res_t *res_master_seq_ctrl, *res_aic_csr, *res_trng_csr; ++ ++ PKA_DEBUG(PKA_DEV, "PKA device delete shim\n"); ++ ++ if (shim->status == PKA_SHIM_STATUS_UNDEFINED) ++ return ret; ++ ++ if (shim->status != PKA_SHIM_STATUS_FINALIZED && ++ shim->status != PKA_SHIM_STATUS_CREATED) ++ { ++ PKA_ERROR(PKA_DEV, "PKA device status must be finalized\n"); ++ return -EPERM; ++ } ++ ++ res_buffer_ram = &shim->resources.buffer_ram; ++ res_master_prog_ram = &shim->resources.master_prog_ram; ++ res_master_seq_ctrl = &shim->resources.master_seq_ctrl; ++ res_aic_csr = &shim->resources.aic_csr; ++ res_trng_csr = &shim->resources.trng_csr; ++ ++ pka_dev_unset_resource_config(shim, res_buffer_ram); ++ pka_dev_unset_resource_config(shim, res_master_prog_ram); ++ pka_dev_unset_resource_config(shim, res_master_seq_ctrl); ++ pka_dev_unset_resource_config(shim, res_aic_csr); ++ pka_dev_unset_resource_config(shim, res_trng_csr); ++ ++ kfree(shim->rings); ++ ++ shim->status = PKA_SHIM_STATUS_UNDEFINED; ++ ++ return ret; ++} ++ ++static int pka_dev_config_aic_interrupts(pka_dev_res_t *aic_csr_ptr) ++{ ++ int ret = 0; ++ ++ uint64_t csr_reg_base, csr_reg_off; ++ void *csr_reg_ptr; ++ ++ if (aic_csr_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ aic_csr_ptr->type != PKA_DEV_RES_TYPE_REG) ++ return -EPERM; ++ ++ PKA_DEBUG(PKA_DEV, "configure the AIC so that all interrupts " ++ "are properly recognized\n"); ++ ++ csr_reg_base = aic_csr_ptr->base; ++ csr_reg_ptr = aic_csr_ptr->ioaddr; ++ ++ // Configure the signal polarity for each interrupt. ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, AIC_POL_CTRL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_AIC_POL_CTRL_REG_VAL); ++ ++ // Configure the signal type for each interrupt ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, AIC_TYPE_CTRL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_AIC_TYPE_CTRL_REG_VAL); ++ ++ // Set the enable control register ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, AIC_ENABLE_CTRL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_AIC_ENABLE_CTRL_REG_VAL); ++ ++ // Set the enabled status register ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, AIC_ENABLED_STAT_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_AIC_ENABLE_STAT_REG_VAL); ++ ++ // *TBD* Write PKA_INT_MASK_RESET with 1's for each interrupt bit ++ // to allow them to propagate out the interrupt controller. ++ // EIP-154 interrupts can still be programmed and observed via polling ++ // regardless of whether PKA_INT_MASK is masking out the interrupts or ++ // not. The mask is for system propagation, i.e. propagate to the GIC. ++ // Bit positions are as follows: ++ // Bit 10 - parity_error_irq (non EIP-154 interrupt) ++ // Bit 9 - trng_irq ++ // Bit 8 - pka_master_irq ++ // Bits 7:4 - pka_queue_*_result_irq ++ // Bits 3:0 - pka_queue_*_empty_irq ++ ++ return ret; ++} ++ ++static int pka_dev_load_image(pka_dev_res_t *res_ptr, const uint32_t *data_buf, ++ uint32_t size) ++{ ++ uint64_t data_rd; ++ int mismatches; ++ int i, j, ret = 0; ++ ++ if (res_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ res_ptr->type != PKA_DEV_RES_TYPE_MEM) ++ return -EPERM; ++ ++ // Note that the image size is in word of 4 bytes and memory 'writes' ++ // are 8 bytes aligned, thus the memory start address and end address ++ // are shifted. ++ if (res_ptr->size < (size * BYTES_PER_WORD) << 1) ++ { ++ PKA_ERROR(PKA_DEV, "image size greater than memory size\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0, j = 0; i < size; i++, j += BYTES_PER_DOUBLE_WORD) ++ pka_dev_io_write(res_ptr->ioaddr, j, ++ (uint64_t) data_buf[i]); ++ ++ mismatches = 0; ++ PKA_DEBUG(PKA_DEV, "PKA DEV: verifying image (%u words)\n", size); ++ for (i = 0, j = 0; i < size; i++, j += BYTES_PER_DOUBLE_WORD) ++ { ++ data_rd = pka_dev_io_read(res_ptr->ioaddr, j); ++ if (data_rd != (uint64_t) data_buf[i]) ++ { ++ mismatches += 1; ++ PKA_DEBUG(PKA_DEV, "error while loading image: " ++ "addr:0x%llx expected data: 0x%x actual data: 0x%llx\n", ++ res_ptr->base + j, ++ data_buf[i], data_rd); ++ } ++ } ++ ++ if (mismatches > 0) ++ { ++ PKA_PANIC(PKA_DEV, "error while loading image: mismatches: %d\n", ++ mismatches); ++ return -EAGAIN; ++ } ++ ++ return ret; ++} ++ ++static int ++pka_dev_config_master_seq_controller(pka_dev_shim_t *shim, ++ pka_dev_res_t *master_seq_ctrl_ptr) ++{ ++ pka_dev_res_t *aic_csr_ptr, *master_prog_ram; ++ void *aic_reg_ptr, *master_reg_ptr; ++ ++ uint64_t aic_reg_base, aic_reg_off; ++ uint64_t master_reg_base, master_reg_off; ++ ++ const uint32_t *boot_img_ptr, *master_img_ptr; ++ uint32_t boot_img_size, master_img_size; ++ ++ uint32_t pka_master_irq; ++ ++ uint64_t timer; ++ uint8_t status_bits; ++ uint8_t shim_fw_id; ++ int ret = 0; ++ ++ if (master_seq_ctrl_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ master_seq_ctrl_ptr->type != PKA_DEV_RES_TYPE_REG) ++ return -EPERM; ++ ++ master_reg_base = master_seq_ctrl_ptr->base; ++ master_reg_ptr = master_seq_ctrl_ptr->ioaddr; ++ master_reg_off = pka_dev_get_register_offset(master_reg_base, ++ PKA_MASTER_SEQ_CTRL_ADDR); ++ ++ PKA_DEBUG(PKA_DEV, "push the EIP-154 master controller into reset\n"); ++ pka_dev_io_write(master_reg_ptr, master_reg_off, ++ PKA_MASTER_SEQ_CTRL_RESET_VAL); ++ ++ shim_fw_id = pka_firmware_get_id(); ++ ++ // Load boot image into PKA_MASTER_PROG_RAM ++ boot_img_size = pka_firmware_array[shim_fw_id].boot_img_size; ++ PKA_DEBUG(PKA_DEV, "loading boot image (%d words)\n", boot_img_size); ++ ++ boot_img_ptr = pka_firmware_array[shim_fw_id].boot_img; ++ ret = pka_dev_load_image(&shim->resources.master_prog_ram, ++ boot_img_ptr, boot_img_size); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to load boot image\n"); ++ return ret; ++ } ++ ++ PKA_DEBUG(PKA_DEV, "take the EIP-154 master controller out of reset\n"); ++ pka_dev_io_write(master_reg_ptr, master_reg_off, 0); ++ ++ // Poll for 'pka_master_irq' bit in AIC_ENABLED_STAT register to indicate ++ // sequencer is initialized ++ aic_csr_ptr = &shim->resources.aic_csr; ++ if (aic_csr_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ aic_csr_ptr->type != PKA_DEV_RES_TYPE_REG) ++ return -EPERM; ++ ++ aic_reg_base = aic_csr_ptr->base; ++ aic_reg_ptr = aic_csr_ptr->ioaddr; ++ aic_reg_off = pka_dev_get_register_offset(aic_reg_base, ++ AIC_ENABLED_STAT_ADDR); ++ ++ pka_master_irq = 0; ++ PKA_DEBUG(PKA_DEV, "poll for 'pka_master_irq'\n"); ++ timer = pka_dev_timer_start(100000); // 100 msec ++ while (pka_master_irq == 0) ++ { ++ pka_master_irq |= pka_dev_io_read(aic_reg_ptr, aic_reg_off) ++ & PKA_AIC_ENABLED_STAT_MASTER_IRQ_MASK; ++ if (pka_dev_timer_done(timer)) ++ { ++ //PKA_PANIC(PKA_DEV, "failed to load firmware\n"); ++ return -EAGAIN; ++ } ++ } ++ PKA_DEBUG(PKA_DEV, "'pka_master_irq' is active\n"); ++ ++ // Verify that the EIP-154 boot firmware has finished without errors ++ status_bits = (uint8_t)((pka_dev_io_read(master_reg_ptr, ++ master_reg_off) >> PKA_MASTER_SEQ_CTRL_MASTER_IRQ_BIT) ++ & 0xff); ++ if (status_bits != PKA_MASTER_SEQ_CTRL_STATUS_BYTE) ++ { ++ // If the error indication (bit [15]) is set, ++ // the EIP-154 boot firmware encountered an error and is stopped. ++ if ((status_bits >> (PKA_MASTER_SEQ_CTRL_MASTER_IRQ_BIT - 1)) == 1) ++ { ++ PKA_ERROR(PKA_DEV, ++ "boot firmware encountered an error 0x%x and is stopped\n", ++ status_bits); ++ return -EAGAIN; ++ } ++ PKA_DEBUG(PKA_DEV, "boot firmware in progress %d", status_bits); ++ } ++ PKA_DEBUG(PKA_DEV, "boot firmware has finished successfully\n"); ++ ++ PKA_DEBUG(PKA_DEV, "push the EIP-154 master controller into reset\n"); ++ pka_dev_io_write(master_reg_ptr, master_reg_off, ++ PKA_MASTER_SEQ_CTRL_RESET_VAL); ++ ++ // Load Master image into PKA_MASTER_PROG_RAM ++ master_img_size = pka_firmware_array[shim_fw_id].master_img_size; ++ PKA_DEBUG(PKA_DEV, "loading master image (%d words)\n", ++ master_img_size); ++ master_prog_ram = &shim->resources.master_prog_ram; ++ master_img_ptr = pka_firmware_array[shim_fw_id].master_img; ++ ret = pka_dev_load_image(master_prog_ram, master_img_ptr, ++ master_img_size); ++ if (ret) ++ { ++ pr_err("PKA DEV: failed to load master image\n"); ++ return ret; ++ } ++ ++ PKA_DEBUG(PKA_DEV, "take the EIP-154 master controller out of reset\n"); ++ pka_dev_io_write(master_reg_ptr, master_reg_off, 0); ++ ++ return ret; ++} ++ ++// Configure ring options. ++static int pka_dev_config_ring_options(pka_dev_res_t *buffer_ram_ptr, ++ uint32_t rings_num, uint8_t ring_priority) ++{ ++ uint64_t control_word; ++ uint64_t word_off; ++ int ret = 0; ++ ++ if (buffer_ram_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ buffer_ram_ptr->type != PKA_DEV_RES_TYPE_MEM) ++ return -EPERM; ++ ++ if (rings_num > PKA_MAX_NUM_RINGS || ++ rings_num < 1) ++ { ++ PKA_ERROR(PKA_DEV, "invalid rings number\n"); ++ return -EINVAL; ++ } ++ ++ PKA_DEBUG(PKA_DEV, "Configure PKA ring options control word\n"); ++ ++ // Write PKA_RING_OPTIONS control word located in the PKA_BUFFER_RAM. The ++ // value of this word is determined by the PKA I/O block (Shim). Set the ++ // number of implemented command/result ring pairs that is available in ++ // this EIP-154, encoded as binary value, which is 4. ++ control_word = (uint64_t) 0x0; ++ control_word |= ring_priority & 0xff; ++ control_word |= ((rings_num - 1) << 8) & 0xff00; ++ control_word |= (PKA_RING_OPTIONS_SIGNATURE_BYTE << 24) & 0xff000000; ++ word_off = pka_dev_get_word_offset(buffer_ram_ptr->base, ++ PKA_RING_OPTIONS_ADDR, PKA_BUFFER_RAM_SIZE); ++ pka_dev_io_write(buffer_ram_ptr->ioaddr, word_off, control_word); ++ ++ return ret; ++} ++ ++static int pka_dev_config_trng_clk(pka_dev_res_t *aic_csr_ptr) ++{ ++ int ret = 0; ++ ++ uint64_t csr_reg_base, csr_reg_off; ++ uint64_t timer; ++ uint32_t trng_clk_en = 0; ++ void *csr_reg_ptr; ++ ++ if (aic_csr_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ aic_csr_ptr->type != PKA_DEV_RES_TYPE_REG) ++ return -EPERM; ++ ++ PKA_DEBUG(PKA_DEV, "Turn on TRNG clock\n"); ++ ++ csr_reg_base = aic_csr_ptr->base; ++ csr_reg_ptr = aic_csr_ptr->ioaddr; ++ ++ // Enable the TRNG clock in PKA_CLK_FORCE. ++ // In general, this register should be left in its default state of all ++ // zeroes! Only when the TRNG is directly controlled via the Host slave ++ // interface, the engine needs to be turned on using the ’trng_clk_on’ ++ // bit in this register. In case the TRNG is controlled via internal ++ // firmware, this is not required. ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, PKA_CLK_FORCE_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_CLK_FORCE_TRNG_ON); ++ // Check whether the system clock for TRNG engine is enabled. The clock ++ // MUST be running to provide access to the TRNG. ++ timer = pka_dev_timer_start(100000); // 100 msec ++ while (trng_clk_en == 0) ++ { ++ trng_clk_en |= pka_dev_io_read(csr_reg_ptr, csr_reg_off) ++ & PKA_CLK_FORCE_TRNG_ON; ++ if (pka_dev_timer_done(timer)) ++ { ++ PKA_DEBUG(PKA_DEV, "Failed to enable TRNG clock\n"); ++ return -EAGAIN; ++ } ++ } ++ PKA_DEBUG(PKA_DEV, "'trng_clk_on' is enabled\n"); ++ ++ return ret; ++} ++ ++static int pka_dev_trng_wait_test_ready(void *csr_reg_ptr, uint64_t csr_reg_base) ++{ ++ uint64_t csr_reg_off, timer, test_ready, csr_reg_val; ++ ++ test_ready = 0; ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_STATUS_ADDR); ++ timer = pka_dev_timer_start(1000000); // 1000 ms ++ ++ while (!test_ready) ++ { ++ csr_reg_val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ test_ready = csr_reg_val & PKA_TRNG_STATUS_TEST_READY; ++ ++ if (pka_dev_timer_done(timer)) ++ { ++ PKA_DEBUG(PKA_DEV, "TRNG: TEST ready timer done, 0x%llx\n", csr_reg_val); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int pka_dev_trng_enable_test(void *csr_reg_ptr, uint64_t csr_reg_base, ++ uint32_t test) ++{ ++ uint64_t csr_reg_val, csr_reg_off; ++ ++ // Set the ‘test_mode’ bit in the TRNG_CONTROL register and the ++ // ‘test_known_noise’ bit in the TRNG_TEST register – this will ++ // immediately set the ‘test_ready’ bit (in the TRNG_STATUS register) ++ // to indicate that data can be written. It will also reset the ++ // ‘monobit test’, ‘run test’ and ‘poker test’ circuits to their ++ // initial states. Note that the TRNG need not be enabled for this ++ // test. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ csr_reg_val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, ++ csr_reg_val | PKA_TRNG_CONTROL_TEST_MODE); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_TEST_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, test); ++ ++ // Wait until the 'test_ready' bit is set ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_STATUS_ADDR); ++ do ++ { ++ csr_reg_val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ } while((csr_reg_val & PKA_TRNG_STATUS_TEST_READY) == 0); ++ ++ // Check whether the 'monobit test', 'run test' and 'poker test' ++ // are reset. ++ if (csr_reg_val & (PKA_TRNG_STATUS_MONOBIT_FAIL ++ | PKA_TRNG_STATUS_RUN_FAIL ++ | PKA_TRNG_STATUS_POKER_FAIL)) ++ { ++ PKA_ERROR(PKA_DEV, "Test bits aren't reset, TRNG_STATUS:0x%llx\n", ++ csr_reg_val); ++ return -EAGAIN; ++ } ++ ++ // Set 'stall_run_poker' bit to allow inspecting the state of the ++ // result counters which would otherwise be reset immediately for ++ // the next 20,000 bits block to test. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_ALARMCNT_ADDR); ++ csr_reg_val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, ++ csr_reg_val | PKA_TRNG_ALARMCNT_STALL_RUN_POKER); ++ ++ return 0; ++} ++ ++static int pka_dev_trng_test_circuits(void *csr_reg_ptr, uint64_t csr_reg_base, ++ uint64_t datal, uint64_t datah, ++ int count, uint8_t add_half, ++ uint64_t *monobit_fail_cnt, ++ uint64_t *run_fail_cnt, ++ uint64_t *poker_fail_cnt) ++{ ++ uint64_t status, csr_reg_off; ++ int test_idx, error; ++ ++ if (monobit_fail_cnt == NULL || run_fail_cnt == NULL || poker_fail_cnt == NULL) ++ return -EINVAL; ++ ++ error = 0; ++ ++ for (test_idx = 0; test_idx < count; test_idx++) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_RAW_L_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, datal); ++ ++ if (add_half) ++ { ++ if (test_idx < count - 1) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_RAW_H_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, datah); ++ } ++ } ++ else ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_RAW_H_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, datah); ++ } ++ ++ // Wait until the ‘test_ready’ bit in the TRNG_STATUS register ++ // becomes ‘1’ again, signaling readiness for the next 64 bits ++ // of test data. At this point, the previous test data has ++ // been handled so the counter states can be inspected. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_STATUS_ADDR); ++ do ++ { ++ status = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ } while((status & PKA_TRNG_STATUS_TEST_READY) == 0); ++ ++ // Check test status bits. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_INTACK_ADDR); ++ if (status & PKA_TRNG_STATUS_MONOBIT_FAIL) ++ { ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_STATUS_MONOBIT_FAIL); ++ *monobit_fail_cnt += 1; ++ } ++ else if (status & PKA_TRNG_STATUS_RUN_FAIL) ++ { ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_STATUS_RUN_FAIL); ++ *run_fail_cnt += 1; ++ } ++ else if (status & PKA_TRNG_STATUS_POKER_FAIL) ++ { ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_STATUS_POKER_FAIL); ++ *poker_fail_cnt += 1; ++ } ++ ++ } ++ ++ error = (*monobit_fail_cnt || *poker_fail_cnt || *run_fail_cnt) ? -EIO : 0; ++ ++ return error; ++} ++ ++static void pka_dev_trng_disable_test(void *csr_reg_ptr, uint64_t csr_reg_base) ++{ ++ uint64_t status, val, csr_reg_off; ++ ++ // When done, clear the ‘test_known_noise’ bit in the TRNG_TEST ++ // register (will immediately clear the ‘test_ready’ bit in the ++ // TRNG_STATUS register and reset the ‘monobit test’, ‘run test’ ++ // and ‘poker test’ circuits) and clear the ‘test_mode’ bit in ++ // the TRNG_CONTROL register. ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_TEST_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_STATUS_ADDR); ++ status = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ if (status & PKA_TRNG_STATUS_TEST_READY) ++ PKA_PRINT(PKA_DEV, "Warning: Test ready bit is still set\n"); ++ ++ if (status & (PKA_TRNG_STATUS_MONOBIT_FAIL ++ | PKA_TRNG_STATUS_RUN_FAIL ++ | PKA_TRNG_STATUS_POKER_FAIL)) ++ PKA_PRINT(PKA_DEV, ++ "Warning: Test bits are still set, TRNG_STATUS:0x%llx\n", status); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, ++ (val & ~PKA_TRNG_STATUS_TEST_READY)); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_ALARMCNT_ADDR); ++ val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, ++ (val & ~PKA_TRNG_ALARMCNT_STALL_RUN_POKER)); ++ ++ return; ++} ++ ++static int pka_dev_trng_test_known_answer_basic(void *csr_reg_ptr, ++ uint64_t csr_reg_base) ++{ ++ int ret, cnt_idx, cnt_off; ++ uint64_t monobit_fail_cnt, run_fail_cnt, poker_fail_cnt, monobit_cnt; ++ uint64_t poker_cnt[4], csr_reg_off; ++ uint64_t poker_test_exp_cnt[4] = { ++ 0x20f42bf4, 0xaf415f4, 0xf4f4fff4, 0xfff4f4f4 ++ }; ++ ++ PKA_DEBUG(PKA_DEV, "Run known-answer test circuits\n"); ++ ++ monobit_fail_cnt = 0; ++ run_fail_cnt = 0; ++ poker_fail_cnt = 0; ++ ++ ret = pka_dev_trng_enable_test(csr_reg_ptr, csr_reg_base, ++ PKA_TRNG_TEST_KNOWN_NOISE); ++ if (ret) ++ return ret; ++ ++ ret = pka_dev_trng_test_circuits(csr_reg_ptr, csr_reg_base, 0x11111333, ++ 0x3555779f, 11, 0, &monobit_fail_cnt, &run_fail_cnt, ++ &poker_fail_cnt); ++ ++ ret |= pka_dev_trng_test_circuits(csr_reg_ptr, csr_reg_base, 0x01234567, ++ 0x89abcdef, 302, 1, &monobit_fail_cnt, &run_fail_cnt, ++ &poker_fail_cnt); ++ ++ PKA_DEBUG(PKA_DEV, "monobit_fail_cnt : 0x%llx\n", monobit_fail_cnt); ++ PKA_DEBUG(PKA_DEV, "poker_fail_cnt : 0x%llx\n", poker_fail_cnt); ++ PKA_DEBUG(PKA_DEV, "run_fail_cnt : 0x%llx\n", run_fail_cnt); ++ ++ for (cnt_idx = 0, cnt_off = 0; cnt_idx < 4; cnt_idx++, cnt_off += 8) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ (TRNG_POKER_3_0_ADDR + cnt_off)); ++ poker_cnt[cnt_idx] = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ } ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_MONOBITCNT_ADDR); ++ monobit_cnt = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ if (!ret) ++ { ++ if (memcmp(poker_cnt, poker_test_exp_cnt, sizeof(poker_test_exp_cnt))) ++ { ++ PKA_DEBUG(PKA_DEV, "invalid poker counters!\n"); ++ ret = -EIO; ++ } ++ ++ if (monobit_cnt != 9978) ++ { ++ PKA_DEBUG(PKA_DEV, "invalid sum of squares!\n"); ++ ret = -EIO; ++ } ++ } ++ ++ pka_dev_trng_disable_test(csr_reg_ptr, csr_reg_base); ++ ++ return ret; ++} ++ ++static int pka_dev_trng_test_known_answer_poker_fail(void *csr_reg_ptr, ++ uint64_t csr_reg_base) ++{ ++ uint64_t monobit_fail_cnt, run_fail_cnt, poker_fail_cnt; ++ int ret; ++ ++ monobit_fail_cnt = 0; ++ run_fail_cnt = 0; ++ poker_fail_cnt = 0; ++ ++ PKA_DEBUG(PKA_DEV, "Run known-answer test circuits (poker fail)\n"); ++ ++ pka_dev_trng_enable_test(csr_reg_ptr, csr_reg_base, ++ PKA_TRNG_TEST_KNOWN_NOISE); ++ ++ // Ignore the return value here as it is expected that poker test should ++ // fail. Check failure counts thereafter to assert only poker test has failed. ++ pka_dev_trng_test_circuits(csr_reg_ptr, csr_reg_base, 0xffffffff, ++ 0xffffffff, 11, 0, &monobit_fail_cnt, &run_fail_cnt, &poker_fail_cnt); ++ ++ PKA_DEBUG(PKA_DEV, "monobit_fail_cnt : 0x%llx\n", monobit_fail_cnt); ++ PKA_DEBUG(PKA_DEV, "poker_fail_cnt : 0x%llx\n", poker_fail_cnt); ++ PKA_DEBUG(PKA_DEV, "run_fail_cnt : 0x%llx\n", run_fail_cnt); ++ ++ if (poker_fail_cnt && !run_fail_cnt && !monobit_fail_cnt) ++ ret = 0; ++ else ++ ret = -EIO; ++ ++ pka_dev_trng_disable_test(csr_reg_ptr, csr_reg_base); ++ ++ return ret; ++} ++ ++static int pka_dev_trng_test_unknown_answer(void *csr_reg_ptr, ++ uint64_t csr_reg_base) ++{ ++ uint64_t datal, datah, csr_reg_off; ++ int ret, test_idx; ++ ++ datah = 0; ++ datal = 0; ++ ret = 0; ++ ++ PKA_DEBUG(PKA_DEV, "Run unknown-answer self test\n"); ++ ++ // First reset, the RAW registers. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_RAW_L_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_RAW_H_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ // There is a small probability for this test to fail, ++ // So run the test 10 times, if it succeeds once then ++ // assume that the test passed. ++ for (test_idx = 0; test_idx < 10; test_idx++) ++ { ++ pka_dev_trng_enable_test(csr_reg_ptr, csr_reg_base, PKA_TRNG_TEST_NOISE); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_RAW_L_ADDR); ++ datal = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_RAW_H_ADDR); ++ datah = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ PKA_DEBUG(PKA_DEV, "datal=0x%llx\n", datal); ++ PKA_DEBUG(PKA_DEV, "datah=0x%llx\n", datah); ++ ++ if (!datah && !datal) ++ { ++ ret = -EIO; ++ } ++ else ++ { ++ ret = 0; ++ break; ++ } ++ ++ pka_dev_trng_disable_test(csr_reg_ptr, csr_reg_base); ++ } ++ ++ return ret; ++} ++ ++// Test TRNG ++static int pka_dev_test_trng(void *csr_reg_ptr, uint64_t csr_reg_base) ++{ ++ int ret; ++ ++ ret = 0; ++ ++ ret = pka_dev_trng_test_known_answer_basic(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++ ret = pka_dev_trng_test_known_answer_poker_fail(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++ ret = pka_dev_trng_test_unknown_answer(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++exit: ++ return ret; ++} ++ ++static void pka_dev_trng_write_ps_ai_str(void *csr_reg_ptr, ++ uint64_t csr_reg_base, ++ uint32_t input_str[]) ++{ ++ uint64_t csr_reg_off; ++ int i; ++ ++ for (i = 0; i < PKA_TRNG_PS_AI_REG_COUNT; i++) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_PS_AI_0_ADDR + (i * 0x8)); ++ ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, input_str[i]); ++ } ++} ++ ++static void pka_dev_trng_drbg_generate(void *csr_reg_ptr, uint64_t csr_reg_base) ++{ ++ uint64_t csr_reg_off; ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_CONTROL_REQ_DATA_VAL); ++} ++ ++static int pka_dev_test_trng_drbg(void *csr_reg_ptr, uint64_t csr_reg_base) ++{ ++ uint64_t csr_reg_off, csr_reg_val; ++ int i, ret; ++ ++ ret = 0; ++ ++ // Make sure the engine is idle. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ // Enable DRBG, TRNG need not be enabled for this test. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_CONTROL_DRBG_ENABLE_VAL); ++ ++ // Set 'test_sp_800_90' bit in the TRNG_TEST register ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_TEST_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_TEST_DRBG_VAL); ++ ++ // Wait for 'test_ready' bit to be set. ++ ret = pka_dev_trng_wait_test_ready(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++ // Instantiate ++ pka_dev_trng_write_ps_ai_str(csr_reg_ptr, csr_reg_base, pka_trng_drbg_test_ps_str); ++ ret = pka_dev_trng_wait_test_ready(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++ // Generate ++ pka_dev_trng_write_ps_ai_str(csr_reg_ptr, csr_reg_base, pka_trng_drbg_test_etpy_str1); ++ ret = pka_dev_trng_wait_test_ready(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++ // A standard NIST SP 800-90A DRBG known-answer test discards ++ // the result of the first 'Generate' function and only checks ++ // the result of the second 'Generate' function. Hence 'Generate' ++ // is performed again. ++ ++ // Generate ++ pka_dev_trng_write_ps_ai_str(csr_reg_ptr, csr_reg_base, pka_trng_drbg_test_etpy_str2); ++ ret = pka_dev_trng_wait_test_ready(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ goto exit; ++ ++ // Check output registers ++ for (i = 0; i < PKA_TRNG_OUTPUT_CNT; i++) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_OUTPUT_0_ADDR + (i * 0x8)); ++ ++ csr_reg_val = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ if ((uint32_t)csr_reg_val != pka_trng_drbg_test_output[i]) ++ { ++ PKA_DEBUG(PKA_DEV, ++ "DRBG known answer test failed for output register:%d, 0x%x\n", ++ i, (uint32_t)csr_reg_val); ++ ret = 1; ++ goto exit; ++ } ++ } ++ ++ // Clear 'test_sp_800_90' bit in the TRNG_TEST register. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_TEST_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++exit: ++ return ret; ++} ++ ++// Configure the TRNG. ++static int pka_dev_config_trng_drbg(pka_dev_res_t *aic_csr_ptr, ++ pka_dev_res_t *trng_csr_ptr) ++{ ++ int ret = 0; ++ ++ uint64_t csr_reg_base, csr_reg_off; ++ void *csr_reg_ptr; ++ ++ if (trng_csr_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ trng_csr_ptr->type != PKA_DEV_RES_TYPE_REG) ++ return -EPERM; ++ ++ PKA_DEBUG(PKA_DEV, "Starting up the TRNG\n"); ++ ++ ret = pka_dev_config_trng_clk(aic_csr_ptr); ++ if (ret) ++ return ret; ++ ++ csr_reg_base = trng_csr_ptr->base; ++ csr_reg_ptr = trng_csr_ptr->ioaddr; ++ ++ // Perform NIST known-answer tests on the complete SP 800-90A DRBG ++ // without BC_DF functionality. ++ ret = pka_dev_test_trng_drbg(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ return ret; ++ ++ // Starting up the TRNG with a DRBG ++ ++ // Make sure the engine is idle. ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ // Disable all FROs initially ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_FROENABLE_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_FRODETUNE_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ // Write all configuration values in the TRNG_CONFIG and TRNG_ALARMCNT, ++ // write zeroes to the TRNG_ALARMMASK and TRNG_ALARMSTOP registers. ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_CONFIG_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_CONFIG_REG_VAL); ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_ALARMCNT_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_ALARMCNT_REG_VAL); ++ ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_ALARMMASK_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_ALARMSTOP_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ // Enable all FROs in the TRNG_FROENABLE register. Note that this can ++ // only be done after clearing the TRNG_ALARMSTOP register. ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_FROENABLE_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_FROENABLE_REG_VAL); ++ ++ // Optionally, write 'Personalization string' of upto 384 bits in ++ // TRNG_PS_AI_... registers. The contents of these registers will be ++ // XOR-ed into the output of the SHA-256 'Conditioning Function' to be ++ // used as seed value for the actual DRBG. ++ pka_dev_trng_write_ps_ai_str(csr_reg_ptr, csr_reg_base, pka_trng_drbg_ps_str); ++ ++ ++ // Run TRNG tests after configuring TRNG. ++ // NOTE: TRNG need not be enabled to carry out these tests. ++ ret = pka_dev_test_trng(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ return ret; ++ ++ // Start the actual engine by setting the 'enable_trng' and 'drbg_en' bit ++ // in the TRNG_CONTROL register (also a nice point to set the interrupt mask ++ // bits). ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_CONTROL_DRBG_REG_VAL); ++ ++ // The engine is now ready to handle the first 'Generate' request using ++ // the 'request_data' bit of the TRNG_CONTROL register. The first output ++ // for these requests will take a while, as Noise Source and Conditioning ++ // Function must first generate seed entropy for the DRBG. ++ ++ ++ // Optionally, when buffer RAM is configured: Set a data available ++ // interrupt threshold using the 'load_thresh' and 'blocks_thresh' ++ // fields of the TRNG_INTACK register. This allows delaying the data ++ // available interrupt until the indicated number of 128-bit words are ++ // available in the buffer RAM. ++ ++ // Start the actual 'Generate' operation using the 'request_data' and 'data_blocks' ++ // fields of the TRNG_CONTROL register. ++ ++ pka_dev_trng_drbg_generate(csr_reg_ptr, csr_reg_base); ++ ++ mdelay(200); ++ ++ return ret; ++} ++ ++// Triggers hardaware zeorize to initialize PKA internal memories ++static int pka_dev_ram_zeroize(pka_dev_res_t *ext_csr_ptr) ++{ ++ uint64_t csr_reg_base, csr_reg_off, csr_reg_value; ++ uint64_t timer; ++ void *csr_reg_ptr; ++ ++ if (ext_csr_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ ext_csr_ptr->type != PKA_DEV_RES_TYPE_REG) ++ return -EPERM; ++ ++ PKA_DEBUG(PKA_DEV, "Starting memory zeroize\n"); ++ ++ csr_reg_base = ext_csr_ptr->base; ++ csr_reg_ptr = ext_csr_ptr->ioaddr; ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ PKA_ZEROIZE_ADDR); ++ // When PKA_ZEROIZE register is written (with any value) ++ // sensitive data in the PKA is zeroed out. ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 1); ++ ++ // Now wait until the zeroize completes ++ timer = pka_dev_timer_start(10000000); // 10000 ms ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ while (csr_reg_value != 0) ++ { ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ if (pka_dev_timer_done(timer)) ++ { ++ PKA_DEBUG(PKA_DEV, "Timeout while PKA zeorize\n"); ++ return -EBUSY; ++ } ++ } ++ ++ return 0; ++} ++ ++// Initialize PKA IO block refered to as shim. It configures shim's ++// parameters and prepare resources by mapping corresponding memory. ++// The function also configures shim registers and load firmware to ++// shim internal rams. The pka_dev_shim_t passed as input is also an ++// output. It returns 0 on success, a negative error code on failure. ++static int pka_dev_init_shim(pka_dev_shim_t *shim) ++{ ++ const uint32_t *farm_img_ptr; ++ uint32_t farm_img_size, data[4], i; ++ uint8_t shim_fw_id; ++ ++ int ret = 0; ++ ++ if (shim->status != PKA_SHIM_STATUS_CREATED) ++ { ++ PKA_ERROR(PKA_DEV, "PKA device must be created\n"); ++ return -EPERM; ++ } ++ ++ // First of all, trigger a hardware zeroize to initialize internal ++ // RAM memories ++ ret = pka_dev_ram_zeroize(&shim->resources.ext_csr); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to zeroize PKA\n"); ++ return ret; ++ } ++ ++ // Configure AIC registers ++ ret = pka_dev_config_aic_interrupts(&shim->resources.aic_csr); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to configure AIC\n"); ++ return ret; ++ } ++ ++ shim_fw_id = pka_firmware_get_id(); ++ ++ // Load Farm image into PKA_BUFFER_RAM for non-High Assurance mode ++ // or into PKA_SECURE_RAM for High Assurance mode. ++ farm_img_size = pka_firmware_array[shim_fw_id].farm_img_size; ++ PKA_DEBUG(PKA_DEV, "loading farm image (%d words)\n", farm_img_size); ++ ++ farm_img_ptr = pka_firmware_array[shim_fw_id].farm_img; ++ // The IP provider suggests using the zeroize function to initialize ++ // the Buffer RAM. But a bug has been detected when writing ECC bits. ++ // Thus a workaround is used, and has already been shown to work; it ++ // consists of padding the farm image. Then all RAM locations will be ++ // written with correct ECC before the IP reads the image out. ++ ret = pka_dev_load_image(&shim->resources.buffer_ram, farm_img_ptr, ++ farm_img_size); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to load farm image\n"); ++ return ret; ++ } ++ ++ // Configure EIP-154 Master controller Sequencer ++ ret = pka_dev_config_master_seq_controller(shim, ++ &shim->resources.master_seq_ctrl); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to configure Master controller " ++ "Sequencer\n"); ++ return ret; ++ } ++ ++ // Configure PKA Ring options control word ++ ret = pka_dev_config_ring_options(&shim->resources.buffer_ram, ++ shim->rings_num, shim->ring_priority); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to configure ring options\n"); ++ return ret; ++ } ++ ++ shim->trng_enabled = PKA_SHIM_TRNG_ENABLED; ++ shim->trng_err_cycle = 0; ++ ++ // Configure the TRNG ++ ret = pka_dev_config_trng_drbg(&shim->resources.aic_csr, ++ &shim->resources.trng_csr); ++ ++ // Pull out data from the content of the TRNG buffer RAM and ++ // start the re-generation of new numbers; read and drop 512 ++ // words. The read must be done over the 4 TRNG_OUTPUT_X registers ++ // at a time. ++ i = 0; ++ while (i < 128) ++ { ++ pka_dev_trng_read(shim, data, sizeof(data)); ++ i++; ++ } ++ ++ if (ret) ++ { ++ // Keep running without TRNG since it does not hurt, but ++ // notify users. ++ PKA_ERROR(PKA_DEV, "failed to configure TRNG\n"); ++ shim->trng_enabled = PKA_SHIM_TRNG_DISABLED; ++ } ++ ++ mutex_init(&shim->mutex); ++ shim->busy_ring_num = 0; ++ shim->status = PKA_SHIM_STATUS_INITIALIZED; ++ ++ return ret; ++} ++ ++// Release a given shim. ++static int pka_dev_release_shim(pka_dev_shim_t *shim) ++{ ++ int ret = 0; ++ ++ uint32_t ring_idx; ++ ++ if (shim->status != PKA_SHIM_STATUS_INITIALIZED && ++ shim->status != PKA_SHIM_STATUS_STOPPED) ++ { ++ PKA_ERROR(PKA_DEV, "PKA device must be initialized or stopped\n"); ++ return -EPERM; ++ } ++ ++ // Release rings which belong to the shim. The operating system might ++ // release ring devices before shim devices. The global configuration ++ // must be checked before proceeding to the release of ring devices. ++ if (pka_gbl_config.dev_rings_cnt) ++ { ++ for (ring_idx = 0; ring_idx < shim->rings_num; ring_idx++) ++ { ++ ret = pka_dev_release_ring(shim->rings[ring_idx]); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to release ring %d\n", ring_idx); ++ return ret; ++ } ++ } ++ } ++ ++ shim->busy_ring_num = 0; ++ shim->status = PKA_SHIM_STATUS_FINALIZED; ++ ++ return ret; ++} ++ ++// Return the ring associated with the given identifier. ++pka_dev_ring_t *pka_dev_get_ring(uint32_t ring_id) ++{ ++ return pka_gbl_config.dev_rings[ring_id]; ++} ++ ++// Return the shim associated with the given identifier. ++pka_dev_shim_t *pka_dev_get_shim(uint32_t shim_id) ++{ ++ return pka_gbl_config.dev_shims[shim_id]; ++} ++ ++ ++static pka_dev_ring_t *__pka_dev_register_ring(uint32_t ring_id, ++ uint32_t shim_id) ++{ ++ pka_dev_shim_t *shim; ++ pka_dev_ring_t *ring; ++ ++ int ret; ++ ++ shim = pka_dev_get_shim(shim_id); ++ if (!shim) ++ return NULL; ++ ++ ring = kzalloc(sizeof(pka_dev_ring_t), GFP_KERNEL); ++ if (!ring) ++ return ring; ++ ++ ring->status = PKA_DEV_RING_STATUS_UNDEFINED; ++ ++ // Initialize ring. ++ ret = pka_dev_init_ring(ring, ring_id, shim); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to initialize ring %d\n", ring_id); ++ pka_dev_release_ring(ring); ++ kfree(ring); ++ return NULL; ++ } ++ ++ return ring; ++} ++ ++pka_dev_ring_t *pka_dev_register_ring(uint32_t ring_id, uint32_t shim_id) ++{ ++ pka_dev_ring_t *ring; ++ ++ ring = __pka_dev_register_ring(ring_id, shim_id); ++ if (ring) ++ { ++ pka_gbl_config.dev_rings[ring->ring_id] = ring; ++ pka_gbl_config.dev_rings_cnt += 1; ++ } ++ ++ return ring; ++} ++ ++static int __pka_dev_unregister_ring(pka_dev_ring_t *ring) ++{ ++ int ret; ++ ++ if (!ring) ++ return -EINVAL; ++ ++ // Release ring ++ ret = pka_dev_release_ring(ring); ++ if (ret) ++ return ret; ++ ++ kfree(ring); ++ ++ return ret; ++} ++ ++int pka_dev_unregister_ring(pka_dev_ring_t *ring) ++{ ++ pka_gbl_config.dev_rings[ring->ring_id] = NULL; ++ pka_gbl_config.dev_rings_cnt -= 1; ++ ++ return __pka_dev_unregister_ring(ring); ++} ++ ++static pka_dev_shim_t *__pka_dev_register_shim(uint32_t shim_id, ++ struct pka_dev_mem_res *mem_res) ++{ ++ pka_dev_shim_t *shim; ++ ++ uint8_t split; ++ int ret = 0; ++ ++ PKA_DEBUG(PKA_DEV, "register shim id=%u\n", shim_id); ++ ++ shim = kzalloc(sizeof(pka_dev_shim_t), GFP_KERNEL); ++ if (!shim) ++ return shim; ++ ++ // Shim state MUST be set to undefined before calling 'pka_dev_create_shim' ++ // function ++ shim->status = PKA_SHIM_STATUS_UNDEFINED; ++ ++ // Set the Window RAM user mode ++ split = PKA_SPLIT_WINDOW_RAM_MODE; ++ ++ // Create PKA shim ++ ret = pka_dev_create_shim(shim, shim_id, split, mem_res); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to create shim %u\n", shim_id); ++ pka_dev_delete_shim(shim); ++ kfree(shim); ++ return NULL; ++ } ++ ++ // Initialize PKA shim ++ ret = pka_dev_init_shim(shim); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to init shim %u\n", shim_id); ++ pka_dev_release_shim(shim); ++ pka_dev_delete_shim(shim); ++ kfree(shim); ++ return NULL; ++ } ++ ++ return shim; ++} ++ ++pka_dev_shim_t *pka_dev_register_shim(uint32_t shim_id, uint8_t shim_fw_id, ++ struct pka_dev_mem_res *mem_res) ++{ ++ pka_dev_shim_t *shim; ++ ++ pka_firmware_set_id(shim_fw_id); ++ ++ shim = __pka_dev_register_shim(shim_id, mem_res); ++ if (shim) ++ { ++ pka_gbl_config.dev_shims[shim->shim_id] = shim; ++ pka_gbl_config.dev_shims_cnt += 1; ++ } ++ ++ return shim; ++} ++ ++static int __pka_dev_unregister_shim(pka_dev_shim_t *shim) ++{ ++ int ret = 0; ++ ++ if (!shim) ++ return -EINVAL; ++ ++ // Release shim ++ ret = pka_dev_release_shim(shim); ++ if (ret) ++ return ret; ++ ++ // Delete shim ++ ret = pka_dev_delete_shim(shim); ++ if (ret) ++ return ret; ++ ++ kfree(shim); ++ ++ return ret; ++} ++ ++int pka_dev_unregister_shim(pka_dev_shim_t *shim) ++{ ++ pka_gbl_config.dev_shims[shim->shim_id] = NULL; ++ pka_gbl_config.dev_shims_cnt -= 1; ++ ++ return __pka_dev_unregister_shim(shim); ++} ++ ++static bool pka_dev_trng_shutdown_oflo(pka_dev_res_t *trng_csr_ptr, ++ uint64_t *err_cycle) ++{ ++ uint64_t csr_reg_base, csr_reg_off, csr_reg_value; ++ uint64_t curr_cycle_cnt, fro_stopped_mask, fro_enabled_mask; ++ void *csr_reg_ptr; ++ ++ csr_reg_base = trng_csr_ptr->base; ++ csr_reg_ptr = trng_csr_ptr->ioaddr; ++ ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_STATUS_ADDR); ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ if (csr_reg_value & PKA_TRNG_STATUS_SHUTDOWN_OFLO) ++ { ++ curr_cycle_cnt = get_cycles(); ++ // See if any FROs were shut down. If they were, toggle bits in the ++ // FRO detune register and reenable the FROs. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_ALARMSTOP_ADDR); ++ fro_stopped_mask = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ if (fro_stopped_mask) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_FROENABLE_ADDR); ++ fro_enabled_mask = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_FRODETUNE_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, fro_stopped_mask); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_FROENABLE_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, ++ fro_stopped_mask | fro_enabled_mask); ++ } ++ ++ // Reset the error ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_ALARMMASK_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_ALARMSTOP_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, 0); ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_INTACK_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, ++ PKA_TRNG_STATUS_SHUTDOWN_OFLO); ++ ++ // If we're seeing this error again within about a second, ++ // the hardware is malfunctioning. Disable the trng and return ++ // an error. ++ if (*err_cycle && (curr_cycle_cnt - *err_cycle < 1000000000)) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_CONTROL_ADDR); ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ csr_reg_value &= ~PKA_TRNG_CONTROL_REG_VAL; ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, csr_reg_value); ++ return false; ++ } ++ ++ *err_cycle = curr_cycle_cnt; ++ } ++ ++ return true; ++} ++ ++static int pka_dev_trng_drbg_reseed(void *csr_reg_ptr, uint64_t csr_reg_base) ++{ ++ uint64_t csr_reg_off; ++ int ret; ++ ++ ret = 0; ++ ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, TRNG_CONTROL_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_CONTROL_DRBG_RESEED); ++ ++ ret = pka_dev_trng_wait_test_ready(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ return ret; ++ ++ // Write personalization string ++ pka_dev_trng_write_ps_ai_str(csr_reg_ptr, csr_reg_base, pka_trng_drbg_ps_str); ++ ++ return ret; ++} ++ ++// Read from DRBG enabled TRNG ++int pka_dev_trng_read(pka_dev_shim_t *shim, uint32_t *data, uint32_t cnt) ++{ ++ int ret = 0; ++ ++ pka_dev_res_t *trng_csr_ptr; ++ uint64_t csr_reg_base, csr_reg_off, csr_reg_value; ++ uint64_t timer; ++ uint32_t data_idx, word_cnt; ++ uint8_t output_idx, trng_ready = 0; ++ void *csr_reg_ptr; ++ ++ if (!shim || !data || (cnt % PKA_TRNG_OUTPUT_CNT != 0)) ++ return -EINVAL; ++ ++ if (!cnt) ++ return ret; ++ ++ mutex_lock(&shim->mutex); ++ ++ trng_csr_ptr = &shim->resources.trng_csr; ++ ++ if (trng_csr_ptr->status != PKA_DEV_RES_STATUS_MAPPED || ++ trng_csr_ptr->type != PKA_DEV_RES_TYPE_REG) ++ { ++ ret = -EPERM; ++ goto exit; ++ } ++ ++ csr_reg_base = trng_csr_ptr->base; ++ csr_reg_ptr = trng_csr_ptr->ioaddr; ++ ++ if (!pka_dev_trng_shutdown_oflo(trng_csr_ptr, ++ &shim->trng_err_cycle)) ++ { ++ ret = -EWOULDBLOCK; ++ goto exit; ++ } ++ ++ // Determine the number of 32-bit words. ++ word_cnt = cnt >> 2; ++ ++ for (data_idx = 0; data_idx < word_cnt; data_idx++) ++ { ++ output_idx = data_idx % PKA_TRNG_OUTPUT_CNT; ++ ++ // Tell the hardware to advance ++ if (output_idx == 0) ++ { ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_INTACK_ADDR); ++ pka_dev_io_write(csr_reg_ptr, csr_reg_off, PKA_TRNG_STATUS_READY); ++ trng_ready = 0; ++ ++ // Check if 'data_blocks' field is zero in TRNG_CONTROL register, ++ // if it is then we have to issue a 'Reseed' and Generate' request ++ // for DRBG enabled TRNG. ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_CONTROL_ADDR); ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ ++ if (!((uint32_t)csr_reg_value & PKA_TRNG_DRBG_DATA_BLOCK_MASK)) ++ { ++ // Issue reseed ++ ret = pka_dev_trng_drbg_reseed(csr_reg_ptr, csr_reg_base); ++ if (ret) ++ { ++ ret = -EBUSY; ++ goto exit; ++ } ++ ++ // Issue generate request ++ pka_dev_trng_drbg_generate(csr_reg_ptr, csr_reg_base); ++ } ++ ++ } ++ ++ // Wait until a data word is available in the TRNG_OUTPUT_X ++ // registers (using the interrupt and/or 'ready' status bit in the ++ // TRNG_STATUS register. The only way this would hang if the TRNG ++ // never initialized, and we would not call this function if that ++ // happened. ++ timer = pka_dev_timer_start(1000000); // 1000 ms ++ csr_reg_off = ++ pka_dev_get_register_offset(csr_reg_base, TRNG_STATUS_ADDR); ++ while (trng_ready == 0) ++ { ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ trng_ready = csr_reg_value & PKA_TRNG_STATUS_READY; ++ ++ if (pka_dev_timer_done(timer)) ++ { ++ PKA_DEBUG(PKA_DEV, ++ "Shim %u got error obtaining random number\n", ++ shim->shim_id); ++ ret = -EBUSY; ++ goto exit; ++ } ++ } ++ ++ // Read the registers ++ csr_reg_off = pka_dev_get_register_offset(csr_reg_base, ++ TRNG_OUTPUT_0_ADDR + (output_idx * 0x8)); ++ csr_reg_value = pka_dev_io_read(csr_reg_ptr, csr_reg_off); ++ data[data_idx] = (uint32_t) csr_reg_value; ++ } ++ ++exit: ++ mutex_unlock(&shim->mutex); ++ return ret; ++} ++ ++bool pka_dev_has_trng(pka_dev_shim_t *shim) ++{ ++ if (!shim) ++ return false; ++ ++ return (shim->trng_enabled == PKA_SHIM_TRNG_ENABLED); ++} ++ ++// Syscall to open ring. ++int __pka_dev_open_ring(uint32_t ring_id) ++{ ++ pka_dev_shim_t *shim; ++ pka_dev_ring_t *ring; ++ ++ int ret = 0; ++ ++ if (pka_gbl_config.dev_rings_cnt == 0) ++ return -EPERM; ++ ++ ring = pka_dev_get_ring(ring_id); ++ if (!ring || !ring->shim) ++ return -ENXIO; ++ ++ shim = ring->shim; ++ ++ mutex_lock(&ring->mutex); ++ ++ if (shim->status == PKA_SHIM_STATUS_UNDEFINED || ++ shim->status == PKA_SHIM_STATUS_CREATED || ++ shim->status == PKA_SHIM_STATUS_FINALIZED) ++ { ++ ret = -EPERM; ++ goto unlock_return; ++ } ++ ++ if (ring->status == PKA_DEV_RING_STATUS_BUSY) ++ { ++ ret = -EBUSY; ++ goto unlock_return; ++ } ++ ++ if (ring->status != PKA_DEV_RING_STATUS_INITIALIZED) ++ { ++ ret = -EPERM; ++ goto unlock_return; ++ } ++ ++ // Set ring information words. ++ ret = pka_dev_set_ring_info(ring); ++ if (ret) ++ { ++ PKA_ERROR(PKA_DEV, "failed to set ring information\n"); ++ ret = -EWOULDBLOCK; ++ goto unlock_return; ++ } ++ ++ if (shim->busy_ring_num == 0) ++ shim->status = PKA_SHIM_STATUS_RUNNING; ++ ++ ring->status = PKA_DEV_RING_STATUS_BUSY; ++ shim->busy_ring_num += 1; ++ ++unlock_return: ++ mutex_unlock(&ring->mutex); ++ return ret; ++} ++ ++// Open ring. ++int pka_dev_open_ring(pka_ring_info_t *ring_info) ++{ ++ return __pka_dev_open_ring(ring_info->ring_id); ++} ++ ++// Syscall to close ring. ++int __pka_dev_close_ring(uint32_t ring_id) ++{ ++ pka_dev_shim_t *shim; ++ pka_dev_ring_t *ring; ++ ++ int ret = 0; ++ ++ if (pka_gbl_config.dev_rings_cnt == 0) ++ return -EPERM; ++ ++ ring = pka_dev_get_ring(ring_id); ++ if (!ring || !ring->shim) ++ return -ENXIO; ++ ++ shim = ring->shim; ++ ++ mutex_lock(&ring->mutex); ++ ++ if (shim->status != PKA_SHIM_STATUS_RUNNING && ++ ring->status != PKA_DEV_RING_STATUS_BUSY) ++ { ++ ret = -EPERM; ++ goto unlock_return; ++ } ++ ++ ring->status = PKA_DEV_RING_STATUS_INITIALIZED; ++ shim->busy_ring_num -= 1; ++ ++ if (shim->busy_ring_num == 0) ++ shim->status = PKA_SHIM_STATUS_STOPPED; ++ ++unlock_return: ++ mutex_unlock(&ring->mutex); ++ return ret; ++} ++ ++// Close ring. ++int pka_dev_close_ring(pka_ring_info_t *ring_info) ++{ ++ if (ring_info) ++ { ++ return __pka_dev_close_ring(ring_info->ring_id); ++ } ++ ++ return 0; ++} ++ ++// Syscall to map ring into memory (kernel-space). ++static int __pka_dev_mmap_ring(uint32_t ring_id) ++{ ++ //not implemented ++ return -1; ++} ++ ++// Map ring into memory (user-space). ++int pka_dev_mmap_ring(pka_ring_info_t *ring_info) ++{ ++ return __pka_dev_mmap_ring(ring_info->ring_id); ++} ++ ++// Syscall to unmap ring (kernel-space). ++static int __pka_dev_munmap_ring(uint32_t ring_id) ++{ ++ //not implemented ++ return -1; ++} ++ ++// Unmap ring (user-space). ++int pka_dev_munmap_ring(pka_ring_info_t *ring_info) ++{ ++ if (ring_info) ++ { ++ return __pka_dev_munmap_ring(ring_info->ring_id); ++ } ++ ++ return 0; ++} ++ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.h +new file mode 100644 +index 000000000..06ac28623 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_dev.h +@@ -0,0 +1,310 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_DEV_H__ ++#define __PKA_DEV_H__ ++ ++/// ++/// @file ++/// ++/// API to handle the PKA EIP-154 I/O block (shim). It provides functions ++/// and data structures to initialize and configure the PKA shim. It's the ++/// "southband interface" for communication with PKA hardware resources. ++/// ++ ++#include ++#include ++#include "mlxbf_pka_firmware.h" ++ ++#include ++ ++#include "mlxbf_pka_config.h" ++#include "mlxbf_pka_cpu.h" ++#include "mlxbf_pka_debug.h" ++#include "mlxbf_pka_ioctl.h" ++#include "mlxbf_pka_mmio.h" ++#include "mlxbf_pka_ring.h" ++ ++#define PKA_SYSFS_RING_DEVICES "/sys/bus/platform/devices" ++#define PKA_VFIO_DIR "/dev/vfio" ++#define PKA_VFIO_CONTAINER_PATH "/dev/vfio/vfio" ++#define PKA_VFIO_GROUP_FMT "/dev/vfio/%d" ++ ++#define PKA_DEVFS_RING_DEVICES "/dev/pka/%d" ++ ++// Defines specific to device-tree and Linux operating system. ++// Careful, all constants MUST be conform with both devicetree ++// (DTS) and ACPI tables (SSDT). ++// *TBD* Better to be detected automatically (or passed as arg ++// so far). ++#define PKA_DEV_RING_DT_PREFIX_0 "45000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_1 "47000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_2 "4d000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_3 "4f000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_4 "44000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_5 "46000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_6 "4c000000.eip154:ring@%d" ++#define PKA_DEV_RING_DT_PREFIX_7 "4e000000.eip154:ring@%d" ++ ++#define PKA_DEV_RING_ACPI_PREFIX "MLNXBF11:%02x" ++ ++/// Device resource structure ++typedef struct ++{ ++ void *ioaddr; ///< (iore)map-ped version of addr, for ++ /// driver internal use. ++ ++ uint64_t base; ///< base address of the device's ++ /// resource ++ ++ uint64_t size; ///< size of IO ++ ++ uint8_t type; ///< type of resource addr points to ++ int8_t status; ///< status of the resource ++ ++ char *name; ///< name of the resource ++} pka_dev_res_t; ++ ++/// defines for pka_dev_res->type ++#define PKA_DEV_RES_TYPE_MEM 1 // resource type is memory ++#define PKA_DEV_RES_TYPE_REG 2 // resource type is register ++ ++/// defines for pka_dev_res->status ++#define PKA_DEV_RES_STATUS_MAPPED 1 // the resource is (iore)-mapped ++#define PKA_DEV_RES_STATUS_UNMAPPED -1 // the resource is unmapped ++ ++/// PKA Ring resources structure ++typedef struct ++{ ++ pka_dev_res_t info_words; // ring information words ++ pka_dev_res_t counters; // ring counters ++ pka_dev_res_t window_ram; // window RAM ++} pka_dev_ring_res_t; ++ ++typedef struct pka_dev_shim_s pka_dev_shim_t; ++ ++/// PKA Ring structure ++typedef struct ++{ ++ uint32_t ring_id; ///< ring identifier. ++ ++ pka_dev_shim_t *shim; ///< pointer to the shim associated ++ /// to the ring. ++ ++ uint32_t resources_num; ///< number of ring ressources. ++ pka_dev_ring_res_t resources; ///< ring resources. ++ ++ pka_dev_hw_ring_info_t *ring_info; ///< ring information. ++ uint32_t num_cmd_desc; ///< number of command descriptors. ++ ++ int8_t status; ///< status of the ring. ++ ++ struct mutex mutex; ///< mutex lock for sharing ring device ++} pka_dev_ring_t; ++ ++/// defines for pka_dev_ring->status ++#define PKA_DEV_RING_STATUS_UNDEFINED -1 ++#define PKA_DEV_RING_STATUS_INITIALIZED 1 ++#define PKA_DEV_RING_STATUS_READY 2 ++#define PKA_DEV_RING_STATUS_BUSY 3 ++#define PKA_DEV_RING_STATUS_FINALIZED 4 ++ ++/// PKA Shim resources structure ++typedef struct ++{ ++ pka_dev_res_t buffer_ram; // buffer RAM ++ pka_dev_res_t master_prog_ram; // master controller program RAM ++ pka_dev_res_t master_seq_ctrl; // master sequencer controller CSR ++ pka_dev_res_t aic_csr; // interrupt controller CSRs ++ pka_dev_res_t trng_csr; // TRNG module CSRs ++ pka_dev_res_t ext_csr; // MiCA specific CSRs (glue logic) ++} pka_dev_shim_res_t; ++ ++#define PKA_DEV_SHIM_RES_CNT 6 // Number of PKA device resources ++ ++/// Platform global shim resource information ++typedef struct ++{ ++ pka_dev_res_t *res_tbl[PKA_DEV_SHIM_RES_CNT]; ++ uint8_t res_cnt; ++} pka_dev_gbl_shim_res_info_t; ++ ++struct pka_dev_mem_res ++{ ++ uint64_t eip154_base; ///< base address for eip154 mmio registers ++ uint64_t eip154_size; ///< eip154 mmio register region size ++ ++ uint64_t wndw_ram_off_mask; ///< common offset mask for alt window ram and window ram ++ uint64_t wndw_ram_base; ///< base address for window ram ++ uint64_t wndw_ram_size; ///< window ram region size ++ ++ uint64_t alt_wndw_ram_0_base; ///< base address for alternate window ram 0 ++ uint64_t alt_wndw_ram_1_base; ///< base address for alternate window ram 1 ++ uint64_t alt_wndw_ram_2_base; ///< base address for alternate window ram 2 ++ uint64_t alt_wndw_ram_3_base; ///< base address for alternate window ram 3 ++ uint64_t alt_wndw_ram_size; ///< alternate window ram regions size ++ ++ uint64_t csr_base; ///< base address for csr registers ++ uint64_t csr_size; ///< csr area size ++}; ++ ++ ++/// PKA Shim structure ++struct pka_dev_shim_s ++{ ++ struct pka_dev_mem_res mem_res; ++ ++ uint64_t trng_err_cycle; ///< TRNG error cycle ++ ++ uint32_t shim_id; ///< shim identifier ++ ++ uint32_t rings_num; ///< Number of supported rings (hw ++ /// specific) ++ ++ pka_dev_ring_t **rings; ///< pointer to rings which belong to ++ /// the shim. ++ ++ uint8_t ring_priority; ///< specify the priority in which ++ /// rings are handled. ++ ++ uint8_t ring_type; ///< indicates whether the result ++ /// ring delivers results strictly ++ /// in-order. ++ ++ pka_dev_shim_res_t resources; ///< shim resources ++ ++ uint8_t window_ram_split; ///< Window RAM mode. if non-zero, ++ /// the splitted window RAM scheme ++ /// is used. ++ ++ uint32_t busy_ring_num; ///< Number of active rings (rings in ++ /// busy state) ++ ++ uint8_t trng_enabled; ///< Whether the TRNG engine is ++ /// enabled. ++ ++ int8_t status; ///< status of the shim ++ ++ struct mutex mutex; ///< mutex lock for sharing shim ++}; ++ ++/// defines for pka_dev_shim->status ++#define PKA_SHIM_STATUS_UNDEFINED -1 ++#define PKA_SHIM_STATUS_CREATED 1 ++#define PKA_SHIM_STATUS_INITIALIZED 2 ++#define PKA_SHIM_STATUS_RUNNING 3 ++#define PKA_SHIM_STATUS_STOPPED 4 ++#define PKA_SHIM_STATUS_FINALIZED 5 ++ ++/// defines for pka_dev_shim->window_ram_split ++#define PKA_SHIM_WINDOW_RAM_SPLIT_ENABLED 1 // window RAM is splitted into ++ // 4 * 16KB blocks ++ ++#define PKA_SHIM_WINDOW_RAM_SPLIT_DISABLED 2 // window RAM is not splitted ++ // and occupies 64KB ++ ++/// defines for pka_dev_shim->trng_enabled ++#define PKA_SHIM_TRNG_ENABLED 1 ++#define PKA_SHIM_TRNG_DISABLED 0 ++ ++/// Platform global configuration structure ++typedef struct ++{ ++ uint32_t dev_shims_cnt; ///< number of registered PKA shims. ++ uint32_t dev_rings_cnt; ///< number of registered Rings. ++ ++ pka_dev_shim_t *dev_shims[PKA_MAX_NUM_IO_BLOCKS]; ///< table of registered ++ /// PKA shims. ++ ++ pka_dev_ring_t *dev_rings[PKA_MAX_NUM_RINGS]; ///< table of registered ++ /// Rings. ++} pka_dev_gbl_config_t; ++ ++extern pka_dev_gbl_config_t pka_gbl_config; ++ ++/// Ring getter for pka_dev_gbl_config_t structure which holds all system ++/// global configuration. This configuration is shared and common to kernel ++/// device driver associated with PKA hardware. ++pka_dev_ring_t *pka_dev_get_ring(uint32_t ring_id); ++ ++/// Shim getter for pka_dev_gbl_config_t structure which holds all system ++/// global configuration. This configuration is shared and common to kernel ++/// device driver associated with PKA hardware. ++pka_dev_shim_t *pka_dev_get_shim(uint32_t shim_id); ++ ++/// Register a Ring. This function initializes a Ring and configures its ++/// related resources, and returns a pointer to that ring. ++pka_dev_ring_t *pka_dev_register_ring(uint32_t ring_id, uint32_t shim_id); ++ ++/// Unregister a Ring ++int pka_dev_unregister_ring(pka_dev_ring_t *ring); ++ ++/// Register PKA IO block. This function initializes a shim and configures its ++/// related resources, and returns a pointer to that ring. ++pka_dev_shim_t *pka_dev_register_shim(uint32_t shim_id, uint8_t shim_fw_id, ++ struct pka_dev_mem_res *mem_res); ++ ++/// Unregister PKA IO block ++int pka_dev_unregister_shim(pka_dev_shim_t *shim); ++ ++/// Reset a Ring. ++int pka_dev_reset_ring(pka_dev_ring_t *ring); ++ ++/// Clear ring counters. This function resets the master sequencer controller ++/// to clear the command and result counters. ++int pka_dev_clear_ring_counters(pka_dev_ring_t *ring); ++ ++/// Read data from the TRNG. Drivers can fill up to 'cnt' bytes of data into ++/// the buffer 'data'. The buffer 'data' is aligned for any type and 'cnt' is ++/// a multiple of 4. ++int pka_dev_trng_read(pka_dev_shim_t *shim, uint32_t *data, uint32_t cnt); ++ ++/// Return true if the TRNG engine is enabled, false if not. ++bool pka_dev_has_trng(pka_dev_shim_t *shim); ++ ++/// Open the file descriptor associated with ring. It returns an integer value, ++/// which is used to refer to the file. If un-successful, it returns a negative ++/// error. ++int pka_dev_open_ring(pka_ring_info_t *ring_info); ++ ++/// Close the file descriptor associated with ring. The function returns 0 if ++/// successful, negative value to indicate an error. ++int pka_dev_close_ring(pka_ring_info_t *ring_info); ++ ++/// Map ring resources. ++int pka_dev_mmap_ring(pka_ring_info_t *ring_info); ++ ++/// Unmap ring resources. ++int pka_dev_munmap_ring(pka_ring_info_t *ring_info); ++ ++#endif /// __PKA_DEV_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c +new file mode 100644 +index 000000000..b8b5a465e +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c +@@ -0,0 +1,1398 @@ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mlxbf_pka_dev.h" ++ ++ ++#define PKA_DRIVER_VERSION "v3.0" ++#define PKA_DRIVER_NAME "pka-mlxbf" ++ ++#define PKA_DRIVER_DESCRIPTION "BlueField PKA driver" ++ ++#define PKA_DEVICE_COMPAT "mlx,mlxbf-pka" ++#define PKA_RING_DEVICE_COMPAT "mlx,mlxbf-pka-ring" ++ ++#define PKA_DEVICE_ACPIHID_BF1 "MLNXBF10" ++#define PKA_RING_DEVICE_ACPIHID_BF1 "MLNXBF11" ++ ++#define PKA_DEVICE_ACPIHID_BF2 "MLNXBF20" ++#define PKA_RING_DEVICE_ACPIHID_BF2 "MLNXBF21" ++ ++#define PKA_DEVICE_ACCESS_MODE 0666 ++ ++#define PKA_DEVICE_RES_CNT 7 ++enum pka_mem_res_idx { ++ PKA_ACPI_EIP154_IDX = 0, ++ PKA_ACPI_WNDW_RAM_IDX, ++ PKA_ACPI_ALT_WNDW_RAM_0_IDX, ++ PKA_ACPI_ALT_WNDW_RAM_1_IDX, ++ PKA_ACPI_ALT_WNDW_RAM_2_IDX, ++ PKA_ACPI_ALT_WNDW_RAM_3_IDX, ++ PKA_ACPI_CSR_IDX ++}; ++ ++enum pka_plat_type { ++ PKA_PLAT_TYPE_BF1 = 0, /* Platform type Bluefield-1 */ ++ PKA_PLAT_TYPE_BF2 /* Platform type Bluefield-2 */ ++}; ++ ++static DEFINE_MUTEX(pka_drv_lock); ++ ++static uint32_t pka_device_cnt; ++static uint32_t pka_ring_device_cnt; ++ ++const char pka_compat[] = PKA_DEVICE_COMPAT; ++const char pka_ring_compat[] = PKA_RING_DEVICE_COMPAT; ++ ++const char pka_acpihid_bf1[] = PKA_DEVICE_ACPIHID_BF1; ++const char pka_ring_acpihid_bf1[] = PKA_RING_DEVICE_ACPIHID_BF1; ++ ++const char pka_acpihid_bf2[] = PKA_DEVICE_ACPIHID_BF2; ++const char pka_ring_acpihid_bf2[] = PKA_RING_DEVICE_ACPIHID_BF2; ++ ++struct pka_drv_plat_info { ++ enum pka_plat_type type; ++ uint8_t fw_id; ++}; ++ ++static struct pka_drv_plat_info pka_drv_plat[] = { ++ [PKA_PLAT_TYPE_BF1] = { ++ .type = PKA_PLAT_TYPE_BF1, ++ .fw_id = PKA_FIRMWARE_IMAGE_0_ID ++ }, ++ [PKA_PLAT_TYPE_BF2] = { ++ .type = PKA_PLAT_TYPE_BF2, ++ .fw_id = PKA_FIRMWARE_IMAGE_2_ID ++ } ++}; ++ ++static const struct acpi_device_id pka_drv_acpi_ids[] = { ++ { PKA_DEVICE_ACPIHID_BF1, (kernel_ulong_t)&pka_drv_plat[PKA_PLAT_TYPE_BF1] }, ++ { PKA_RING_DEVICE_ACPIHID_BF1, 0 }, ++ { PKA_DEVICE_ACPIHID_BF2, (kernel_ulong_t)&pka_drv_plat[PKA_PLAT_TYPE_BF2] }, ++ { PKA_RING_DEVICE_ACPIHID_BF2, 0 }, ++ {}, ++}; ++ ++struct pka_info { ++ struct device *dev; /* the device this info belongs to */ ++ const char *name; /* device name */ ++ const char *version; /* device driver version */ ++ const char *compat; ++ const char *acpihid; ++ uint8_t flag; ++ struct module *module; ++ void *priv; /* optional private data */ ++}; ++ ++/* defines for pka_info->flags */ ++#define PKA_DRIVER_FLAG_RING_DEVICE 1 ++#define PKA_DRIVER_FLAG_DEVICE 2 ++ ++struct pka_platdata { ++ struct platform_device *pdev; ++ struct pka_info *info; ++ spinlock_t lock; ++ unsigned long irq_flags; ++}; ++ ++/* Bits in pka_platdata.irq_flags */ ++enum { ++ PKA_IRQ_DISABLED = 0, ++}; ++ ++struct pka_ring_region { ++ u64 off; ++ u64 addr; ++ resource_size_t size; ++ u32 flags; ++ u32 type; ++ void __iomem *ioaddr; ++}; ++ ++/* defines for pka_ring_region->flags */ ++#define PKA_RING_REGION_FLAG_READ (1 << 0) /* Region supports read */ ++#define PKA_RING_REGION_FLAG_WRITE (1 << 1) /* Region supports write */ ++#define PKA_RING_REGION_FLAG_MMAP (1 << 2) /* Region supports mmap */ ++ ++/* defines for pka_ring_region->type */ ++#define PKA_RING_RES_TYPE_NONE 0 ++#define PKA_RING_RES_TYPE_WORDS 1 /* info control/status words */ ++#define PKA_RING_RES_TYPE_CNTRS 2 /* count registers */ ++#define PKA_RING_RES_TYPE_MEM 4 /* window RAM region */ ++ ++#define PKA_DRIVER_RING_DEV_MAX PKA_MAX_NUM_RINGS ++ ++struct pka_ring_device { ++ struct pka_info *info; ++ struct device *device; ++ struct iommu_group *group; ++ int32_t group_id; ++ uint32_t device_id; ++ uint32_t parent_device_id; ++ struct mutex mutex; ++ uint32_t flags; ++ struct module *parent_module; ++ pka_dev_ring_t *ring; ++ int minor; ++ uint32_t num_regions; ++ struct pka_ring_region *regions; ++}; ++ ++#define PKA_DRIVER_DEV_MAX PKA_MAX_NUM_IO_BLOCKS ++#define PKA_DRIVER_RING_NUM_REGIONS_MAX PKA_MAX_NUM_RING_RESOURCES ++ ++/* defines for region index */ ++#define PKA_RING_REGION_WORDS_IDX 0 ++#define PKA_RING_REGION_CNTRS_IDX 1 ++#define PKA_RING_REGION_MEM_IDX 2 ++ ++#define PKA_RING_REGION_OFFSET_SHIFT 40 ++#define PKA_RING_REGION_OFFSET_MASK \ ++ (((u64)(1) << PKA_RING_REGION_OFFSET_SHIFT) - 1) ++ ++#define PKA_RING_OFFSET_TO_INDEX(off) \ ++ (off >> PKA_RING_REGION_OFFSET_SHIFT) ++ ++#define PKA_RING_REGION_INDEX_TO_OFFSET(index) \ ++ ((u64)(index) << PKA_RING_REGION_OFFSET_SHIFT) ++ ++struct pka_device { ++ struct pka_info *info; ++ struct device *device; ++ uint32_t device_id; ++ uint8_t fw_id; /* firmware identifier */ ++ struct mutex mutex; ++ struct resource *resource[PKA_DEVICE_RES_CNT]; ++ pka_dev_shim_t *shim; ++ long irq; /* interrupt number */ ++ struct hwrng rng; ++}; ++ ++/* defines for pka_device->irq */ ++#define PKA_IRQ_CUSTOM -1 ++#define PKA_IRQ_NONE 0 ++ ++/* Hardware interrupt handler */ ++static irqreturn_t pka_drv_irq_handler(int irq, void *device) ++{ ++ struct pka_device *pka_dev = (struct pka_device *)device; ++ struct platform_device *pdev = to_platform_device(pka_dev->device); ++ struct pka_platdata *priv = platform_get_drvdata(pdev); ++ ++ PKA_DEBUG(PKA_DRIVER, ++ "handle irq in device %u\n", pka_dev->device_id); ++ ++ /* Just disable the interrupt in the interrupt controller */ ++ ++ spin_lock(&priv->lock); ++ if (!__test_and_set_bit(PKA_IRQ_DISABLED, &priv->irq_flags)) ++ disable_irq_nosync(irq); ++ spin_unlock(&priv->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int pka_drv_register_irq(struct pka_device *pka_dev) ++{ ++ if (pka_dev->irq && (pka_dev->irq != PKA_IRQ_CUSTOM)) { ++ /* ++ * Allow sharing the irq among several devices (child devices ++ * so far) ++ */ ++ return request_irq(pka_dev->irq, ++ (irq_handler_t) pka_drv_irq_handler, ++ IRQF_SHARED, pka_dev->info->name, ++ pka_dev); ++ } ++ ++ return -ENXIO; ++} ++ ++static int pka_drv_ring_regions_init(struct pka_ring_device *ring_dev) ++{ ++ struct pka_ring_region *region; ++ pka_dev_ring_t *ring; ++ pka_dev_res_t *res; ++ uint32_t num_regions; ++ ++ ring = ring_dev->ring; ++ if (!ring || !ring->shim) ++ return -ENXIO; ++ ++ num_regions = ring->resources_num; ++ ring_dev->num_regions = num_regions; ++ ring_dev->regions = kcalloc(num_regions, ++ sizeof(struct pka_ring_region), ++ GFP_KERNEL); ++ if (!ring_dev->regions) ++ return -ENOMEM; ++ ++ /* Information words region */ ++ res = &ring->resources.info_words; ++ region = &ring_dev->regions[PKA_RING_REGION_WORDS_IDX]; ++ /* map offset to the physical address */ ++ region->off = ++ PKA_RING_REGION_INDEX_TO_OFFSET(PKA_RING_REGION_WORDS_IDX); ++ region->addr = res->base; ++ region->size = res->size; ++ region->type = PKA_RING_RES_TYPE_WORDS; ++ region->flags |= (PKA_RING_REGION_FLAG_MMAP | ++ PKA_RING_REGION_FLAG_READ | ++ PKA_RING_REGION_FLAG_WRITE); ++ ++ /* Count regiters region */ ++ res = &ring->resources.counters; ++ region = &ring_dev->regions[PKA_RING_REGION_CNTRS_IDX]; ++ /* map offset to the physical address */ ++ region->off = ++ PKA_RING_REGION_INDEX_TO_OFFSET(PKA_RING_REGION_CNTRS_IDX); ++ region->addr = res->base; ++ region->size = res->size; ++ region->type = PKA_RING_RES_TYPE_CNTRS; ++ region->flags |= (PKA_RING_REGION_FLAG_MMAP | ++ PKA_RING_REGION_FLAG_READ | ++ PKA_RING_REGION_FLAG_WRITE); ++ ++ /* Window ram region */ ++ res = &ring->resources.window_ram; ++ region = &ring_dev->regions[PKA_RING_REGION_MEM_IDX]; ++ /* map offset to the physical address */ ++ region->off = ++ PKA_RING_REGION_INDEX_TO_OFFSET(PKA_RING_REGION_MEM_IDX); ++ region->addr = res->base; ++ region->size = res->size; ++ region->type = PKA_RING_RES_TYPE_MEM; ++ region->flags |= (PKA_RING_REGION_FLAG_MMAP | ++ PKA_RING_REGION_FLAG_READ | ++ PKA_RING_REGION_FLAG_WRITE); ++ ++ return 0; ++} ++ ++static void pka_drv_ring_regions_cleanup(struct pka_ring_device *ring_dev) ++{ ++ /* clear vfio device regions */ ++ ring_dev->num_regions = 0; ++ kfree(ring_dev->regions); ++} ++ ++static int pka_drv_ring_open(void *device_data) ++{ ++ struct pka_ring_device *ring_dev = device_data; ++ struct pka_info *info = ring_dev->info; ++ pka_ring_info_t ring_info; ++ ++ int error; ++ ++ PKA_DEBUG(PKA_DRIVER, ++ "open ring device %u (device_data:%p)\n", ++ ring_dev->device_id, ring_dev); ++ ++ if (!try_module_get(info->module)) ++ return -ENODEV; ++ ++ ring_info.ring_id = ring_dev->device_id; ++ error = pka_dev_open_ring(&ring_info); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to open ring %u\n", ring_dev->device_id); ++ module_put(info->module); ++ return error; ++ } ++ ++ /* Initialize regions */ ++ error = pka_drv_ring_regions_init(ring_dev); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, "failed to initialize regions\n"); ++ pka_dev_close_ring(&ring_info); ++ module_put(info->module); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static void pka_drv_ring_release(void *device_data) ++{ ++ struct pka_ring_device *ring_dev = device_data; ++ struct pka_info *info = ring_dev->info; ++ pka_ring_info_t ring_info; ++ ++ int error; ++ ++ PKA_DEBUG(PKA_DRIVER, ++ "release ring device %u (device_data:%p)\n", ++ ring_dev->device_id, ring_dev); ++ ++ pka_drv_ring_regions_cleanup(ring_dev); ++ ++ ring_info.ring_id = ring_dev->device_id; ++ error = pka_dev_close_ring(&ring_info); ++ if (error) ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to close ring %u\n", ++ ring_dev->device_id); ++ ++ module_put(info->module); ++} ++ ++static int pka_drv_ring_mmap_region(struct pka_ring_region region, ++ struct vm_area_struct *vma) ++{ ++ u64 req_len, pgoff, req_start; ++ ++ req_len = vma->vm_end - vma->vm_start; ++ pgoff = vma->vm_pgoff & ++ ((1U << (PKA_RING_REGION_OFFSET_SHIFT - PAGE_SHIFT)) - 1); ++ req_start = pgoff << PAGE_SHIFT; ++ ++ region.size = roundup(region.size, PAGE_SIZE); ++ ++ if (req_start + req_len > region.size) ++ return -EINVAL; ++ ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff; ++ ++ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, ++ req_len, vma->vm_page_prot); ++} ++ ++static int pka_drv_ring_mmap(void *device_data, struct vm_area_struct *vma) ++{ ++ struct pka_ring_device *ring_dev = device_data; ++ struct pka_ring_region *region; ++ unsigned int index; ++ ++ PKA_DEBUG(PKA_DRIVER, "mmap device %u\n", ring_dev->device_id); ++ ++ index = vma->vm_pgoff >> (PKA_RING_REGION_OFFSET_SHIFT - PAGE_SHIFT); ++ ++ if (vma->vm_end < vma->vm_start) ++ return -EINVAL; ++ if (!(vma->vm_flags & VM_SHARED)) ++ return -EINVAL; ++ if (index >= ring_dev->num_regions) ++ return -EINVAL; ++ if (vma->vm_start & ~PAGE_MASK) ++ return -EINVAL; ++ if (vma->vm_end & ~PAGE_MASK) ++ return -EINVAL; ++ ++ region = &ring_dev->regions[index]; ++ ++ if (!(region->flags & PKA_RING_REGION_FLAG_MMAP)) ++ return -EINVAL; ++ ++ if (!(region->flags & PKA_RING_REGION_FLAG_READ) ++ && (vma->vm_flags & VM_READ)) ++ return -EINVAL; ++ ++ if (!(region->flags & PKA_RING_REGION_FLAG_WRITE) ++ && (vma->vm_flags & VM_WRITE)) ++ return -EINVAL; ++ ++ vma->vm_private_data = ring_dev; ++ ++ if (region->type & PKA_RING_RES_TYPE_CNTRS || ++ region->type & PKA_RING_RES_TYPE_MEM) ++ return pka_drv_ring_mmap_region(ring_dev->regions[index], vma); ++ ++ if (region->type & PKA_RING_RES_TYPE_WORDS) ++ /* ++ * Currently user space is not allowed to access this ++ * region. ++ */ ++ return -EINVAL; ++ ++ return -EINVAL; ++} ++ ++static long pka_drv_ring_ioctl(void *device_data, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct pka_ring_device *ring_dev = device_data; ++ ++ int error = -ENOTTY; ++ ++ if (cmd == PKA_RING_GET_REGION_INFO) { ++ pka_dev_region_info_t info; ++ ++ info.mem_index = PKA_RING_REGION_MEM_IDX; ++ info.mem_offset = ring_dev->regions[info.mem_index].off; ++ info.mem_size = ring_dev->regions[info.mem_index].size; ++ ++ info.reg_index = PKA_RING_REGION_CNTRS_IDX; ++ info.reg_offset = ring_dev->regions[info.reg_index].off; ++ info.reg_size = ring_dev->regions[info.reg_index].size; ++ ++ return copy_to_user((void __user *)arg, &info, sizeof(info)) ? ++ -EFAULT : 0; ++ ++ } else if (cmd == PKA_GET_RING_INFO) { ++ pka_dev_hw_ring_info_t *this_ring_info; ++ pka_dev_hw_ring_info_t hw_ring_info; ++ ++ this_ring_info = ring_dev->ring->ring_info; ++ ++ hw_ring_info.cmmd_base = this_ring_info->cmmd_base; ++ hw_ring_info.rslt_base = this_ring_info->rslt_base; ++ hw_ring_info.size = this_ring_info->size; ++ hw_ring_info.host_desc_size = this_ring_info->host_desc_size; ++ hw_ring_info.in_order = this_ring_info->in_order; ++ hw_ring_info.cmmd_rd_ptr = this_ring_info->cmmd_rd_ptr; ++ hw_ring_info.rslt_wr_ptr = this_ring_info->rslt_wr_ptr; ++ hw_ring_info.cmmd_rd_stats = this_ring_info->cmmd_rd_ptr; ++ hw_ring_info.rslt_wr_stats = this_ring_info->rslt_wr_stats; ++ ++ return copy_to_user((void __user *)arg, &hw_ring_info, ++ sizeof(hw_ring_info)) ? -EFAULT : 0; ++ } else if (cmd == PKA_CLEAR_RING_COUNTERS) { ++ return pka_dev_clear_ring_counters(ring_dev->ring); ++ } else if (cmd == PKA_GET_RANDOM_BYTES) { ++ pka_dev_trng_info_t *trng_data; ++ pka_dev_shim_t *shim; ++ bool trng_present; ++ uint32_t byte_cnt; ++ uint32_t *data; ++ int ret; ++ ++ ret = -ENOENT; ++ shim = ring_dev->ring->shim; ++ trng_data = (pka_dev_trng_info_t *)arg; ++ /* ++ * We need byte count which is multiple of 4 as ++ * required by pka_dev_trng_read() interface. ++ */ ++ byte_cnt = round_up(trng_data->count, 4); ++ ++ data = kzalloc(byte_cnt, GFP_KERNEL); ++ if (data == NULL) { ++ PKA_DEBUG(PKA_DRIVER, "failed to allocate memory.\n"); ++ return -ENOMEM; ++ } ++ ++ trng_present = pka_dev_has_trng(shim); ++ if (!trng_present) { ++ kfree(data); ++ return ret; ++ } ++ ++ ret = pka_dev_trng_read(shim, data, byte_cnt); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, "TRNG failed %d\n", ret); ++ kfree(data); ++ return ret; ++ } ++ ++ ret = copy_to_user((void __user *)(trng_data->data), data, trng_data->count); ++ kfree(data); ++ return ret ? -EFAULT : 0; ++ } ++ ++ return error; ++} ++ ++#ifdef CONFIG_PKA_VFIO_IOMMU ++static const struct vfio_device_ops pka_ring_vfio_ops = { ++ .name = PKA_DRIVER_NAME, ++ .open = pka_drv_ring_open, ++ .release = pka_drv_ring_release, ++ .ioctl = pka_drv_ring_ioctl, ++ .mmap = pka_drv_ring_mmap, ++}; ++ ++static int pka_drv_add_ring_device(struct pka_ring_device *ring_dev) ++{ ++ struct device *dev = ring_dev->device; ++ int ret; ++ ++ ring_dev->parent_module = THIS_MODULE; ++ ring_dev->flags = VFIO_DEVICE_FLAGS_PLATFORM; ++ ++ ring_dev->group = vfio_iommu_group_get(dev); ++ if (!ring_dev->group) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to get IOMMU group for device %d\n", ++ ring_dev->device_id); ++ return -EINVAL; ++ } ++ ++ /* ++ * Note that this call aims to add the given child device to a vfio ++ * group. This function creates a new driver data for the device ++ * different from the structure passed as a 3rd argument - i.e. ++ * pka_ring_dev. The struct newly created corresponds to 'vfio_device' ++ * structure which includes a field called 'device_data' that holds ++ * the initialized 'pka_ring_dev'. So to retrieve our private data, ++ * we must call 'dev_get_drvdata()' which returns the 'vfio_device' ++ * struct and access its 'device_data' field. Here one can use ++ * 'pka_platdata' structure instead to be consistent with the parent ++ * devices, and have a common driver data structure which will be used ++ * to manage devices - 'pka_drv_remove()' for instance. Since the VFIO ++ * framework alters the driver data and introduce an indirection, it ++ * is no more relevant to have a common driver data structure. Hence, ++ * we prefer to set the struct 'pka_vfio_dev' instead to avoid ++ * indirection when we have to retrieve this structure during the ++ * open(), mmap(), and ioctl() calls. Since, this structure is used ++ * as driver data here, it will be immediately reachable for these ++ * functions (see first argument passed (void *device_data) passed ++ * to those functions). ++ */ ++ ret = vfio_add_group_dev(dev, &pka_ring_vfio_ops, ring_dev); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to add group device %d\n", ++ ring_dev->device_id); ++ vfio_iommu_group_put(ring_dev->group, dev); ++ return ret; ++ } ++ ++ ring_dev->group_id = iommu_group_id(ring_dev->group); ++ ++ PKA_DEBUG(PKA_DRIVER, ++ "ring device %d bus:%p iommu_ops:%p group:%p\n", ++ ring_dev->device_id, ++ dev->bus, ++ dev->bus->iommu_ops, ++ ring_dev->group); ++ ++ return 0; ++} ++ ++static struct pka_ring_device *pka_drv_del_ring_device(struct device *dev) ++{ ++ struct pka_ring_device *ring_dev; ++ ++ ring_dev = vfio_del_group_dev(dev); ++ if (ring_dev) ++ vfio_iommu_group_put(dev->iommu_group, dev); ++ ++ return ring_dev; ++} ++ ++static int pka_drv_init_class(void) ++{ ++ return 0; ++} ++ ++static void pka_drv_destroy_class(void) ++{ ++} ++#else ++static struct pka { ++ struct class *class; ++ struct idr ring_idr; ++ struct mutex ring_lock; ++ struct cdev ring_cdev; ++ dev_t ring_devt; ++} pka; ++ ++static int pka_drv_open(struct inode *inode, struct file *filep) ++{ ++ struct pka_ring_device *ring_dev; ++ int ret; ++ ++ ring_dev = idr_find(&pka.ring_idr, iminor(inode)); ++ if (!ring_dev) { ++ PKA_ERROR(PKA_DRIVER, ++ "failed to find idr for device %d\n", ++ ring_dev->device_id); ++ return -ENODEV; ++ } ++ ++ ret = pka_drv_ring_open(ring_dev); ++ if (ret) ++ return ret; ++ ++ filep->private_data = ring_dev; ++ return 0; ++} ++ ++static int pka_drv_release(struct inode *inode, struct file *filep) ++{ ++ struct pka_ring_device *ring_dev = filep->private_data; ++ ++ filep->private_data = NULL; ++ pka_drv_ring_release(ring_dev); ++ ++ return 0; ++} ++ ++static int pka_drv_mmap(struct file *filep, struct vm_area_struct *vma) ++{ ++ return pka_drv_ring_mmap(filep->private_data, vma); ++} ++ ++static long pka_drv_unlocked_ioctl(struct file *filep, ++ unsigned int cmd, unsigned long arg) ++{ ++ return pka_drv_ring_ioctl(filep->private_data, cmd, arg); ++} ++ ++static const struct file_operations pka_ring_fops = { ++ .owner = THIS_MODULE, ++ .open = pka_drv_open, ++ .release = pka_drv_release, ++ .unlocked_ioctl = pka_drv_unlocked_ioctl, ++ .mmap = pka_drv_mmap, ++}; ++ ++static int pka_drv_add_ring_device(struct pka_ring_device *ring_dev) ++{ ++ struct device *dev = ring_dev->device; ++ ++ ring_dev->minor = idr_alloc(&pka.ring_idr, ++ ring_dev, 0, MINORMASK + 1, GFP_KERNEL); ++ if (ring_dev->minor < 0) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to alloc minor to device %d\n", ++ ring_dev->device_id); ++ return ring_dev->minor; ++ } ++ ++ dev = device_create(pka.class, NULL, ++ MKDEV(MAJOR(pka.ring_devt), ring_dev->minor), ++ ring_dev, "%d", ring_dev->device_id); ++ if (IS_ERR(dev)) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to create device %d\n", ++ ring_dev->device_id); ++ idr_remove(&pka.ring_idr, ring_dev->minor); ++ return PTR_ERR(dev); ++ } ++ ++ PKA_DEBUG(PKA_DRIVER, ++ "ring device %d minor:%d\n", ++ ring_dev->device_id, ring_dev->minor); ++ ++ return 0; ++} ++ ++static struct pka_ring_device *pka_drv_del_ring_device(struct device *dev) ++{ ++ struct platform_device *pdev = ++ container_of(dev, struct platform_device, dev); ++ struct pka_platdata *priv = platform_get_drvdata(pdev); ++ struct pka_info *info = priv->info; ++ struct pka_ring_device *ring_dev = info->priv; ++ ++ if (ring_dev) { ++ device_destroy(pka.class, MKDEV(MAJOR(pka.ring_devt), ++ ring_dev->minor)); ++ idr_remove(&pka.ring_idr, ring_dev->minor); ++ } ++ ++ return ring_dev; ++} ++ ++static char *pka_drv_devnode(struct device *dev, umode_t *mode) ++{ ++ if (mode != NULL) ++ *mode = PKA_DEVICE_ACCESS_MODE; ++ return kasprintf(GFP_KERNEL, "pka/%s", dev_name(dev)); ++} ++ ++static int pka_drv_init_class(void) ++{ ++ int ret; ++ ++ idr_init(&pka.ring_idr); ++ /* /sys/class/pka/$RING */ ++ pka.class = class_create(THIS_MODULE, "pka"); ++ if (IS_ERR(pka.class)) ++ return PTR_ERR(pka.class); ++ ++ /* /dev/pka/$RING */ ++ pka.class->devnode = pka_drv_devnode; ++ ++ ret = alloc_chrdev_region(&pka.ring_devt, 0, MINORMASK, "pka"); ++ if (ret) ++ goto err_alloc_chrdev; ++ ++ cdev_init(&pka.ring_cdev, &pka_ring_fops); ++ ret = cdev_add(&pka.ring_cdev, pka.ring_devt, MINORMASK); ++ if (ret) ++ goto err_cdev_add; ++ ++ return 0; ++ ++err_cdev_add: ++ unregister_chrdev_region(pka.ring_devt, MINORMASK); ++err_alloc_chrdev: ++ class_destroy(pka.class); ++ pka.class = NULL; ++ return ret; ++} ++ ++static void pka_drv_destroy_class(void) ++{ ++ idr_destroy(&pka.ring_idr); ++ cdev_del(&pka.ring_cdev); ++ unregister_chrdev_region(pka.ring_devt, MINORMASK); ++ class_destroy(pka.class); ++ pka.class = NULL; ++} ++#endif ++ ++static void pka_drv_get_mem_res(struct pka_device *pka_dev, ++ struct pka_dev_mem_res *mem_res, ++ uint64_t wndw_ram_off_mask) ++{ ++ enum pka_mem_res_idx acpi_mem_idx; ++ ++ acpi_mem_idx = PKA_ACPI_EIP154_IDX; ++ mem_res->wndw_ram_off_mask = wndw_ram_off_mask; ++ ++ /* PKA EIP154 MMIO base address*/ ++ mem_res->eip154_base = pka_dev->resource[acpi_mem_idx]->start; ++ mem_res->eip154_size = pka_dev->resource[acpi_mem_idx]->end - ++ mem_res->eip154_base + 1; ++ acpi_mem_idx++; ++ ++ /* PKA window ram base address*/ ++ mem_res->wndw_ram_base = pka_dev->resource[acpi_mem_idx]->start; ++ mem_res->wndw_ram_size = pka_dev->resource[acpi_mem_idx]->end - ++ mem_res->wndw_ram_base + 1; ++ acpi_mem_idx++; ++ ++ /* PKA alternate window ram base address ++ * Note: Here the size of all the alt window ram is same, depicted by ++ * 'alt_wndw_ram_size' variable. All alt window ram resources are read ++ * here even though not all of them are used currently. ++ */ ++ mem_res->alt_wndw_ram_0_base = pka_dev->resource[acpi_mem_idx]->start; ++ mem_res->alt_wndw_ram_size = pka_dev->resource[acpi_mem_idx]->end - ++ mem_res->alt_wndw_ram_0_base + 1; ++ ++ if (mem_res->alt_wndw_ram_size != PKA_WINDOW_RAM_REGION_SIZE) ++ PKA_ERROR(PKA_DRIVER, ++ "Alternate Window RAM size read from ACPI is incorrect.\n"); ++ ++ acpi_mem_idx++; ++ ++ mem_res->alt_wndw_ram_1_base = pka_dev->resource[acpi_mem_idx]->start; ++ acpi_mem_idx++; ++ ++ mem_res->alt_wndw_ram_2_base = pka_dev->resource[acpi_mem_idx]->start; ++ acpi_mem_idx++; ++ ++ mem_res->alt_wndw_ram_3_base = pka_dev->resource[acpi_mem_idx]->start; ++ acpi_mem_idx++; ++ ++ /* PKA CSR base address*/ ++ mem_res->csr_base = pka_dev->resource[acpi_mem_idx]->start; ++ mem_res->csr_size = pka_dev->resource[acpi_mem_idx]->end - ++ mem_res->csr_base + 1; ++} ++ ++/* ++ * Note that this function must be serialized because it calls ++ * 'pka_dev_register_shim' which manipulates common counters for ++ * pka devices. ++ */ ++static int pka_drv_register_device(struct pka_device *pka_dev, ++ uint64_t wndw_ram_off_mask) ++{ ++ uint32_t pka_shim_id; ++ uint8_t pka_shim_fw_id; ++ struct pka_dev_mem_res mem_res; ++ ++ /* Register Shim */ ++ pka_shim_id = pka_dev->device_id; ++ pka_shim_fw_id = pka_dev->fw_id; ++ ++ pka_drv_get_mem_res(pka_dev, &mem_res, wndw_ram_off_mask); ++ ++ pka_dev->shim = pka_dev_register_shim(pka_shim_id, pka_shim_fw_id, ++ &mem_res); ++ if (!pka_dev->shim) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register shim id=%u\n", pka_shim_id); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int pka_drv_unregister_device(struct pka_device *pka_dev) ++{ ++ if (!pka_dev) ++ return -EINVAL; ++ ++ if (pka_dev->shim) { ++ PKA_DEBUG(PKA_DRIVER, ++ "unregister device shim %u\n", ++ pka_dev->shim->shim_id); ++ return pka_dev_unregister_shim(pka_dev->shim); ++ } ++ ++ return 0; ++} ++ ++/* ++ * Note that this function must be serialized because it calls ++ * 'pka_dev_register_ring' which manipulates common counters for ++ * vfio devices. ++ */ ++static int pka_drv_register_ring_device(struct pka_ring_device *ring_dev) ++{ ++ uint32_t ring_id; ++ uint32_t shim_id; ++ ++ ring_id = ring_dev->device_id; ++ shim_id = ring_dev->parent_device_id; ++ ++ ring_dev->ring = pka_dev_register_ring(ring_id, shim_id); ++ if (!ring_dev->ring) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register ring device %u\n", ring_id); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int pka_drv_unregister_ring_device(struct pka_ring_device *ring_dev) ++{ ++ uint32_t ring_id; ++ ++ if (!ring_dev) ++ return -EINVAL; ++ ++ ring_id = ring_dev->ring->ring_id; ++ ++ if (ring_dev->ring) { ++ PKA_DEBUG(PKA_DRIVER, "unregister ring device %u\n", ring_id); ++ return pka_dev_unregister_ring(ring_dev->ring); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id pka_ring_match[] = { ++ { .compatible = PKA_RING_DEVICE_COMPAT }, ++ {}, ++}; ++ ++static int pka_drv_rng_read(struct hwrng *rng, void *data, size_t max, ++ bool wait) ++{ ++ int ret; ++ ++ struct pka_device *pka_dev = container_of(rng, struct pka_device, rng); ++ uint32_t *buffer = data; ++ ++ ret = pka_dev_trng_read(pka_dev->shim, buffer, max); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, ++ "%s: failed to read random bytes ret=%d", ++ rng->name, ret); ++ return 0; ++ } ++ ++ return max; ++} ++ ++static int pka_drv_probe_device(struct pka_info *info) ++{ ++ struct pka_device *pka_dev; ++ struct device *dev = info->dev; ++ struct device_node *of_node = dev->of_node; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct hwrng *trng; ++ const struct acpi_device_id *aid; ++ struct pka_drv_plat_info *plat_info; ++ uint64_t wndw_ram_off_mask; ++ int ret; ++ enum pka_mem_res_idx acpi_mem_idx; ++ ++ if (!info) ++ return -EINVAL; ++ ++ pka_dev = kzalloc(sizeof(*pka_dev), GFP_KERNEL); ++ if (!pka_dev) ++ return -ENOMEM; ++ ++ mutex_lock(&pka_drv_lock); ++ pka_device_cnt += 1; ++ if (pka_device_cnt > PKA_DRIVER_DEV_MAX) { ++ PKA_DEBUG(PKA_DRIVER, ++ "cannot support %u devices\n", pka_device_cnt); ++ kfree(pka_dev); ++ mutex_unlock(&pka_drv_lock); ++ return -EPERM; ++ } ++ pka_dev->device_id = pka_device_cnt - 1; ++ mutex_unlock(&pka_drv_lock); ++ ++ pka_dev->info = info; ++ pka_dev->device = dev; ++ info->flag = PKA_DRIVER_FLAG_DEVICE; ++ mutex_init(&pka_dev->mutex); ++ ++ for (acpi_mem_idx = PKA_ACPI_EIP154_IDX; ++ acpi_mem_idx < PKA_DEVICE_RES_CNT; acpi_mem_idx++) { ++ pka_dev->resource[acpi_mem_idx] = ++ platform_get_resource(pdev, IORESOURCE_MEM, acpi_mem_idx); ++ } ++ ++ /* Window ram offset mask is platform dependent */ ++ aid = acpi_match_device(pka_drv_acpi_ids, dev); ++ if (!aid) ++ return -ENODEV; ++ ++ plat_info = (struct pka_drv_plat_info *)aid->driver_data; ++ if (plat_info->type <= PKA_PLAT_TYPE_BF2) { ++ wndw_ram_off_mask = PKA_WINDOW_RAM_OFFSET_MASK1; ++ } else { ++ PKA_ERROR(PKA_DRIVER, "Invalid platform type: %d\n", ++ (int)plat_info->type); ++ return -EINVAL; ++ } ++ ++ /* Set interrupts */ ++ ret = platform_get_irq(pdev, 0); ++ pka_dev->irq = ret; ++ if (ret == -ENXIO && of_node) { ++ pka_dev->irq = PKA_IRQ_NONE; ++ } else if (ret < 0) { ++ PKA_ERROR(PKA_DRIVER, ++ "failed to get device %u IRQ\n", pka_dev->device_id); ++ return ret; ++ } ++ ++ /* Register IRQ */ ++ ret = pka_drv_register_irq(pka_dev); ++ if (ret) { ++ PKA_ERROR(PKA_DRIVER, ++ "failed to register device %u IRQ\n", ++ pka_dev->device_id); ++ return ret; ++ } ++ ++ /* Firmware version */ ++ pka_dev->fw_id = plat_info->fw_id; ++ ++ mutex_lock(&pka_drv_lock); ++ ret = pka_drv_register_device(pka_dev, wndw_ram_off_mask); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, "failed to register shim id=%u\n", ++ pka_dev->device_id); ++ mutex_unlock(&pka_drv_lock); ++ return ret; ++ } ++ mutex_unlock(&pka_drv_lock); ++ ++ /* Setup the TRNG, if needed */ ++ if (pka_dev_has_trng(pka_dev->shim)) { ++ trng = &pka_dev->rng; ++ trng->name = pdev->name; ++ trng->read = pka_drv_rng_read; ++ ++ ret = hwrng_register(&pka_dev->rng); ++ if (ret) { ++ PKA_ERROR(PKA_DRIVER, ++ "failed to register trng\n"); ++ return ret; ++ } ++ } ++ ++ info->priv = pka_dev; ++ ++#ifdef BUG_SW_1127083_FIXED ++ /* ++ * Create platform devices (pka-ring) from current node. ++ * This code is reserverd for DT. ++ */ ++ if (of_node) { ++ ret = of_platform_populate(of_node, pka_ring_match, ++ NULL, dev); ++ if (ret) { ++ PKA_ERROR(PKA_DRIVER, ++ "failed to create platform devices\n"); ++ return ret; ++ } ++ } ++#endif ++ ++ return 0; ++} ++ ++static int pka_drv_remove_device(struct platform_device *pdev) ++{ ++ struct pka_platdata *priv = platform_get_drvdata(pdev); ++ struct pka_info *info = priv->info; ++ struct pka_device *pka_dev = (struct pka_device *)info->priv; ++ ++ if (!pka_dev) { ++ PKA_ERROR(PKA_DRIVER, "failed to unregister device\n"); ++ return -EINVAL; ++ } ++ ++ if (pka_dev_has_trng(pka_dev->shim)) ++ hwrng_unregister(&pka_dev->rng); ++ ++ if (pka_drv_unregister_device(pka_dev)) ++ PKA_ERROR(PKA_DRIVER, "failed to unregister device\n"); ++ ++ return 0; ++} ++ ++static int pka_drv_probe_ring_device(struct pka_info *info) ++{ ++ struct pka_ring_device *ring_dev; ++ struct device *dev = info->dev; ++ ++ int ret; ++ ++ if (!info) ++ return -EINVAL; ++ ++ ring_dev = kzalloc(sizeof(*ring_dev), GFP_KERNEL); ++ if (!ring_dev) ++ return -ENOMEM; ++ ++ mutex_lock(&pka_drv_lock); ++ pka_ring_device_cnt += 1; ++ if (pka_ring_device_cnt > PKA_DRIVER_RING_DEV_MAX) { ++ PKA_DEBUG(PKA_DRIVER, "cannot support %u ring devices\n", ++ pka_ring_device_cnt); ++ kfree(ring_dev); ++ mutex_unlock(&pka_drv_lock); ++ return -EPERM; ++ } ++ ring_dev->device_id = pka_ring_device_cnt - 1; ++ ring_dev->parent_device_id = pka_device_cnt - 1; ++ mutex_unlock(&pka_drv_lock); ++ ++ ring_dev->info = info; ++ ring_dev->device = dev; ++ info->flag = PKA_DRIVER_FLAG_RING_DEVICE; ++ mutex_init(&ring_dev->mutex); ++ ++ ret = pka_drv_add_ring_device(ring_dev); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to add ring device %u\n", ++ ring_dev->device_id); ++ kfree(ring_dev); ++ return ret; ++ } ++ ++ mutex_lock(&pka_drv_lock); ++ /* Register ring device */ ++ ret = pka_drv_register_ring_device(ring_dev); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register ring device %u\n", ++ ring_dev->device_id); ++ mutex_unlock(&pka_drv_lock); ++ goto err_register_ring; ++ } ++ mutex_unlock(&pka_drv_lock); ++ ++ info->priv = ring_dev; ++ ++ return 0; ++ ++ err_register_ring: ++ pka_drv_del_ring_device(dev); ++ kfree(ring_dev); ++ return ret; ++} ++ ++static int pka_drv_remove_ring_device(struct platform_device *pdev) ++{ ++ struct pka_ring_device *ring_dev; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ ring_dev = pka_drv_del_ring_device(dev); ++ if (ring_dev) { ++ ret = pka_drv_unregister_ring_device(ring_dev); ++ if (ret) { ++ PKA_ERROR(PKA_DRIVER, ++ "failed to unregister vfio device\n"); ++ return ret; ++ } ++ kfree(ring_dev); ++ } ++ ++ return 0; ++} ++ ++static int pka_drv_of_probe(struct platform_device *pdev, ++ struct pka_info *info) ++{ ++#ifdef BUG_SW_1127083_FIXED ++ struct device *dev = &pdev->dev; ++ ++ int error; ++ ++ error = device_property_read_string(dev, "compatible", &info->compat); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, "cannot retrieve compat for %s\n", ++ pdev->name); ++ return -EINVAL; ++ } ++ ++ if (!strcmp(info->compat, pka_ring_compat)) { ++ PKA_PRINT(PKA_DRIVER, "probe ring device %s\n", ++ pdev->name); ++ error = pka_drv_probe_ring_device(info); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register ring device compat=%s\n", ++ info->compat); ++ return error; ++ } ++ ++ } else if (!strcmp(info->compat, pka_compat)) { ++ PKA_PRINT(PKA_DRIVER, "probe device %s\n", pdev->name); ++ error = pka_drv_probe_device(info); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register device compat=%s\n", ++ info->compat); ++ return error; ++ } ++ } ++ ++ return 0; ++#endif ++ return -EPERM; ++} ++ ++static int pka_drv_acpi_probe(struct platform_device *pdev, ++ struct pka_info *info) ++{ ++ struct acpi_device *adev; ++ struct device *dev = &pdev->dev; ++ ++ int error; ++ ++ if (acpi_disabled) ++ return -ENOENT; ++ ++ adev = ACPI_COMPANION(dev); ++ if (!adev) { ++ PKA_DEBUG(PKA_DRIVER, ++ "ACPI companion device not found for %s\n", ++ pdev->name); ++ return -ENODEV; ++ } ++ ++ info->acpihid = acpi_device_hid(adev); ++ if (WARN_ON(!info->acpihid)) ++ return -EINVAL; ++ ++ if (!strcmp(info->acpihid, pka_ring_acpihid_bf1) ++ || !strcmp(info->acpihid, pka_ring_acpihid_bf2)) { ++ error = pka_drv_probe_ring_device(info); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register ring device %s\n", ++ pdev->name); ++ return error; ++ } ++ PKA_DEBUG(PKA_DRIVER, "ring device %s probed\n", ++ pdev->name); ++ ++ } else if (!strcmp(info->acpihid, pka_acpihid_bf1) ++ || !strcmp(info->acpihid, pka_acpihid_bf2)) { ++ error = pka_drv_probe_device(info); ++ if (error) { ++ PKA_DEBUG(PKA_DRIVER, ++ "failed to register device %s\n", ++ pdev->name); ++ return error; ++ } ++ PKA_PRINT(PKA_DRIVER, "device %s probed\n", pdev->name); ++ } ++ ++ return 0; ++} ++ ++static int pka_drv_probe(struct platform_device *pdev) ++{ ++ struct pka_platdata *priv; ++ struct pka_info *info; ++ struct device *dev = &pdev->dev; ++ ++ int ret; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->lock); ++ priv->pdev = pdev; ++ /* interrupt is disabled to begin with */ ++ priv->irq_flags = 0; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->name = pdev->name; ++ info->version = PKA_DRIVER_VERSION; ++ info->module = THIS_MODULE; ++ info->dev = dev; ++ ++ priv->info = info; ++ ++ platform_set_drvdata(pdev, priv); ++ ++ /* ++ * There can be two kernel build combinations. One build where ++ * ACPI is not selected and another one with the ACPI. ++ * ++ * In the first case, 'pka_drv_acpi_probe' will return since ++ * acpi_disabled is 1. DT user will not see any kind of messages ++ * from ACPI. ++ * ++ * In the second case, both DT and ACPI is compiled in but the ++ * system is booting with any of these combinations. ++ * ++ * If the firmware is DT type, then acpi_disabled is 1. The ACPI ++ * probe routine terminates immediately without any messages. ++ * ++ * If the firmware is ACPI type, then acpi_disabled is 0. All other ++ * checks are valid checks. We cannot claim that this system is DT. ++ */ ++ ret = pka_drv_acpi_probe(pdev, info); ++ if (ret) ++ ret = pka_drv_of_probe(pdev, info); ++ ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, "unknown device\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int pka_drv_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ ++ /* ++ * Little hack here: ++ * The issue here is that the driver data structure which holds our ++ * initialized private data cannot be used when the 'pdev' arguments ++ * points to child device -i.e. vfio device. Indeed, during the probe ++ * function we set an initialized structure called 'priv' as driver ++ * data for all platform devices including parents devices and child ++ * devices. This driver data is unique to each device - see call to ++ * 'platform_set_drvdata()'. However, when we add the child device to ++ * a vfio group through 'vfio_add_group_dev()' call, this function ++ * creates a new driver data for the device - i.e. a 'vfio_device' ++ * structure which includes a field called 'device_data' to hold the ++ * aforementionned initialized private data. So, to retrieve our ++ * private data, we must call 'dev_get_drvdata()' which returns the ++ * 'vfio_device' struct and access its 'device_data' field. However, ++ * this cannot be done before determining if the 'pdev' is associated ++ * with a child device or a parent device. ++ * In order to deal with that we propose this little hack which uses ++ * the iommu_group to distinguich between parent and child devices. ++ * For now, let's say it is a customized solution that works for our ++ * case. Indeed, in the current design, the private data holds some ++ * infos that defines the type of the device. The intuitive way to do ++ * that is as following: ++ * ++ * struct pka_platdata *priv = platform_get_drvdata(pdev); ++ * struct pka_info *info = priv->info; ++ * ++ * if (info->flag == PKA_DRIVER_FLAG_RING_DEVICE) ++ * return pka_drv_remove_ring_device(info); ++ * if (info->flag == PKA_DRIVER_FLAG_DEVICE) ++ * return pka_drv_remove_ring_device(info); ++ * ++ * Since the returned private data of child devices -i.e vfio devices ++ * corresponds to 'vfio_device' structure, we cannot use it to ++ * differentiate between parent and child devices. This alternative ++ * solution is used instead. ++ */ ++ if (dev->iommu_group) { ++ PKA_PRINT(PKA_DRIVER, "remove ring device %s\n", ++ pdev->name); ++ return pka_drv_remove_ring_device(pdev); ++ } ++ ++ PKA_PRINT(PKA_DRIVER, "remove device %s\n", pdev->name); ++ return pka_drv_remove_device(pdev); ++} ++ ++static const struct of_device_id pka_drv_match[] = { ++ { .compatible = PKA_DEVICE_COMPAT }, ++ { .compatible = PKA_RING_DEVICE_COMPAT }, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, pka_drv_match); ++ ++MODULE_DEVICE_TABLE(acpi, pka_drv_acpi_ids); ++ ++static struct platform_driver pka_drv = { ++ .driver = { ++ .name = PKA_DRIVER_NAME, ++ .of_match_table = of_match_ptr(pka_drv_match), ++ .acpi_match_table = ACPI_PTR(pka_drv_acpi_ids), ++ }, ++ .probe = pka_drv_probe, ++ .remove = pka_drv_remove, ++}; ++ ++/* Initialize the module - Register the pka platform driver */ ++static int __init pka_drv_register(void) ++{ ++ int ret; ++ ++ ret = pka_drv_init_class(); ++ if (ret) { ++ PKA_ERROR(PKA_DRIVER, "failed to create class\n"); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&pka_drv); ++ if (ret) { ++ PKA_ERROR(PKA_DRIVER, "failed to register platform driver\n"); ++ return ret; ++ } ++ ++ PKA_PRINT(PKA_DRIVER, "version: " PKA_DRIVER_VERSION "\n"); ++ ++ return 0; ++} ++ ++/* Cleanup the module - unregister the pka platform driver */ ++static void __exit pka_drv_unregister(void) ++{ ++ platform_driver_unregister(&pka_drv); ++ pka_drv_destroy_class(); ++} ++ ++module_init(pka_drv_register); ++module_exit(pka_drv_unregister); ++ ++MODULE_DESCRIPTION(PKA_DRIVER_DESCRIPTION); ++MODULE_VERSION(PKA_DRIVER_VERSION); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_firmware.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_firmware.h +new file mode 100644 +index 000000000..29ea27ce0 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_firmware.h +@@ -0,0 +1,4823 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __DRIVERS_MICA_PKA_FW_H__ ++#define __DRIVERS_MICA_PKA_FW_H__ ++ ++#include ++ ++// ++// Program binaries ++// ++ ++// Align to PKA_BUFFER_RAM_SIZE. This is greater than the actual buffer ++// length so that the image is zero padded. ++static const uint32_t fw0_farm_img_data_buf[2048] = ++{ ++ 0x137001C9, 0x692040FA, 0x55502301, 0x328C0200, ++ 0x5E7000C9, 0x3D7000C8, 0x3670001D, 0x5370001F, ++ 0x746A4010, 0x046B4014, 0x3C621FF8, 0x4B631FF4, ++ 0x2A684000, 0x5A694004, 0x4F601FF6, 0x3F611FF2, ++ 0x5A6A4008, 0x2A6B400C, 0x19621FFA, 0x6D631FF0, ++ 0x0F684034, 0x7070001E, 0x5D34003F, 0x08601FFE, ++ 0x0328000B, 0x52C40047, 0x69240027, 0x04880000, ++ 0x76800047, 0x3380002E, 0x36800047, 0x7A800039, ++ 0xB6800047, 0xDF80003B, 0xD7800027, 0x9B800035, ++ 0xDC80003D, 0xB980003F, 0xB5800041, 0xF36A4018, ++ 0xDA621FFC, 0x9997017D, 0xA4300002, 0xD9D00061, ++ 0xBC30FFFE, 0xFC800056, 0xF36A4018, 0x9A621FFC, ++ 0xD59701CC, 0xA4300002, 0x99D00061, 0xFC30FFFE, ++ 0x99800062, 0xD097026C, 0xD38C0400, 0x8B614018, ++ 0xBC800056, 0xFF97039F, 0xFC800056, 0x9A97039D, ++ 0xFC800056, 0x9D9703A3, 0xBC800056, 0xF89703A1, ++ 0xBC800056, 0xDC970367, 0xFC800056, 0x9D200003, ++ 0xFC800056, 0xB7200023, 0xBC800056, 0xFD7000C8, ++ 0xD2200021, 0xBA8C5000, 0x9B80006F, 0xF5707FC8, ++ 0x84702084, 0xF670001D, 0xDB200000, 0xB6010000, ++ 0xCF220001, 0xB197007F, 0xA0684084, 0xD3340020, ++ 0xA7CC0052, 0xFC20000F, 0xF18C0100, 0xA4300002, ++ 0x99D00061, 0xED601FFC, 0xD5681FF0, 0x926A4014, ++ 0xF6010000, 0xB18C0100, 0x9260400C, 0xF197007F, ++ 0x34681FFC, 0x7C30FFFE, 0x616A1FF6, 0x336B1FF8, ++ 0x44624000, 0x3B634010, 0x076A1FF2, 0x526B1FF4, ++ 0x62624004, 0x1D634014, 0x006A1FFA, 0x7A230000, ++ 0x03624008, 0x7A8C5000, 0x5A63401C, 0x086440C9, ++ 0x5B800003, 0x3B6B1FE4, 0x118B4000, 0x7F8C0480, ++ 0x17BC004B, 0x6D61401C, 0x518B4000, 0x36010000, ++ 0x3C30FFFE, 0x66500000, 0x66500000, 0x26500000, ++ 0x66500000, 0x24300002, 0x102A0002, 0x65614000, ++ 0xAD624010, 0xF4604008, 0xEE218808, 0x93800073, ++ 0xE5631FEC, 0x8B6B4000, 0x846A1FF4, 0xF3604000, ++ 0xC3614004, 0x95634008, 0xAD624010, 0xCB624014, ++ 0xBB218001, 0xD0970073, 0xFA068000, 0x8C6B4008, ++ 0xE6691FF2, 0x92634000, 0x83614004, 0xF4604008, ++ 0xAD624010, 0xD6218200, 0xD0970073, 0xBC6B1FEC, ++ 0x918B4000, 0xE2631FE4, 0xF0681FF2, 0xB56040A0, ++ 0xE5691FF4, 0xB3604000, 0xB4604008, 0xCC614010, ++ 0x138C0400, 0x6470081C, 0x5270881D, 0x20F000A3, ++ 0x7C30FFFE, 0x33490000, 0x34310001, 0x5D200003, ++ 0x48D40071, 0x0931FFFF, 0x146540B4, 0x706B1FFE, ++ 0x216A1FF6, 0x7E33FFFF, 0x56D000BA, 0x336B1FF8, ++ 0x44624000, 0x03624008, 0x3B634010, 0x7F8C0480, ++ 0x17BC004B, 0x5E70011F, 0x6470081C, 0x1270881D, ++ 0x08F000B8, 0x538000BC, 0x7F8C0480, 0x17BC004B, ++ 0x6C6840A0, 0x30694024, 0x2F090000, 0x7FC8017A, ++ 0x23024000, 0x6E2E0001, 0x4B624014, 0x2F31FFFB, ++ 0x47684028, 0x1370001F, 0x3734001F, 0x57184000, ++ 0x592C0001, 0x17020000, 0x24240008, 0x6934FFE0, ++ 0x04300005, 0x65691FF4, 0x506040A2, 0x366040A6, ++ 0x592C0001, 0x2F090000, 0x10C400DF, 0x7A6940A0, ++ 0x0E050000, 0x722DFFFF, 0x6A31FFFE, 0x30510000, ++ 0x30510000, 0x61691FFA, 0x4E050000, 0x322DFFFF, ++ 0x6A31FFFE, 0x30510000, 0x30510000, 0x592C0001, ++ 0x8434FFFE, 0xC4601FEC, 0xF526000C, 0xB0621FEA, ++ 0xD126005F, 0xBA200060, 0xBA230000, 0xCB0B2000, ++ 0xF22DFFFF, 0x816140AA, 0x8F2D0001, 0xEA072000, ++ 0xBF6B1FEA, 0xD4004000, 0xFA30FFFD, 0xAF0AC000, ++ 0xFA230000, 0xA6631FEA, 0x8B0B2000, 0xFA20000C, ++ 0xBA230000, 0xF4290007, 0xF9C400F9, 0x95250007, ++ 0x9B8000FA, 0xED210007, 0xCD084000, 0xB61B4000, ++ 0xF9634088, 0x986940AA, 0xBA30FFFD, 0xCF2D0001, ++ 0xAA072000, 0xF22A0008, 0xD5621FE8, 0xB5008000, ++ 0xEE2E0001, 0xA934FFE0, 0x84300005, 0xD92C0001, ++ 0xF46B1FF0, 0x8B691FEC, 0xA1601FEE, 0xCD074000, ++ 0x92634000, 0xDD33FFFE, 0xC7530000, 0x87530000, ++ 0xC7530000, 0x87530000, 0x85330002, 0xD5634008, ++ 0xB9070000, 0xE52B0003, 0xE4280004, 0x8FC00130, ++ 0x992C0001, 0xDA604010, 0xFF8C0480, 0x97BC004B, ++ 0xDE70011F, 0x9570001C, 0x9270881D, 0xE3F0011F, ++ 0x07691FFE, 0x66684024, 0x4931FFFF, 0x1BD0012F, ++ 0x40691FF6, 0x02140000, 0x3ED00177, 0x4D084000, ++ 0x51694028, 0x2135001F, 0x3930FFFB, 0x57184000, ++ 0x3BC80174, 0x592C0001, 0x40601FE2, 0x1370001F, ++ 0x75008000, 0x3E3CFFFF, 0x18218000, 0x6C110000, ++ 0x1D33FFFE, 0x50340010, 0x57C8013B, 0x0B41C000, ++ 0x27270002, 0x47530000, 0x5180013D, 0x07530000, ++ 0x4B41C000, 0x38681FEE, 0x3A6940A0, 0x5A604010, ++ 0x0B6B4000, 0x7904C000, 0x592C0001, 0x0434FFFE, ++ 0x43614004, 0x34604008, 0x2268401C, 0x7F8C0480, ++ 0x57BC004B, 0x1E70011F, 0x1570001C, 0x6D70821D, ++ 0x07F0014C, 0x7E340008, 0x73C8015E, 0x07691FFE, ++ 0x66684024, 0x0931FFFF, 0x30D0015E, 0x40691FF6, ++ 0x02140000, 0x7ED00177, 0x4D084000, 0x11694028, ++ 0x3930FFFB, 0x6135001F, 0x57184000, 0x3BC80174, ++ 0x592C0001, 0x00601FE2, 0x1370001F, 0x6D691FE8, ++ 0x9F20000E, 0xF4310001, 0xC931FFFF, 0xB4D00166, ++ 0xE42CFFFF, 0x94800162, 0xBC694000, 0xC62207FA, ++ 0xCC6B4008, 0xA46140A8, 0xB26340A4, 0xE36240AC, ++ 0xB16040AE, 0xD77000B2, 0xFF8C0480, 0x97BC004B, ++ 0xF8700484, 0x9CE00171, 0xB8200001, 0xF6800071, ++ 0xBF200009, 0xD370001F, 0xF6800071, 0x9E200005, ++ 0x9370001F, 0xF6800071, 0xFB200007, 0x9370001F, ++ 0xF3C80071, 0x84631FE0, 0xBA230000, 0xE9631FFE, ++ 0x3F970099, 0x433C0001, 0x7CC80185, 0x033C0001, ++ 0x558001CA, 0x37681FFA, 0x136040A4, 0x5D8C0180, ++ 0x57BC004B, 0x1A700184, 0x39E0018A, 0x7D6940A8, ++ 0x096840A2, 0x65614000, 0x592C0001, 0x346B1FF0, ++ 0x5A604010, 0x15634008, 0x1D8C0180, 0x57BC004B, ++ 0x1570001C, 0x5270881D, 0x62691FFC, 0x322DFFFF, ++ 0x17C801AE, 0x54004000, 0x4034FFF0, 0x1A20000B, ++ 0x68CC01CA, 0x2A6A1FEC, 0x0100C000, 0x4D048000, ++ 0x936340A8, 0xF26340A4, 0xFF8C0480, 0x97BC004B, ++ 0xDA700184, 0xB4E001A5, 0xB26040A8, 0xCD048000, ++ 0xDD8C0180, 0x97BC004B, 0x99700284, 0xF0E001AB, ++ 0xB22DFFFF, 0xE8CC01A6, 0xD5681FF0, 0x8B691FEC, ++ 0xCE050000, 0xA16A1FF6, 0xB86B1FE2, 0xF26040A8, ++ 0x856140A4, 0xE36240AC, 0xF4681FFC, 0x862B0002, ++ 0xA42CFFFF, 0xD06340AE, 0xF96040B2, 0x968C5080, ++ 0xD7BC004B, 0xB8700484, 0x9CE001BE, 0xFE201FE8, ++ 0x85500001, 0xE4300002, 0xD36040A4, 0x9B200000, ++ 0xF66040A6, 0x9D8C0180, 0x97BC004B, 0xDA700184, ++ 0xD7E001C8, 0xB8200001, 0x9D6B1FE0, 0xD18B4000, ++ 0x87631FE6, 0xE6691FF2, 0xC06A1FFA, 0x83614004, ++ 0xE5691FF4, 0xB3621FDA, 0xAA614014, 0xD4004000, ++ 0x86240002, 0xC434FFFE, 0xE1601FD8, 0xBA054000, ++ 0xA26A1FF0, 0xCC614010, 0xC4624000, 0xAF060000, ++ 0xEF060000, 0xB1260002, 0x83624008, 0xD6218200, ++ 0x10970073, 0x516B1FF2, 0x6F060000, 0x39070000, ++ 0x74634004, 0x03624008, 0x10970073, 0x57020000, ++ 0x7B694008, 0x15681FF0, 0x3A098000, 0x7A068000, ++ 0x3197007F, 0x78681FD8, 0x476A1FF2, 0x00691FF6, ++ 0x736B1FF8, 0x2F060000, 0x21270001, 0x6537FFFE, ++ 0x2F05C000, 0x746B1FF0, 0x59611FF6, 0x3904C000, ++ 0x1E621FF2, 0x6E601FFA, 0x4C601FF0, 0x138C0400, ++ 0x5997017D, 0x01030000, 0x223F0001, 0x6DCC026A, ++ 0xB18C0100, 0xCF6A1FD8, 0xC3691FF0, 0x94004000, ++ 0xFA098000, 0x8D048000, 0xB197007F, 0xF6010000, ++ 0xEA684000, 0xBA098000, 0xBA068000, 0xF197007F, ++ 0xB36B1FF8, 0xC0691FF6, 0xE1270001, 0xA537FFFE, ++ 0xCE09C000, 0x996B1FD8, 0x876A1FF2, 0xD9611FF6, ++ 0xAF0AC000, 0xDE621FF2, 0xD38C0400, 0x9997017D, ++ 0xBC6B1FDA, 0xCF6A1FD8, 0xC3691FF0, 0x8F631FFA, ++ 0xFA098000, 0x9A611FF0, 0x81030000, 0xE23F0001, ++ 0x2DCC026A, 0x718C0100, 0x54004000, 0x0D048000, ++ 0x5260400C, 0x0D048000, 0x06240002, 0x66691FF2, ++ 0x446A1FF4, 0x3C30FFFE, 0x26500000, 0x66500000, ++ 0x24300002, 0x7197007F, 0x4B624014, 0x2A6B400C, ++ 0x77260001, 0x03691FF0, 0x21280001, 0x6D624010, ++ 0x34604008, 0x43614004, 0x52634000, 0x162A0001, ++ 0x1B058000, 0x6A31FFFE, 0x70510000, 0x30510000, ++ 0x6C078000, 0x1D33FFFE, 0x07530000, 0x47530000, ++ 0x3D218002, 0x50970073, 0x71260002, 0x2D624010, ++ 0x61691FFA, 0x1A6A4008, 0x03614004, 0x43624008, ++ 0x7B218001, 0x10970073, 0x30681FF2, 0x7C694000, ++ 0x04624000, 0x55604004, 0x526B1FF4, 0x22614008, ++ 0x5807C000, 0x27270002, 0x3B634010, 0x56218200, ++ 0x10970073, 0x7B694008, 0x43624008, 0x196B1FD8, ++ 0x25614000, 0x79070000, 0x73681FF4, 0x34634004, ++ 0x5A604010, 0x3B218001, 0x10970073, 0x62624004, ++ 0xA26A1FF0, 0xD8040000, 0xC4624000, 0x83624008, ++ 0xFC604014, 0xB6218018, 0x90970073, 0xE562400C, ++ 0xD38C0400, 0xB8200001, 0x9E6B1FE6, 0xD18B4000, ++ 0xA2631FE4, 0xD5681FF0, 0xD260400C, 0x84691FF8, ++ 0xF4611FDE, 0x846A1FF4, 0xB0621FDC, 0xFA0A4000, ++ 0x820E4000, 0xC5D40277, 0xE3024000, 0x92260003, ++ 0xB336FFFE, 0xC0601FE2, 0xCD048000, 0xA5601FE0, ++ 0xCD048000, 0xBA068000, 0xBB621FF0, 0xCD048000, ++ 0x25601FD6, 0x4B68400C, 0x76970077, 0x226A1FF0, ++ 0x4B68400C, 0x0D048000, 0x36970077, 0x656A1FF8, ++ 0x59681FE2, 0x346B1FF0, 0x3904C000, 0x40691FF6, ++ 0x3197007F, 0x538C0400, 0x476B4024, 0x22631FD2, ++ 0x4D378000, 0x23CC035A, 0x3C681FE0, 0x746B1FF0, ++ 0x3904C000, 0x66691FF2, 0x446A1FF4, 0x3197007F, ++ 0x19681FE2, 0x7C30FFFE, 0x45500001, 0x3C681FE0, ++ 0x66691FF2, 0x3197007F, 0x3D201FD8, 0x66500000, ++ 0xA6500000, 0xE6691FF2, 0xEA31FFFE, 0x87494000, ++ 0xF4310001, 0x80D4035D, 0x8931FFFF, 0xDB200000, ++ 0xC0601FD4, 0x99230001, 0x8F220001, 0xC100C000, ++ 0x97148000, 0xDCC802B2, 0xD9681FD4, 0x8D048000, ++ 0xC0601FD4, 0x8D074000, 0xBA054000, 0xFA068000, ++ 0xA9CC02AB, 0xD9681FE2, 0xF46B1FF0, 0xB904C000, ++ 0x8D210000, 0xCC6A1FDE, 0xDF970361, 0xBC30FFFE, ++ 0xE5480000, 0x8D388000, 0xA2300001, 0xD7D002C2, ++ 0x96250001, 0xF88002BE, 0xF63D0000, 0x94C802F4, ++ 0xD38C0400, 0x8B614018, 0x93218040, 0xD0970073, ++ 0xD9681FD4, 0x8F691FE2, 0xAA31FFFE, 0xC7494000, ++ 0xAA072000, 0xEE210001, 0xE56B4018, 0x9F3FFFFF, ++ 0xE1270001, 0x8D11C000, 0xB22DFFFF, 0xC1164000, ++ 0x996B1FD8, 0xD38C0400, 0xF0694024, 0x95611FD2, ++ 0xBAC802EC, 0xEF1F8000, 0xDEC802E5, 0x96621FD8, ++ 0xF0681FF2, 0x862107F6, 0xBC970360, 0xCF220001, ++ 0x0B624014, 0x7C681FD6, 0x74604008, 0x3B218001, ++ 0x50970073, 0x2A691FD6, 0x19681FE2, 0x446A1FF4, ++ 0x77260001, 0x1F970361, 0x31218010, 0x50970073, ++ 0x19681FE2, 0x4D210000, 0x446A1FF4, 0x37260001, ++ 0x5F970361, 0x13218040, 0x10970073, 0x798002B5, ++ 0x3C681FE0, 0x746B1FF0, 0x7904C000, 0x15604004, ++ 0x19681FE2, 0x7904C000, 0x73604000, 0x0C6A1FDE, ++ 0x7F6B1FDC, 0x1D634014, 0x2F0AC000, 0x570EC000, ++ 0x05D40302, 0x7602C000, 0x6D624010, 0x37218400, ++ 0x50970073, 0x0C691FD2, 0x2F1C4000, 0x44CC030F, ++ 0x6A31FFFE, 0x11484000, 0x033C0001, 0x492D0002, ++ 0x07494000, 0x57184000, 0x79C80350, 0x138C0400, ++ 0x40684020, 0x22300001, 0x18D0035A, 0x64300002, ++ 0x33D0031D, 0x6A684000, 0x5A694004, 0x15604004, ++ 0x25614000, 0x43684010, 0x73694014, 0x3C604014, ++ 0x4C614010, 0x0B6B4000, 0x15634008, 0x47631FD0, ++ 0xB2218020, 0xD0970073, 0xF1D00326, 0xBC681FE0, ++ 0xCF691FE2, 0xB3800328, 0x99681FE2, 0xEA691FE0, ++ 0xC46A1FF4, 0xB7260001, 0x9F970361, 0xD38C0400, ++ 0x916A4024, 0xF2218020, 0xD0970073, 0xBF681FD0, ++ 0xCE0A0000, 0xB7260001, 0xAA691FE0, 0xF46B1FF0, ++ 0xAF05C000, 0xCD1D0000, 0xE2CC033D, 0x99681FE2, ++ 0xAA691FE0, 0xE5601FE0, 0xD6611FE2, 0xBB681FDE, ++ 0xC7601FDC, 0x95621FDE, 0x99681FE2, 0xE6691FF2, ++ 0xBC970360, 0xF46A4010, 0xCD048000, 0xBC30FFFE, ++ 0xD38C0400, 0x844B0000, 0xA6500000, 0xE6500000, ++ 0xC13F0000, 0xBCC802B5, 0xB1218010, 0xD0970073, ++ 0xA22CFFFC, 0xD38C0400, 0xE6500000, 0xB98002B5, ++ 0xCF691FE2, 0xBC681FE0, 0x846A1FF4, 0xF197007F, ++ 0x8B624014, 0xF8200001, 0xCD210000, 0xAA6B400C, ++ 0xAD631FF0, 0xF6800071, 0xD2200017, 0xAD210007, ++ 0xDC800357, 0x9D200003, 0x8321001F, 0xDC800357, ++ 0x046A1FF4, 0x6D624010, 0x4B624014, 0x33604000, ++ 0x43614004, 0x34604008, 0x118B4000, 0x47631FE6, ++ 0x56681FF6, 0x04691FF8, 0x046A1FF4, 0x6E601FCC, ++ 0x3B611FCA, 0x7C621FF8, 0x52260003, 0x3336FFFE, ++ 0x7C621FCE, 0x346B1FF0, 0x2C078000, 0x6C078000, ++ 0x2E631FF6, 0x6C078000, 0x6D631FF0, 0x1097026C, ++ 0x033C0001, 0x72C8037C, 0x433C0001, 0x3980039A, ++ 0x55681FF0, 0x256A1FCE, 0x2C088000, 0x76970077, ++ 0x83691FF0, 0xE56A1FCE, 0xF5034000, 0x94004000, ++ 0xEC078000, 0x92634000, 0xAC088000, 0xEC088000, ++ 0xD4970084, 0x83691FF0, 0xA56A1FCE, 0xD4004000, ++ 0xAC088000, 0xFC30FFFE, 0xC5500001, 0xA7280002, ++ 0xE4300002, 0xAC088000, 0xAC088000, 0xCC601FF0, ++ 0x94970084, 0xE1691FCC, 0xC36A1FCA, 0x99611FF6, ++ 0xBC621FF8, 0xF8200001, 0xD38C0400, 0x9E6B1FE6, ++ 0xD18B4000, 0xAC220000, 0xBE8003A4, 0xD8224000, ++ 0x3E8003A4, 0x79228000, 0x7E8003A4, 0x0D22C000, ++ 0x7F621FFE, 0x07631FE6, 0x3F970099, 0x526B1FF4, ++ 0x44270003, 0x2537FFFE, 0x22631FBE, 0x76010000, ++ 0x033C0001, 0x718C0100, 0x67CC04E2, 0x3E6A40A2, ++ 0x6B6840A8, 0x37260001, 0x1A970658, 0x70681FF2, ++ 0x046A1FF4, 0x5A970658, 0x77260001, 0x3336FFFE, ++ 0x276240A2, 0x416240A6, 0x7D6940A8, 0x2D6A1FBE, ++ 0x70611FBC, 0x13201FC0, 0x13230010, 0x5B058000, ++ 0x2A410000, 0x5F2C0002, 0x452FFFFF, 0x2BCC03BF, ++ 0x56681FC0, 0x2E32FFFC, 0x36970077, 0x7B970638, ++ 0x4F691FD4, 0x30681FF2, 0x0F220001, 0x7197061F, ++ 0x306B1FFE, 0x7E33FFFF, 0x74D0052F, 0x3B6B1FBE, ++ 0x66691FF2, 0x0B6A1FD6, 0x2F05C000, 0x7797062A, ++ 0x00691FC0, 0x4F220001, 0x7E97063D, 0x2D691FDE, ++ 0x0A220004, 0x7E97063D, 0x6A6A1FDA, 0x21691FFA, ++ 0x7797062A, 0x2E691FD8, 0x3B6B1FBE, 0x70681FF2, ++ 0x89220002, 0xF904C000, 0xF904C000, 0xB197061F, ++ 0xD2970628, 0xB06B1FFE, 0xA1691FFA, 0xE31BC000, ++ 0xCAD403EF, 0xBB6B1FBE, 0xA26A1FC6, 0xEF05C000, ++ 0xAF05C000, 0xF797062A, 0xDF8003F2, 0x80691FC0, ++ 0xD5681FC6, 0xB0970614, 0x8B691FDA, 0xF0681FC4, ++ 0xA26A1FC6, 0xD46040AC, 0xE46140A8, 0xA46240A4, ++ 0xBA8C5000, 0xD4700384, 0xFA970605, 0x8D21889C, ++ 0xC5614092, 0xBA8C5000, 0xB1700080, 0xCF691FE2, ++ 0xB597064B, 0xE9204096, 0xC0502A27, 0xA15030A7, ++ 0xE9204096, 0xAA504A52, 0x995024A5, 0xD1970642, ++ 0xEF502E27, 0xBF502084, 0xB7970646, 0xC450292F, ++ 0x91970642, 0xE76B4080, 0xF2370020, 0xA2CC0444, ++ 0xE9503548, 0xA1501CE4, 0xB7970646, 0xF85024A9, ++ 0x91970642, 0xE150A148, 0xC55035A4, 0xB7970646, ++ 0x94502530, 0xD1970642, 0xC7502929, 0x8C5035B3, ++ 0xF7970646, 0xBF502108, 0x91970642, 0xF55025A9, ++ 0x2E502CA6, 0x77970646, 0x4A50288A, 0x11970642, ++ 0x7150B4EB, 0x0C509525, 0x37970646, 0x7B501086, ++ 0x51970642, 0x27502D67, 0x215035AD, 0x77970646, ++ 0x2350198F, 0x51970642, 0x676B4080, 0x00631FEE, ++ 0x715098C4, 0x1E509DB1, 0x37970646, 0x4A50316C, ++ 0x11970642, 0x40509148, 0x4F502CC6, 0x37970646, ++ 0x20503590, 0x51970642, 0x7A5099AB, 0x01194000, ++ 0x5CC80447, 0x3597064B, 0x2D204098, 0x615030A7, ++ 0x37970646, 0x595024A5, 0x51970642, 0x35800408, ++ 0x7A8C5000, 0x34200013, 0x398004E3, 0x7A8C5000, ++ 0x716A4080, 0x3B681FDE, 0x24360020, 0x4ECC04F2, ++ 0x2D6A1FBE, 0x76970077, 0x7B970638, 0x0F220001, ++ 0x6D691FDE, 0x3E97063D, 0x0C691FD2, 0x7B6B1FBE, ++ 0x37681FFA, 0x4F220001, 0x7904C000, 0x3197061F, ++ 0x12970628, 0x7B6B1FBE, 0x66691FF2, 0x086A1FD0, ++ 0x6F05C000, 0x2F05C000, 0x3797062A, 0x6E691FD8, ++ 0xBB6B1FBE, 0xF0681FF2, 0xCF220001, 0xB904C000, ++ 0xF904C000, 0xB197061F, 0x92970628, 0xD8700090, ++ 0xFA970605, 0xBA8C5000, 0xA9204096, 0xEA504A52, ++ 0x815029E5, 0xE9204096, 0xEA504A52, 0xBC502491, ++ 0xD1970642, 0x8150292A, 0xB95020B1, 0xF7970646, ++ 0x9D501264, 0xD1970642, 0xC0502D04, 0xBD5040B0, ++ 0xB7970646, 0xD25024E5, 0xD1970642, 0x8B50A088, ++ 0xDC504130, 0xB7970646, 0xAC502D4B, 0xD1970642, ++ 0x2A504A52, 0x45502924, 0x77970646, 0x27502CEB, ++ 0x51970642, 0x24502E0B, 0x3D5011AA, 0x77970646, ++ 0x7F502108, 0x11970642, 0x2A504A52, 0x45502E6B, ++ 0x37970646, 0x555020C8, 0x51970642, 0x3250AD0B, ++ 0x66502925, 0x11970642, 0x03501E52, 0x5550166B, ++ 0x37970646, 0x4C5019AA, 0x51970642, 0x2A504A52, ++ 0x115020C6, 0x77970646, 0x595024A5, 0x11970642, ++ 0x6A504A52, 0x01502D0F, 0x37970646, 0x4E502884, ++ 0x91970642, 0xCA50296A, 0xD3502188, 0x91970642, ++ 0xE650A509, 0xA4502944, 0x91970642, 0xEA504A52, ++ 0xD95024C9, 0x91970642, 0xAD50A549, 0xD5502144, ++ 0xB7970646, 0xD1502669, 0xD1970642, 0x95681FC6, ++ 0xFA8C5000, 0xA76B4080, 0xBC30FFFE, 0xDF370008, ++ 0x80CC04B7, 0xF320001B, 0xF98004E3, 0x85500001, ++ 0xB06B1FFE, 0xED204098, 0xE31BC000, 0x8DD404C4, ++ 0xFF5010E4, 0xAD204098, 0xB35014E5, 0xF7970646, ++ 0xAB5018E6, 0xD1970642, 0xF18C0100, 0xB180051F, ++ 0xEB5018E6, 0xB46B1FF0, 0x96681FF6, 0xC4691FF8, ++ 0xCC631FCA, 0xAE601FCC, 0x9D611FCE, 0xF0681FC4, ++ 0xA5691FF4, 0xF46B1FC6, 0xCF2D0001, 0x9D611FF8, ++ 0xED631FF0, 0x8F601FF6, 0xBA8C5000, 0xD097026C, ++ 0x956B1FCA, 0xC06A1FCC, 0xC4691FCE, 0xAD631FF0, ++ 0xB8621FF6, 0xDD611FF8, 0xD38C0400, 0x833C0001, ++ 0xE7CC04E2, 0x80691FC0, 0xBA97065F, 0xE5691FC2, ++ 0x3A97065F, 0x7180051F, 0x433C0001, 0x3423001F, ++ 0x44601FEC, 0x00631FEE, 0x2D6A1FBE, 0x47691FFE, ++ 0x55681FF0, 0x01194000, 0x14038000, 0x43D404ED, ++ 0x3A068000, 0x4E06C000, 0x76970077, 0x1D681FEC, ++ 0x596B1FEE, 0x1480052B, 0x0F6A1FEE, 0x4E6B4090, ++ 0x33320005, 0x4D1EC000, 0x6D360001, 0x12C804FB, ++ 0x1920000D, 0x5A230007, 0x598004E4, 0x2D6A1FBE, ++ 0x55681FF0, 0x07691FFE, 0x14038000, 0x7A068000, ++ 0x01194000, 0x47D40503, 0x4E06C000, 0x36970077, ++ 0x61691FFA, 0x15681FF0, 0x046A1FF4, 0x55970616, ++ 0x6D6A1FBE, 0x166B1FFA, 0x15681FF0, 0x6C078000, ++ 0x34634004, 0x4D048000, 0x74604008, 0x26691FF2, ++ 0x446A1FF4, 0x25614000, 0x0B624014, 0x72218020, ++ 0x266A1FFE, 0x50970073, 0x411A8000, 0x0FD40529, ++ 0x3B6B1FBE, 0x55681FF0, 0x5807C000, 0x3904C000, ++ 0x7C30FFFE, 0x05500001, 0x31800529, 0x6D6A1FBE, ++ 0x80691FC0, 0xD1681FFE, 0xD4038000, 0xA3180000, ++ 0xE8D40526, 0xBA068000, 0x8E06C000, 0xD5681FF0, ++ 0xD5970616, 0xBA230000, 0xB8200001, 0xD38C0400, ++ 0xBC634018, 0xDE6B1FE6, 0xD18B4000, 0xAD691FDE, ++ 0xCF220001, 0xBE97063D, 0xA16A1FC0, 0xE1691FFA, ++ 0xB797062A, 0xFB6B1FBE, 0xE1691FFA, 0x8F6A1FD8, ++ 0xAF05C000, 0xF797062A, 0xC76A1FC4, 0x80691FF6, ++ 0xF797062A, 0xBB6B1FBE, 0x80691FF6, 0xEA6A1FDA, ++ 0xAF05C000, 0xF797062A, 0xD1681FFE, 0xA3180000, ++ 0xD3D0054C, 0xAD691FDE, 0xB3681FC2, 0xF6970617, ++ 0xED691FDE, 0x95681FC6, 0xB6970617, 0xDA800558, ++ 0xBB6B1FBE, 0xE1691FFA, 0xC46A1FC2, 0xAF05C000, ++ 0xEF05C000, 0xB797062A, 0xBB6B1FBE, 0xC0691FF6, ++ 0xA26A1FC6, 0xEF05C000, 0xEF05C000, 0xB797062A, ++ 0x98700090, 0xFA970605, 0xFA8C5000, 0xB1700080, ++ 0xE9204096, 0xAA504A52, 0xB15024E4, 0xE9204096, ++ 0x2A504A52, 0x425030A6, 0x51970642, 0x1450B12C, ++ 0x515020F0, 0x37970646, 0x085028B1, 0x51970642, ++ 0x7E50A90A, 0x3E50AD8C, 0x11970642, 0x5050456B, ++ 0x2850BD4A, 0x77970646, 0x676B4080, 0x00631FEE, ++ 0x71700080, 0x0E50352B, 0x11970642, 0x596B1FEE, ++ 0x316A4080, 0x63330006, 0x6BD4057A, 0x35320006, ++ 0x35D005B1, 0x518004F8, 0x6A504A52, 0x0B502D8B, ++ 0x77970646, 0x37502531, 0x11970642, 0x7C50252B, ++ 0xB950210B, 0xF7970646, 0xED5018E5, 0x91970642, ++ 0xEA504A52, 0x99503CCF, 0xB7970646, 0xD1502669, ++ 0xD1970642, 0x8F50A52F, 0x835018CB, 0xD1970642, ++ 0xAA504A52, 0xD2503E69, 0xF7970646, 0x9250112C, ++ 0xD1970642, 0xBF50B5ED, 0x8950326C, 0xD1970642, ++ 0xAA504A52, 0xC15035AA, 0xD1970642, 0xB250B50D, ++ 0x92502533, 0xD1970642, 0xC3501E52, 0x9650166D, ++ 0xD1970642, 0xBB970638, 0xBB6B1FBE, 0xE6691FF2, ++ 0x0B6A1FD6, 0x6F05C000, 0x7797062A, 0x3B6B1FBE, ++ 0x66691FF2, 0x086A1FD0, 0x2F05C000, 0x6F05C000, ++ 0x7797062A, 0x3A970605, 0x3A8C5000, 0x69204096, ++ 0x2A504A52, 0x515020C6, 0x69204096, 0x2A504A52, ++ 0x5580049A, 0x3B970638, 0x3B6B1FBE, 0x66691FF2, ++ 0x0B6A1FD6, 0x6F05C000, 0x7797062A, 0x08691FDC, ++ 0x1D681FDA, 0x70970614, 0x4B691FDA, 0x09220002, ++ 0x7E97063D, 0x08691FDC, 0x15681FC6, 0x76970617, ++ 0x03691FC6, 0x6A220003, 0x7E97063D, 0x3A970605, ++ 0x7A8C5000, 0x31700080, 0x29204096, 0x6A504A52, ++ 0x7F502084, 0x29204096, 0x2A504A52, 0x6C503611, ++ 0x11970642, 0x6A504A52, 0x46502D07, 0x37970646, ++ 0x6C5034AD, 0x11970642, 0x2A504A52, 0x595024A5, ++ 0x37970646, 0x665029B0, 0x51970642, 0x27503144, ++ 0x1A50252F, 0x77970646, 0x4150194A, 0x11970642, ++ 0x745010C8, 0x0750318C, 0x37970646, 0x695028D1, ++ 0x91970642, 0xD2502569, 0xEC5019AD, 0xB7970646, ++ 0xDD501264, 0x91970642, 0x9F50B08C, 0xE8502D29, ++ 0xF7970646, 0xAD5019A6, 0x91970642, 0xEA504A52, ++ 0xB550166C, 0xF7970646, 0xDE502191, 0x91970642, ++ 0xF250AD0B, 0xAD502953, 0x91970642, 0xEA504A52, ++ 0xA950326B, 0xF7970646, 0xDE5011AB, 0x91970642, ++ 0x9950B585, 0xD2502533, 0xD1970642, 0xAA504A52, ++ 0xC75035A9, 0x91970642, 0xB950B54D, 0xC5502E6B, ++ 0x11970642, 0x43501E52, 0x5650166D, 0x11970642, ++ 0x7880059D, 0x2D6A1FBE, 0x00691FC0, 0x4B624014, ++ 0x4B32FFFE, 0x3A098000, 0x25614000, 0x456140A4, ++ 0x0F691FD4, 0x696A1FDC, 0x62614008, 0x25691FF4, ++ 0x62624004, 0x0F2D0001, 0x0C614010, 0x518B4000, ++ 0x046A1FF4, 0x6E2E0001, 0x6D624010, 0x25614000, ++ 0x34604008, 0x538C0400, 0x5570001C, 0x1270881D, ++ 0x5B058000, 0x0D048000, 0x118B4000, 0x73604000, ++ 0xB3681FF4, 0xE2614008, 0xDA604010, 0x938C0400, ++ 0xEA624018, 0x97020000, 0xB4218080, 0xD3800073, ++ 0xED684008, 0x99800634, 0xA5631FEC, 0xE5614000, ++ 0x83624008, 0xF5008000, 0xE9218800, 0x90970073, ++ 0xC46A1FF4, 0x9A970658, 0xAD684008, 0xFC6B1FEC, ++ 0xB26040A8, 0xFA8C5000, 0xDA700184, 0x918B4000, ++ 0x846A1FF4, 0xE9691FBC, 0xED624010, 0x856140A4, ++ 0xD18B4000, 0x94004000, 0xAA31FFFE, 0xD38C0400, ++ 0xBF424000, 0xD9800634, 0xD68C5080, 0x97BC004B, ++ 0xE9204096, 0x918B4000, 0x968C5080, 0xD7BC004B, ++ 0xE9204096, 0xAA504A52, 0x918B4000, 0xD6681FF6, ++ 0xB22DFFFF, 0xE3024000, 0xF736FFF0, 0xB0320003, ++ 0xFC30FFFE, 0xAF060000, 0x874A8000, 0xD4004000, ++ 0x9E34000F, 0xCD120000, 0xC1624090, 0x918B4000, ++ 0x8D048000, 0xFC30FFFE, 0xE6500000, 0xA6500000, ++ 0xE6500000, 0xA6500000, 0x918B4000, 0xE26A1FC6, ++ 0x246140A8, 0x646240A4, 0x718C0100, 0x1A700184, ++ 0x476A1FF2, 0x22624004, 0x046A1FF4, 0x4B624014, ++ 0x65614000, 0x22614008, 0x318C0100, 0x50694080, ++ 0x0C350001, 0x47CC066F, 0x518B4000, 0x2E2E0001, ++ 0x6D624010, 0x32218020, 0x13800073, 0x0079084F ++}; ++ ++static const uint32_t fw0_boot_img_data_buf[] = ++{ ++ 0x3F200503, 0x6E210001, 0x6A710249, 0x38200001, ++ 0x5460B41C, 0x1397008C, 0x0D210000, 0x4931FFFF, ++ 0x6D390001, 0x242CFFFF, 0x00CC0007, 0x736AB1F8, ++ 0x2361B140, 0x6F3A0000, 0x4FCC0013, 0x1F200777, ++ 0x5860B438, 0x1F60B45C, 0x14800017, 0x5D200333, ++ 0x1860B438, 0x5F60B45C, 0x7E60B43C, 0x0520FFFF, ++ 0x3660B420, 0x4D210000, 0x6F68B420, 0x0561B422, ++ 0x4934FEFE, 0x22300001, 0x3660B420, 0x4661B424, ++ 0xA361B426, 0xE761B428, 0xC261B42A, 0x8161B42C, ++ 0xE461B42E, 0xAF61B434, 0x8A61B436, 0xD397008C, ++ 0xCE21A0CA, 0xB9228000, 0xBF424000, 0xE12D0100, ++ 0xA42CFFFF, 0xE8CC002A, 0xCB710449, 0x83B80032, ++ 0xD8224000, 0x98800033, 0xAC220000, 0xC3210045, ++ 0x8661B424, 0xFA230000, 0xF663B42C, 0x9397008C, ++ 0xA9232000, 0xC662B428, 0xD863B434, 0x9269B1F8, ++ 0xCE390000, 0xABCC0040, 0x89210777, 0xF5800041, ++ 0x8B210333, 0xF38C0078, 0xD6BC0076, 0x8E61B438, ++ 0xE42CFFFF, 0x87CC0039, 0x85710649, 0xD397008C, ++ 0xEB21A0C8, 0xAC220000, 0xBF424000, 0xC92D0002, ++ 0xBF424000, 0xCC2D00FE, 0xE42CFFFF, 0x89CC004A, ++ 0xC468B1F8, 0x8D223000, 0x98380000, 0xC0CC005D, ++ 0x96711049, 0xE5B8005A, 0xEF204000, 0xBF222000, ++ 0x91230071, 0xD2800078, 0xDB200000, 0x91230071, ++ 0xD2800078, 0xB7712049, 0x82B80063, 0xF9214000, ++ 0x3A230000, 0x7F222000, 0x79800065, 0x0D210000, ++ 0x7A230000, 0x0C20B424, 0x2C500011, 0x45500001, ++ 0x6850C400, 0x05500001, 0x0161B42C, 0x5363B42E, ++ 0x0E62B434, 0x7C230333, 0x738C0078, 0x16BC0076, ++ 0x7963B438, 0x1B200000, 0x3560B140, 0x69710149, ++ 0x3C8C0000, 0x73800074, 0x7971FF49, 0x33800074, ++ 0x15320001, 0x45367FFF, 0x75C8008B, 0x322A0008, ++ 0x4DC00087, 0x26500000, 0x26500000, 0x66500000, ++ 0xA6500000, 0xE6500000, 0xE6500000, 0xA6500000, ++ 0xE6500000, 0xB5C8008B, 0x9480007B, 0xD3260008, ++ 0xE6500000, 0x932EFFFF, 0x8BCC0088, 0xD18B4000, ++ 0x8468B1F8, 0xDE34000F, 0xDBC80093, 0xA028000A, ++ 0xFAC40093, 0x8124000A, 0x918B4000, 0xF920000A, ++ 0x918B4000, 0xE0000000, 0xE0000000, 0xA0000000 ++}; ++ ++static const uint32_t fw0_master_img_data_buf[] = ++{ ++ 0x3F200503, 0x6E210001, 0x5E605FF4, 0x2D615FF6, ++ 0x5B200000, 0x3260B148, 0x0D205FE0, 0x5C215FE8, ++ 0x7D230008, 0x2F090000, 0x23C000F3, 0x78200001, ++ 0x1460B41C, 0x719700B0, 0x539700BA, 0x0E208000, ++ 0x7560B140, 0x20000000, 0x20000000, 0x60000000, ++ 0x25685FFE, 0x5269B1F8, 0x626B5FFA, 0x353C4600, ++ 0x2CCC0012, 0x793B0000, 0x48D4001D, 0x1B3700FF, ++ 0x5763B47A, 0x1D200333, 0x1860B438, 0x5F60B45C, ++ 0xBE60B43C, 0xFC230003, 0xF722B400, 0x8520FFFF, ++ 0xE9408000, 0x8D210000, 0xB0488000, 0xF1260002, ++ 0xFF418000, 0x8934FEFE, 0xA2300001, 0xD02A0002, ++ 0xA9408000, 0xFE260020, 0xC52FFFFF, 0x8CCC0023, ++ 0xDB200000, 0x9F60B406, 0xB660B416, 0xF560B426, ++ 0x9C60B436, 0xD460B446, 0xFD60B456, 0xA16B5FFC, ++ 0x80210100, 0xE2222F00, 0xF4370080, 0x9FC8003E, ++ 0xCD210000, 0x8D223000, 0x8C20B424, 0xEC500011, ++ 0x85500001, 0xE850C400, 0xC5500001, 0xAA410000, ++ 0xDF2C0002, 0xA6500000, 0x8E62B434, 0xC8205E90, ++ 0xE6220164, 0xAF970F80, 0x9269B1F8, 0xEA220333, ++ 0x9B200000, 0xF38C0078, 0xD1BC00EB, 0xAF62B438, ++ 0xD060B424, 0xB560B426, 0xB9610102, 0xC835000F, ++ 0x9C610100, 0xC568B400, 0xF969B420, 0x99605FCA, ++ 0xA9615FCE, 0xFA3400FF, 0xD6380200, 0x9A605FCC, ++ 0xF235FF00, 0xAB390002, 0x84615FD0, 0xC1970F0D, ++ 0x38200001, 0x57605EA0, 0x502001A0, 0x2B60010C, ++ 0x7A203000, 0x0E60010E, 0x38200001, 0x7260B148, ++ 0x58695EA0, 0x39228000, 0x14004000, 0x433C0001, ++ 0x26CC006F, 0x4262B140, 0x50800075, 0x14004000, ++ 0x463C0004, 0x2DCC0075, 0x2C68B140, 0x543C4000, ++ 0x3560B140, 0x4835000F, 0x4931FFFF, 0x002D0079, ++ 0x26894000, 0x528C1D78, 0x5F800098, 0x378C1D7A, ++ 0x5F800098, 0x3E8C1DF8, 0x1F800098, 0x5B8C1DFA, ++ 0x9F800098, 0xF48C1D7C, 0xDF800098, 0x918C1D7E, ++ 0xDF800098, 0x988C1DFC, 0x9F800098, 0xFD8C1DFE, ++ 0xDF800098, 0xB18C1D79, 0x9F800098, 0xD48C1D7B, ++ 0x9F800098, 0xDD8C1DF9, 0xDF800098, 0xB88C1DFB, ++ 0xDF800098, 0x978C1D7D, 0x9F800098, 0xF28C1D7F, ++ 0x9F800098, 0xFB8C1DFD, 0xDF800098, 0x9E8C1DFF, ++ 0x95B000E9, 0xC8BC0BF6, 0xFDD80CC3, 0x90A00BF7, ++ 0xEBA40C1D, 0xA5A80C38, 0x8CF80EFB, 0xD3E80CE1, ++ 0x17E00107, 0x796A5EA0, 0x7F2300A6, 0x2B360002, ++ 0x5DC800A6, 0x38AC0E86, 0x38215EA2, 0x63220014, ++ 0x44970F9D, 0x3EC80068, 0x30884000, 0x58380000, ++ 0x36C80101, 0x78215EA2, 0x63220014, 0x27800FC0, ++ 0x5B200000, 0x3360B000, 0x3460B008, 0x4F220001, ++ 0x2B2D0008, 0x6D62B010, 0x7B60B01C, 0x08228800, ++ 0x0C62B01C, 0x518B4000, 0x4468B1F8, 0x36635E96, ++ 0x5E34000F, 0x01030000, 0x012B000A, 0x45C000C1, ++ 0x3920000A, 0x41030000, 0x4D210000, 0x0931FFFF, ++ 0x6D390001, 0x242CFFFF, 0x01CC00C3, 0x6361B140, ++ 0x79228000, 0x36010000, 0x10310008, 0x4D39A0CA, ++ 0x3F424000, 0x6C220000, 0x7F424000, 0x06220020, ++ 0x7C2DFFBA, 0x3F424000, 0x2C220000, 0x582DFF7C, ++ 0x3F424000, 0x6B2D0008, 0x7F424000, 0x0F220001, ++ 0x2B2D0008, 0x7F424000, 0x6C220000, 0x0D2D000C, ++ 0x7F424000, 0x08228800, 0x3F424000, 0x43220400, ++ 0xA462B144, 0xD7020000, 0xE13A0200, 0xA462B144, ++ 0xD92C0001, 0x852FFFFF, 0x80CC00C8, 0xEF6B5E96, ++ 0xD18B4000, 0x8222008D, 0x988000FC, 0xE4220089, ++ 0x988000FC, 0xC6220083, 0xD88000FC, 0x85220085, ++ 0xD88000FC, 0xA9220005, 0x988000FC, 0xE0220087, ++ 0x988000FC, 0xCC220007, 0xD88000FC, 0xA6220011, ++ 0x988000FC, 0xC122008B, 0xD88000FC, 0xAD22000B, ++ 0xEA625FF2, 0x99635FF0, 0xB1320008, 0xC562B148, ++ 0xB3D00102, 0xD18B4000, 0xF8200001, 0xB19700B0, ++ 0xD39700BA, 0xBC8C0000, 0x95800105, 0xF9695F20, ++ 0xFE20011B, 0x8E35C000, 0x91C8010E, 0xC9685F24, ++ 0x823D4000, 0xC5CC00A1, 0xDF2300A1, 0xB96A5EA0, ++ 0xE1210080, 0xB336FFFE, 0xA0625EA0, 0xFB655F21, ++ 0x9A8000AB, 0xF9695F20, 0xC9685F24, 0x8E35C000, ++ 0x973DC000, 0xF2C8010F, 0xD18B4000, 0xA9970F20, ++ 0xFBC801BB, 0x90605F24, 0x80685FFC, 0xCD210000, ++ 0x24615F2E, 0x7F340003, 0x5F2C012D, 0x30884000, ++ 0x5B200000, 0x3160B122, 0x30800131, 0x4A6BB124, ++ 0x5C695F22, 0x1B200000, 0x3B370001, 0x4ECC0137, ++ 0x3C65B123, 0x70800131, 0x5C800124, 0x1A800127, ++ 0x7B9700FB, 0x2868B122, 0x3D69B124, 0x7734001F, ++ 0x34310001, 0x6C110000, 0x62D401B1, 0x216B5FFC, ++ 0x0E645F20, 0x4537FF00, 0x67330008, 0x180B0000, ++ 0x4EC001AE, 0x3E6A5F24, 0x3F215F26, 0x462E0040, ++ 0x29408000, 0x7930FFFB, 0x4E2C4000, 0x0F970FDD, ++ 0x7A695F26, 0x1B2C000C, 0x29350003, 0x49CC01AA, ++ 0x7F215F26, 0x1122FFFE, 0x21970FF3, 0x5F695F24, ++ 0x1C2C0004, 0x524A0000, 0x422D0042, 0x3F424000, ++ 0x6E2E0001, 0x0B420000, 0x26971027, 0x64970C53, ++ 0x2C685F26, 0x7E695F28, 0x5B60B408, 0x2861B40A, ++ 0x09685F24, 0x5221B40E, 0x7D60B40C, 0x30510000, ++ 0x52200021, 0x3A60B404, 0x10200040, 0x5360B414, ++ 0x91200164, 0xC7210152, 0xFF2300A6, 0xA9800C7A, ++ 0xEF685F20, 0xB86A5FE8, 0xBA3400FF, 0xD3605F22, ++ 0xEE2E0001, 0xA1625FE8, 0x81030000, 0xF930FFFB, ++ 0xA72C4010, 0xD24A0000, 0xDC2C0004, 0xB3490000, ++ 0xD63B0400, 0x8F2D0001, 0xBA0A4000, 0xF9C40175, ++ 0x8D210000, 0xEA410000, 0xC9685F24, 0xB563B120, ++ 0xBE2C0038, 0xE6500000, 0xE6500000, 0xA6500000, ++ 0xE6500000, 0x802CFFF6, 0x924A0000, 0xE22CFFCA, ++ 0x0A6B5F2E, 0x5B368000, 0x63CC018A, 0x393B0000, ++ 0x50C801A6, 0x392F003C, 0x1D40C000, 0x46685F30, ++ 0x50605F24, 0x158001A6, 0x32605F2E, 0x793B0000, ++ 0x26CC018F, 0x5F605F30, 0x76800191, 0x392F003C, ++ 0x5D40C000, 0x39695F20, 0x2B68B124, 0x4F220001, ++ 0x3A230000, 0x6C3500FF, 0x6C0B4000, 0x2C12C000, ++ 0x17148000, 0x4FCC019F, 0x5A9700F7, 0x11230191, ++ 0x71635F24, 0x10200040, 0x198001B4, 0x69970F20, ++ 0x9EC801B9, 0xD0605F24, 0xEF685F20, 0xBE6A5F24, ++ 0xFA3400FF, 0x9780013E, 0xBA215FDA, 0xE4970F39, ++ 0xDE2301B3, 0xB78001C0, 0xAF685F20, 0xFF9700F5, ++ 0xBA3400FF, 0xF18001AF, 0xFB9700FB, 0xB7380400, ++ 0xD460B120, 0x89685F24, 0x86970F33, 0xDB200000, ++ 0xB96A5EA0, 0xED645F21, 0xCC3A0001, 0xA0625EA0, ++ 0x988000A6, 0xD523019F, 0xDE8001BC, 0x9F23011B, ++ 0xF1635F24, 0xBC2000C0, 0xAD645F21, 0xD88000A6, ++ 0xB5695F32, 0xCE208000, 0xD4150000, 0xB7C801C5, ++ 0xD18B4000, 0xBA605F32, 0xB62001C8, 0xDA8000AB, ++ 0xCC685FD8, 0x9F215FD8, 0x98380000, 0xDAC801ED, ++ 0xA0970F5B, 0xF9605F34, 0xF6010000, 0x9F2C0034, ++ 0xE5480000, 0x9E6A5FEC, 0x81030000, 0xDE34000F, ++ 0xAE2E0001, 0xC7625FEC, 0xEC220000, 0x8A625F3A, ++ 0xBA62013E, 0xC6330004, 0xFF37000F, 0x9A2F01DD, ++ 0xD18B4000, 0xB48003B5, 0x9B80053F, 0xF08006DD, ++ 0x138006EA, 0x53800200, 0x53800200, 0x13800200, ++ 0x53800200, 0x13800200, 0x13800200, 0x53800200, ++ 0x53800200, 0x13800200, 0x13800200, 0x4B800BC6, ++ 0x13800200, 0x79605F34, 0x7A605F32, 0x188000A6, ++ 0x682200C1, 0x15800203, 0x2C2200A3, 0x55800203, ++ 0x2722008F, 0x55800203, 0x45220085, 0x15800203, ++ 0x0B2200C0, 0x55800203, 0x6A2200A0, 0x15800203, ++ 0x492200A1, 0x15800203, 0x23220081, 0x55800203, ++ 0xA0220087, 0xD5800203, 0xEC220000, 0xA3685F32, ++ 0xEF625F38, 0xB3230208, 0x8B341000, 0xE8CC02A0, ++ 0xFB97035E, 0xA0685F34, 0xB66A5F38, 0xDA230218, ++ 0xBC2C0035, 0xF3460000, 0xF6695F34, 0x9D800273, ++ 0xE860013C, 0xB5635F46, 0xBB97035E, 0xF9200215, ++ 0x9C605F36, 0xDE970393, 0xC9CC0263, 0x90970236, ++ 0x856A010C, 0xFA680110, 0xFE2A01A0, 0xB5C801C8, ++ 0xD8380000, 0x8DCC01C8, 0x94620110, 0xE7970C63, ++ 0x0D6A0110, 0x4C20B424, 0x6C500011, 0x05500001, ++ 0x6850C400, 0x05500001, 0x2D5001A0, 0x66500000, ++ 0x4E62B434, 0x0821022C, 0x172301C8, 0x6B940C7D, ++ 0x3E6B0112, 0x672201A0, 0x5C62010C, 0x1B200000, ++ 0x4D6A0110, 0x06600112, 0x23600110, 0x793B0000, ++ 0x0ACC0385, 0x588000A6, 0x79635F38, 0x201A4000, ++ 0x0262B140, 0x6F6B5EA0, 0x57020000, 0x1F3B0004, ++ 0x76635EA0, 0x0D388000, 0x3A605F32, 0x75008000, ++ 0x07300003, 0x75605F4A, 0x75008000, 0x3F30FFF8, ++ 0x4F384001, 0x36605F4C, 0x2832FFFF, 0x5D2E0D06, ++ 0x5D23024A, 0x078A4000, 0x13605F4E, 0x456A010C, ++ 0x102001A0, 0x4D210000, 0x4E0A0000, 0x26970DE4, ++ 0x6B970E02, 0x026B5F32, 0x0A685F4E, 0x7F37000F, ++ 0x343B0100, 0x576A5F34, 0x7263B144, 0x0B420000, ++ 0x1B695F46, 0x5F2C0002, 0x6A410000, 0x136A5F3A, ++ 0x5F2C0002, 0x0B420000, 0x31695F3C, 0x606B5F38, ++ 0x9F2C0002, 0xEA410000, 0xD18B4000, 0xBA20C000, ++ 0xFA605F32, 0xAE970C74, 0xA7220040, 0xCC20B424, ++ 0xEC500011, 0xA0500003, 0xA850C400, 0xC5500001, ++ 0x87500180, 0xE6500000, 0xCE62B434, 0x9E2000A6, ++ 0xC82100A6, 0xBF2300A6, 0x89800C7D, 0xD4635E9C, ++ 0xAD6B5FEE, 0xC5615E98, 0xEC2D0036, 0x91484000, ++ 0xB82F0001, 0xF4635FEE, 0xC0349FFF, 0x88404000, ++ 0xEC348000, 0xB9C80286, 0x912DFFFE, 0xE64A4000, ++ 0x2B2D0008, 0x51484000, 0x41625E9A, 0x30510000, ++ 0x58380000, 0x32C8029C, 0x10605E9E, 0x4A685E98, ++ 0x79215FDC, 0x2A970F4A, 0x21970E86, 0x49685E9E, ++ 0x0D6B5E9C, 0x58380000, 0x6BCC0290, 0x118B4000, ++ 0x586A5E9A, 0x1F215FD8, 0x1336FF00, 0x70D00297, ++ 0x2A970F4A, 0x4D6B5E9C, 0x778001C0, 0x31320008, ++ 0x3C2C0035, 0x73460000, 0x5F695E9E, 0x3D800274, ++ 0x7C9700F3, 0x3C209000, 0x3A605F32, 0x4480101D, ++ 0x8E208000, 0xFA605F32, 0xE480102C, 0xBD635F36, ++ 0xEC685F4A, 0xB9695F4C, 0x8B32FFFE, 0xCD048000, ++ 0xF0C402AB, 0x8F2D0001, 0xA0615F4C, 0xF5605F4A, ++ 0x93320002, 0xE4685F3A, 0xD88002B9, 0xBD635F36, ++ 0xD8380000, 0xBCD002B3, 0x99970354, 0xE4685F3A, ++ 0x8E390000, 0xDDC802B9, 0xE4300002, 0x88404000, ++ 0xBC30FFFE, 0xF6010000, 0xE72D01A0, 0x9F610106, ++ 0xCB32FFFE, 0x9CC80352, 0x94038000, 0xC3330001, ++ 0xAFD402C2, 0xEB2E0004, 0xD40C8000, 0xBD605F3A, ++ 0xD4038000, 0xBF37000F, 0x95C802C9, 0xF736FFF0, ++ 0xE42E0010, 0xAF6B5F40, 0xAC625F3E, 0xCD0B8000, ++ 0x94C402CE, 0xE0625F40, 0xDC6A5F42, 0x9B200000, ++ 0xE93600C0, 0xB5320006, 0x9BC802D6, 0xF12C0040, ++ 0x932EFFFF, 0xF88002D2, 0xEC600104, 0x85970CA6, ++ 0x9E2000A6, 0xE1970CAF, 0xEC970CB6, 0xA7970C63, ++ 0xE3690104, 0xB5680104, 0xAF2D0030, 0xE64A4000, ++ 0x092D0002, 0x704B4000, 0x493EFFFF, 0x0D1EC000, ++ 0x6CCC0322, 0x1A21B424, 0x18510041, 0x7160B428, ++ 0x4A2D0004, 0x30510000, 0x3851C010, 0x53510001, ++ 0x28220038, 0x4E62B434, 0x4C2102DB, 0x3F2300A6, ++ 0x6B940C7D, 0x3920003C, 0x3C60B348, 0x64970C53, ++ 0x27970C63, 0x50680106, 0x7B21B428, 0x356A5F3E, ++ 0x2A6B5FD0, 0x4251E000, 0x53510001, 0x1760B42C, ++ 0x492D0002, 0x30510000, 0x12200311, 0x5763B420, ++ 0x1060B424, 0x4E62B434, 0x6C685F4A, 0x39695F4C, ++ 0x5B60B408, 0x2861B40A, 0x226B5FCC, 0x7721B40C, ++ 0x4251E000, 0x13510001, 0x2B201061, 0x7D63B400, ++ 0x3A60B404, 0x6462B414, 0x5D200003, 0x3E605F50, ++ 0x7020031B, 0x21210325, 0x0A970C7D, 0x7F2300A6, ++ 0x0B940C7A, 0x67685F50, 0x4434FFFE, 0x3E605F50, ++ 0x18380000, 0x71C80320, 0x588000A6, 0x27685F50, ++ 0x4234FFFD, 0x3E605F50, 0x18380000, 0x65CC00A6, ++ 0xA46B5F36, 0xEE800CBD, 0xEA970C83, 0xB62301F2, ++ 0xEE800CBD, 0xBB2302DB, 0xA9800C83, 0xFD635F36, ++ 0xD8380000, 0xB3D0032B, 0x99970354, 0xE4685F3A, ++ 0x8E390000, 0xFBC80331, 0xE4300002, 0x88404000, ++ 0xFC30FFFE, 0xB6010000, 0xA72D01A0, 0xDF610106, ++ 0x8B32FFFE, 0xDCC80352, 0xEF6B5F40, 0xAC625F3E, ++ 0x8D0B8000, 0xF8C4033B, 0xE0625F40, 0x94038000, ++ 0xE6330003, 0x84D4033F, 0xAB2E0004, 0xD40C8000, ++ 0xBD605F3A, 0xE4970C53, 0xEC685F4A, 0xB9695F4C, ++ 0xDB60B408, 0xA861B40A, 0x90680106, 0xF56A5F3E, ++ 0xD221B40E, 0xB0510000, 0xBD60B40C, 0xD2200021, ++ 0xBA60B404, 0xE462B414, 0xC5685F36, 0xA6210341, ++ 0xFF2300A6, 0xA9800C7A, 0xA46B5F36, 0xF88000FB, ++ 0xB5635E90, 0xC16B5F34, 0xE00CC000, 0x844B0000, ++ 0x9F2C0002, 0xE5480000, 0xD4635F4A, 0xAC6B5E90, ++ 0xF6605F4C, 0x918B4000, 0xB96A5F40, 0xDB200000, ++ 0x17605F40, 0x6F3A0000, 0x7ECC0C95, 0x118B4000, ++ 0x4520FFFF, 0x2C2D0036, 0x264A4000, 0x772DFFFA, ++ 0x45625F42, 0x1D34003F, 0x17148000, 0x6CCC01F2, ++ 0x118B4000, 0x664A4000, 0x492D0002, 0x273607FC, ++ 0x57C801F4, 0x13320002, 0x2C088000, 0x4EC001F4, ++ 0x35008000, 0x62300001, 0x6FD40378, 0x2E2E0001, ++ 0x1F30FFFF, 0x518B4000, 0x76635E96, 0x33200102, ++ 0x7E97036D, 0x09600130, 0x06625F44, 0x73200102, ++ 0xBE97036D, 0xEF6B5E96, 0xEF600134, 0xA3625F46, ++ 0xD18B4000, 0xA469010C, 0x9768010E, 0xFD3D01A0, ++ 0xE6CC0390, 0x862E01A0, 0x9C62010C, 0xD8380000, ++ 0x90C8038F, 0xEC088000, 0xE8C001F0, 0x918B4000, ++ 0xD4620110, 0xA7630112, 0x988000A6, 0xD3680100, ++ 0xB6635E96, 0xDB6AB140, 0xEE210001, 0xBA230000, ++ 0xA1280001, 0xD80B0000, 0xCD11C000, 0x94038000, ++ 0xD7174000, 0xBEC803A1, 0xB4310001, 0xE1280001, ++ 0x3EC4039B, 0x6F6B5E96, 0x518B4000, 0x36635E96, ++ 0x6C220000, 0x05625E94, 0x0D6BB140, 0x45690100, ++ 0x78200001, 0x3602C000, 0x35160000, 0x5C6A5E94, ++ 0x02CC03AF, 0x6E2E0001, 0x45625E94, 0x1F30FFFF, ++ 0x722DFFFF, 0x01CC03A9, 0x2F6B5E96, 0x5C6A5E94, ++ 0x118B4000, 0x64625F4E, 0x512C03B8, 0x30884000, ++ 0x13800200, 0x7E8003C8, 0x5C800442, 0x3C800445, ++ 0x56800465, 0x1D800486, 0x3E8004EB, 0x7B8004EE, ++ 0x1B800509, 0x5E80050C, 0x7780052A, 0x13800200, ++ 0x53800200, 0x13800200, 0x13800200, 0x53800200, ++ 0x54230018, 0x0963013C, 0x1A970364, 0x7797037A, ++ 0x276A0130, 0x41030000, 0x4D0B8000, 0x2FC003D1, ++ 0x57020000, 0x106B013C, 0x28685F44, 0x5B695F46, ++ 0x32370020, 0x4DCC03D7, 0x6E2E0001, 0x09625F3C, ++ 0x360E0000, 0x420E4000, 0x4B32FFFE, 0x34970385, ++ 0x5797029D, 0x1B200000, 0x2A210120, 0x5F6A5F44, ++ 0x97970327, 0xDC200008, 0xCC210124, 0xBA6A5F46, ++ 0xD7970327, 0x969702A0, 0xA4685F3A, 0xE4210010, ++ 0xE4300002, 0xA7600128, 0xBA610104, 0xFB97035E, ++ 0xA6970CCB, 0xD0680130, 0xE0690134, 0x8E6A0120, ++ 0xFE6B0124, 0x9A60B010, 0xAA61B014, 0xFE680128, ++ 0x8E69012C, 0xEB2E0068, 0xC462B000, 0xBD2F0068, ++ 0xB463B004, 0xE06A0138, 0xDC2C0068, 0xB460B008, ++ 0xCA2D0068, 0x8461B00C, 0xAA62B018, 0xF168013C, ++ 0xBF2300A6, 0xCD388000, 0xFB60B01C, 0xAF940CD0, ++ 0xCA685F4E, 0x976A5F34, 0x98380000, 0xF5C8040D, ++ 0xF0884000, 0x8E208000, 0xA9408000, 0xDB200000, ++ 0xBF800419, 0xE4685F3A, 0xF069B024, 0xA02E0028, ++ 0xCE390000, 0x90D00409, 0xA4300002, 0xDC2C0068, ++ 0xAF090000, 0xEA31FFFE, 0xC768B028, 0xBF418000, ++ 0xB734001F, 0xE82E0002, 0xE9408000, 0xB5008000, ++ 0xDF2C0002, 0xA6500000, 0xA6500000, 0xC9970CD8, ++ 0x106A5F3C, 0x60685F34, 0x4B32FFFE, 0x33C80202, ++ 0x546B0104, 0x32695F3A, 0x09625F3C, 0x60625F40, ++ 0x600CC000, 0x272D01A0, 0x3A610104, 0x73490000, ++ 0x1F2C0002, 0x65480000, 0x63615F4A, 0x36605F4C, ++ 0x64970C53, 0x2C685F4A, 0x39695F4C, 0x7D60B40C, ++ 0x0E61B40E, 0x75680104, 0x4D210000, 0x2861B40A, ++ 0x1B60B408, 0x506A5F3C, 0x54200081, 0x3A60B404, ++ 0x6462B414, 0x21210430, 0x3F2300A6, 0x4B940C7A, ++ 0x11230202, 0x7880035E, 0x57230028, 0x0963013C, ++ 0x5B8003CA, 0x1A970364, 0x33200102, 0x7E97036D, ++ 0x49600130, 0x06625F44, 0x192C0001, 0x7E605F3C, ++ 0x2E32FFFC, 0x6B2E0004, 0x74970385, 0x1797029D, ++ 0x5B200000, 0x2A210120, 0x1F6A5F44, 0x57970327, ++ 0x1F6A5F44, 0x5C200008, 0x4C210124, 0x17970327, ++ 0x1F6A5F44, 0x72200010, 0x6D210128, 0x17970327, ++ 0x569702A0, 0x24685F3A, 0x23210018, 0x64300002, ++ 0x8160012C, 0xFA610104, 0xD823000A, 0x8963013C, ++ 0xD28003EB, 0x9A970364, 0xB797037A, 0xE8685F44, ++ 0xF60E0000, 0x8B32FFFE, 0xB4970385, 0xD797029D, ++ 0x9B200000, 0xEA210120, 0xDF6A5F44, 0x97970327, ++ 0xFA6A5F46, 0x9C200008, 0x8C210124, 0xD7970327, ++ 0x969702A0, 0xE4685F3A, 0xE76A0130, 0x976B0134, ++ 0xA4300002, 0xE7600128, 0xD70EC000, 0x8B32FFFE, ++ 0xC9625F3C, 0xAA208009, 0xB9970210, 0xC1970D7E, ++ 0x1F680148, 0x61970E49, 0x4D210000, 0x316A5F5C, ++ 0x72200010, 0x2F800E66, 0x03208100, 0x6860013C, ++ 0x5A970364, 0x3797037A, 0x316B0130, 0x7E695F44, ++ 0x180B0000, 0x4EC001F4, 0x4434FFFE, 0x17C801F4, ++ 0x420E4000, 0x0B32FFFE, 0x34970385, 0x5797029D, ++ 0x1B200000, 0x6A210120, 0x5F6A5F44, 0x17970327, ++ 0x3A6A5F46, 0x5C200008, 0x4C210124, 0x17970327, ++ 0x569702A0, 0x016A0134, 0x09690124, 0x532EFFFF, ++ 0x820D8000, 0xEA31FFFE, 0xE72D01A0, 0xA64A4000, ++ 0xC92D0002, 0x87494000, 0xB168013C, 0xE01A4000, ++ 0xD3C801FA, 0xB2695F3A, 0x816A0134, 0xF2310002, ++ 0xB1610128, 0xF4340100, 0xFAC804BA, 0xB16B0130, ++ 0xF5008000, 0x8D0B8000, 0xB82F0001, 0xEE2E0001, ++ 0xA2300001, 0xFBD004B7, 0xEE2E0001, 0x820D8000, ++ 0x9761012C, 0xD70EC000, 0xCB32FFFE, 0x89625F3C, ++ 0xF168013C, 0xB9970210, 0x81970D7E, 0xC669015C, ++ 0xB968014C, 0xE2350100, 0xDCC804E4, 0xA1970E49, ++ 0xD1520000, 0xAB2E0004, 0xA3690168, 0xDF680148, ++ 0xCE390000, 0x91D004CD, 0xAF090000, 0xEA31FFFE, ++ 0x918004CE, 0xD8218000, 0xC2685F52, 0x952EFFFC, ++ 0xFF418000, 0xAA381000, 0x9B605F52, 0xC797101D, ++ 0xA06A0154, 0xD068015C, 0xCD210000, 0x8B32FFFE, ++ 0xB4340100, 0xF2200010, 0xFCC804E3, 0x8F970E67, ++ 0xDF680148, 0xAF69014C, 0xB16A5F5C, 0xEF090000, ++ 0x2A31FFFE, 0x7A0A4000, 0x75200018, 0x2F800E66, ++ 0x576A5F58, 0x202E0028, 0x11520000, 0x51520000, ++ 0x51520000, 0x11520000, 0x168004C6, 0x40208200, ++ 0x2860013C, 0x59800488, 0x70200088, 0x2860013C, ++ 0x5A970364, 0x21361F00, 0x31320008, 0x79620138, ++ 0x33200102, 0x7E97036D, 0x49600130, 0x366B0138, ++ 0x06625F44, 0x793B0000, 0x506B013C, 0x29CC04FD, ++ 0x7F800500, 0x13370040, 0x02CC0500, 0x592C0001, ++ 0x3E605F3C, 0x760E0000, 0x4B32FFFE, 0x34970385, ++ 0x5B200000, 0x2A210120, 0x1F6A5F44, 0x772303E6, ++ 0x54800327, 0x17200048, 0x2860013C, 0x568004F0, ++ 0x1A970364, 0x73200102, 0x7E97036D, 0x09600130, ++ 0x46625F44, 0x0D32FFFD, 0x34970385, 0x5797029D, ++ 0x1B200000, 0x6A210120, 0x5F6A5F44, 0x17970327, ++ 0x1F6A5F44, 0x5C200008, 0x4C210124, 0x17970327, ++ 0x569702A0, 0x36200522, 0x13605F4E, 0x55230400, ++ 0x8963013C, 0xD28003EB, 0xD669B020, 0xA02E0028, ++ 0xD1520000, 0x91520000, 0x91520000, 0xFF418000, ++ 0xD1230202, 0x8A800CD8, 0x9A970364, 0xD52001FF, ++ 0xBE97036D, 0xC9600130, 0xFE605F3C, 0x97020000, ++ 0xC6625F44, 0x8B32FFFE, 0xB4970385, 0xDB200000, ++ 0xAA210120, 0xDF6A5F44, 0xD7970327, 0x9B200000, ++ 0xBD605F3A, 0xE7600128, 0xE4210010, 0xBA610104, ++ 0xCC230808, 0x8963013C, 0x928003EB, 0xC1030000, ++ 0xA637FFF8, 0xEECC0200, 0xF52C0544, 0xB0884000, ++ 0xD580054C, 0xBC800593, 0x9A800604, 0xD3800200, ++ 0xD780061D, 0xB380064E, 0x93800200, 0xD3800200, ++ 0x8320FFFC, 0xF9970365, 0xE1361F00, 0xB2C801F6, ++ 0xF1320008, 0xB9620138, 0xBF2A0011, 0xD3C401F6, ++ 0xB797037A, 0xE2300001, 0xDCD00558, 0xA82E0002, ++ 0xB2347FFF, 0xD7C801F4, 0xD7680138, 0xA3625F46, ++ 0xF6010000, 0x92290003, 0xBAC40560, 0xDD200003, ++ 0x3C2C0003, 0x63018000, 0x6A072000, 0x393B0000, ++ 0x4ECC01F8, 0x3E695F44, 0x242E0010, 0x420E4000, ++ 0x442A0800, 0x3A6A5F46, 0x17C401F8, 0x6832FFFF, ++ 0x020E4000, 0x4B32FFFE, 0x74970385, 0x1797029D, ++ 0x5B200000, 0x2A210120, 0x0A6B5F42, 0x5F6A5F44, ++ 0x03330001, 0x76D00578, 0x74230579, 0x14800327, ++ 0x319702AF, 0x4A6B5F42, 0x5C200008, 0x0C210124, ++ 0x7A6A5F46, 0x05330002, 0x36D00581, 0x51230582, ++ 0x94800327, 0xF19702AF, 0xC56B5F3A, 0xBA6A5F46, ++ 0xED210128, 0xB5635F46, 0xB2200010, 0xD7970327, ++ 0xD69702A0, 0xAC6B5F46, 0xBE680128, 0xC16A0134, ++ 0x8160012C, 0xCB32FFFE, 0xDC635F3A, 0x89625F3C, ++ 0xE920E000, 0xBE2305FD, 0xBA800210, 0xE520FFF8, ++ 0xB9970365, 0xE1361F00, 0xF2C801F6, 0xB1320008, ++ 0xB9620138, 0xFF2A0011, 0xD3C401F6, 0x92200082, ++ 0xFE97036D, 0x89600130, 0x86625F44, 0xD2200082, ++ 0x3E97036D, 0x6F600134, 0x62300001, 0x3AD005A5, ++ 0x682E0002, 0x32347FFF, 0x17C801F4, 0x57680138, ++ 0x63625F46, 0x36010000, 0x12290003, 0x5FC405AD, ++ 0x1D200003, 0x792C0006, 0x63018000, 0x2A072000, ++ 0x793B0000, 0x0ECC01F8, 0x3E695F44, 0x76680134, ++ 0x242E0010, 0x4931FFFF, 0x420E4000, 0x042A0800, ++ 0x17C401F8, 0x57020000, 0x4B32FFFE, 0x360E0000, ++ 0x420E4000, 0x082E0005, 0x0B32FFFE, 0x74970385, ++ 0x1797029D, 0x5B200000, 0x6A210120, 0x0A6B5F42, ++ 0x5F6A5F44, 0x03330001, 0x3CD005CA, 0x6832FFFF, ++ 0x7D2305CD, 0x14800327, 0x319702AF, 0x5F6A5F44, ++ 0x109702A3, 0x4A6B5F42, 0x5C200008, 0x0C210124, ++ 0x7A6A5F46, 0x05330002, 0x34D005D6, 0x6832FFFF, ++ 0x322305D9, 0x54800327, 0x719702AF, 0x3A6A5F46, ++ 0x109702A3, 0x49690124, 0x7A6A5F46, 0x2A31FFFE, ++ 0x672D01A0, 0x11484000, 0x0B32FFFE, 0x420D8000, ++ 0xB04B4000, 0xDA340001, 0xF5C801FE, 0xBB370001, ++ 0xF5C801FE, 0x816A0134, 0xB2200010, 0xCA6B5F42, ++ 0xED210128, 0xA6330003, 0xB6D005ED, 0xD12305EE, ++ 0x94800327, 0xF19702AF, 0xE4685F3A, 0x816A0134, ++ 0xD3605F4E, 0xB6200028, 0x8B21012C, 0xE832FFFF, ++ 0x97970327, 0xD69702A0, 0xCA685F4E, 0x816A0134, ++ 0xBD605F3A, 0xFC209000, 0xCD32FFFD, 0x89625F3C, ++ 0xF9970210, 0x81970D7E, 0xB968014C, 0xE1970E49, ++ 0x0D210000, 0x716A5F5C, 0x75200018, 0x2F800E66, ++ 0x5A970364, 0x3797037A, 0x096B5F44, 0x570EC000, ++ 0x4B32FFFE, 0x34970385, 0x1797029D, 0x5B200000, ++ 0x2A210120, 0x5F6A5F44, 0x57970327, 0x1C200008, ++ 0x4C210124, 0x3A6A5F46, 0x17970327, 0x569702A0, ++ 0x056B5F3A, 0x416A0134, 0x45330002, 0x2063012C, ++ 0x0B32FFFE, 0x49625F3C, 0x5B20F000, 0x3E2305FD, ++ 0x7A800210, 0x0620FFF9, 0x39970365, 0x45625F42, ++ 0x892D0002, 0xF5200018, 0xFE97036D, 0xAF600134, ++ 0xC434FFFE, 0x97C801F4, 0xA82E0002, 0xE3625F46, ++ 0xF420013C, 0xB3508000, 0x85500001, 0xF1290002, ++ 0x91484000, 0xD4038000, 0xCD32FFFD, 0x970EC000, ++ 0xFF340003, 0x90605F48, 0x8B32FFFE, 0xF4970385, ++ 0x9797029D, 0xFA6A5F46, 0xE86B5F48, 0xB5008000, ++ 0xA832FFFF, 0xFB370001, 0xDBC8063C, 0xB60E0000, ++ 0xEA210120, 0x9B200000, 0x97970327, 0xE86B5F48, ++ 0xBA6A5F46, 0xFB370001, 0xCCCC0675, 0x96230675, ++ 0xE4685F3A, 0x9701C000, 0xB12C01A0, 0xC5500001, ++ 0xCB32FFFE, 0x902A0002, 0xAF970F80, 0xC92801A0, ++ 0xBD605F3A, 0xE6894000, 0xE520FFF8, 0xB9970365, ++ 0xC5625F42, 0xB5200018, 0xBE97036D, 0xC9600130, ++ 0x86625F44, 0xF5200018, 0xFE97036D, 0xAF600134, ++ 0x8434FFFE, 0xD7C801F4, 0xE82E0002, 0xA3625F46, ++ 0xF420013C, 0x81509000, 0x85500001, 0xF1290002, ++ 0x11484000, 0x7E695F44, 0x5C340002, 0x10605F48, ++ 0x6832FFFF, 0x14038000, 0x170EC000, 0x570EC000, ++ 0x420E4000, 0x0B32FFFE, 0x34970385, 0x5797029D, ++ 0x1B200000, 0x6A210120, 0x4A6B5F42, 0x1F6A5F44, ++ 0x43330001, 0x14D00674, 0x16230675, 0x54800327, ++ 0x319702AF, 0x4A6B5F42, 0x7A6A5F46, 0x1C200008, ++ 0x05330002, 0x56D00680, 0x63018000, 0x2832FFFF, ++ 0x420E4000, 0x0C210124, 0x34230686, 0x54800327, ++ 0x8C210124, 0xF19702AF, 0xFA6A5F46, 0x909702A3, ++ 0xFA6A5F46, 0x909702A3, 0x8A6B5F42, 0xFA6A5F46, ++ 0xED210128, 0xA6330003, 0xBED006AD, 0xE86B5F48, ++ 0xB5008000, 0xE832FFFF, 0xFB370001, 0x9FC80691, ++ 0xF60E0000, 0xB2200010, 0x97970327, 0xE86B5F48, ++ 0xBA6A5F46, 0xFB370001, 0xEDCC06B6, 0xA769013C, ++ 0xA0685F34, 0xFA6A5F46, 0xD13D9000, 0x86CC06AB, ++ 0xD72C0028, 0x844B0000, 0x9F2C0002, 0xF3490000, ++ 0x1F2C0002, 0x761B4000, 0x73490000, 0x1F2C0002, ++ 0x761B4000, 0x33490000, 0x36200028, 0x761B4000, ++ 0x7EC806AB, 0x372306B6, 0x14800327, 0x772306B6, ++ 0x11800644, 0x72200010, 0x719702AF, 0x3A6A5F46, ++ 0x509702A3, 0x286B5F48, 0x3A6A5F46, 0x7B370001, ++ 0x1CC80697, 0x509702A3, 0x569702A0, 0x3E6A5F48, ++ 0x24685F3A, 0x6B360002, 0x5EC806C0, 0x3A6A5F46, ++ 0x60690134, 0x2832FFFF, 0x020E4000, 0x4B32FFFE, ++ 0x09625F3C, 0x64300002, 0x4160012C, 0x3168013C, ++ 0x79970210, 0x36695F58, 0x0A2D0032, 0x51484000, ++ 0x5C340002, 0x0CCC06D6, 0x206A0154, 0x5D20A000, ++ 0x14038000, 0x43330001, 0x4CD406D0, 0x2E2E0001, ++ 0x682E0002, 0x3E33FFFF, 0x170EC000, 0x4B32FFFE, ++ 0x28625F5C, 0x4E970D6A, 0x41970D7E, 0x3968014C, ++ 0x21970E49, 0x4D210000, 0x716A5F5C, 0x35200018, ++ 0x6F800E66, 0x01030000, 0x2637FFF8, 0x6ECC0200, ++ 0xB32C06E2, 0xF0884000, 0xF38006ED, 0x978007A7, ++ 0xE38009AE, 0xAE800A87, 0x93800200, 0xD78007A7, ++ 0xD3800200, 0xAE800A87, 0x98380000, 0xEECC0200, ++ 0x8D800BC5, 0xC320FFFC, 0xF9970365, 0x892D0002, ++ 0xF5200018, 0xBE97036D, 0x89600130, 0xEF600134, ++ 0x8434FFFE, 0xD7C801F4, 0xE82E0002, 0xB1290002, ++ 0x91484000, 0xE3625F46, 0xDA340001, 0x90605F48, ++ 0xF5008000, 0xBA30FFFD, 0xB60E0000, 0xF60E0000, ++ 0x8B32FFFE, 0xF4970385, 0xD797029D, 0x9B200000, ++ 0xEA210120, 0x8A6B5F42, 0xBA6A5F46, 0xC3330001, ++ 0xF6D0070B, 0xB723070C, 0x94800327, 0xF19702AF, ++ 0xA897097D, 0xFA6A5F46, 0xF6200028, 0x8D210000, ++ 0xD7970327, 0x969702A0, 0x8D685F46, 0xDB695F46, ++ 0xBA30FFFD, 0xF50C4000, 0xE0600120, 0xAA31FFFE, ++ 0x90610124, 0xC16A0134, 0xFC30FFFE, 0xB12C01A0, ++ 0xE832FFFF, 0x8D210000, 0x844B0000, 0xDF2C0002, ++ 0x1419C000, 0x532EFFFF, 0x61CC071E, 0x1235FFFE, ++ 0x50C801FC, 0x26970CCB, 0x20690134, 0x4E6A0120, ++ 0x7E6B0124, 0x21208400, 0x2B2E0068, 0x7D2F0068, ++ 0x0C61B010, 0x4462B000, 0x7463B004, 0x3B60B01C, ++ 0x7F2300A6, 0x2F940CD0, 0x1669B020, 0x72310002, ++ 0x14D00737, 0x49970CD8, 0x558001FC, 0x09970CD8, ++ 0x0D685F46, 0x6C220000, 0x46600124, 0x36010000, ++ 0x6A31FFFE, 0x170D0000, 0x31610128, 0x630D4000, ++ 0x170D0000, 0x5761012C, 0x49625F3C, 0x38200001, ++ 0x4D60013E, 0x3C209000, 0x39970210, 0x5D20A000, ++ 0x4E970D6A, 0x14680164, 0x286A0148, 0x58380000, ++ 0x20D00E47, 0x6F69014C, 0x630E8000, 0x17610140, ++ 0x71620148, 0x3A098000, 0x3661014C, 0x6A31FFFE, ++ 0x31610144, 0x40208200, 0x4D970D6C, 0x35680168, ++ 0x0E6A014C, 0x58380000, 0x60D00E47, 0x09690148, ++ 0x71620148, 0x3A098000, 0x17610140, 0x7A098000, ++ 0x8B32FFFE, 0xC20D8000, 0xF661014C, 0x9B20F000, ++ 0xCD970D6C, 0x9F680148, 0x8E690140, 0xEC220000, ++ 0xD0620144, 0xA060014C, 0x970D0000, 0xD7610140, ++ 0x9930FFFC, 0xC6600148, 0xED208001, 0x8D970D6C, ++ 0xE86A0148, 0xB968014C, 0xB66B0154, 0xF6620140, ++ 0xB6010000, 0xFA30FFFD, 0xE7600144, 0xA2300001, ++ 0x8E0A0000, 0xC20D8000, 0xD0610148, 0x810FC000, ++ 0xC9630150, 0xA7208010, 0x8D970D6C, 0xD4680164, ++ 0x0E690140, 0x58380000, 0x60D00E47, 0x286A0148, ++ 0x7968014C, 0x106B0150, 0x10610148, 0x76620140, ++ 0x782F0001, 0x09630150, 0x0E0A0000, 0x50620144, ++ 0x2D208001, 0x4D970D6C, 0x466A0150, 0x366B0154, ++ 0x7968014C, 0x09690148, 0x170EC000, 0x5F620150, ++ 0x096A0144, 0x57610140, 0x4E0A0000, 0x31620148, ++ 0x200F0000, 0x5D33FFFE, 0x7E635F5C, 0x3C30FFFE, ++ 0x67600144, 0x00208200, 0x0D970D6C, 0x41970D7E, ++ 0xA3690168, 0xF16A5F5C, 0xCE390000, 0xA0D00E47, ++ 0xE8970E5E, 0xB5200018, 0xAF800E66, 0xE020FFFD, ++ 0xF9970365, 0x892D0002, 0xB5200018, 0xFE97036D, ++ 0x89600130, 0xEF600134, 0xC434FFFE, 0x97C801F4, ++ 0xE82E0002, 0xB1290002, 0x91484000, 0xE3625F46, ++ 0x9C340002, 0xD0605F48, 0xF5008000, 0xA3018000, ++ 0xBC30FFFE, 0xCD32FFFD, 0xF60E0000, 0x820E4000, ++ 0xCB32FFFE, 0xB4970385, 0x9797029D, 0xE897097D, ++ 0xBA6A5F46, 0xF6200028, 0xCD210000, 0xA832FFFF, ++ 0xD7970327, 0x9B200000, 0xBA6A5F46, 0xCD210000, ++ 0xE832FFFF, 0x97970327, 0x969702A0, 0xFA6A5F46, ++ 0x92970644, 0xDB695F46, 0xCD685F46, 0xAC31FFFD, ++ 0xF6610120, 0xB4310001, 0xAF090000, 0xD0610124, ++ 0xA6970CCB, 0xE0690134, 0xCE6A0120, 0x8C61B010, ++ 0xAB2E0068, 0xC462B000, 0xC362B008, 0xB8208808, ++ 0xFB60B01C, 0xBF2300A6, 0xAF940CD0, 0xF069B024, ++ 0x0E390000, 0x62D00889, 0x49690124, 0x21208400, ++ 0x4A2D0068, 0x0361B004, 0x3B60B01C, 0x7F2300A6, ++ 0x6F940CD0, 0x1669B020, 0x32310002, 0x5AD40889, ++ 0x1B695F46, 0x4E6A0120, 0x78208808, 0x020E4000, ++ 0x57620120, 0x2B2E0068, 0x0462B000, 0x4362B008, ++ 0x3B60B01C, 0x7F2300A6, 0x6F940CD0, 0x3069B024, ++ 0x0E390000, 0x62D00889, 0x61208400, 0x3B60B01C, ++ 0x7F2300A6, 0x2F940CD0, 0x1669B020, 0x72310002, ++ 0x9AD40889, 0xC9970CD8, 0xCD685F46, 0xAF690120, ++ 0xE7600128, 0xBC30FFFE, 0x970D0000, 0xD761012C, ++ 0xDD9703A3, 0xA8615F3C, 0x9B20F000, 0xD02A0002, ++ 0xA5C4088B, 0xDF695F48, 0xCA350002, 0xBCCC088B, ++ 0xF9970210, 0x83970956, 0xA0970961, 0xE06A0154, ++ 0xB968014C, 0xF96B0140, 0xDF620150, 0x89690148, ++ 0xA7630148, 0xD80B0000, 0xC6630144, 0x9F30FFFF, ++ 0xEF090000, 0x97610140, 0xAD208001, 0xCD970D6C, ++ 0x2A970970, 0x7968014C, 0x6F6A0140, 0x09690148, ++ 0x766B0154, 0x0E0A0000, 0x1762014C, 0x5F30FFFF, ++ 0x570D0000, 0x17610140, 0x22300001, 0x570D0000, ++ 0x10610148, 0x5B200000, 0x67600144, 0x09630150, ++ 0x7C209000, 0x0E970D6A, 0x1F680148, 0x4E690140, ++ 0x0E6A014C, 0x4D084000, 0x6060014C, 0x10610148, ++ 0x36620140, 0x76010000, 0x5F30FFFF, 0x170D0000, ++ 0x7E610150, 0x3F208800, 0x0D970D6C, 0x7968014C, ++ 0x2F6A0140, 0x49690148, 0x766B0154, 0x0E0A0000, ++ 0x5762014C, 0x1F30FFFF, 0x2F090000, 0x57610140, ++ 0x7C30FFFE, 0x0E0A0000, 0x31620148, 0x49630150, ++ 0x3C209000, 0x4E970D6A, 0x7968014C, 0x09690148, ++ 0x6F6A0140, 0x06600148, 0x0D084000, 0x54038000, ++ 0x360E0000, 0x5762014C, 0x64300002, 0x200F0000, ++ 0x20630140, 0x4E208000, 0x4E970D6A, 0x1D20A000, ++ 0x4E970D6A, 0x17680154, 0x0E6A014C, 0x76010000, ++ 0xB4310001, 0xF5D40863, 0xD92C0001, 0x9F2C0002, ++ 0xE060014C, 0xB6620140, 0xB6010000, 0xDF30FFFF, ++ 0xF50C4000, 0xA7600144, 0xB6010000, 0xDF30FFFF, ++ 0x970D0000, 0xD0610148, 0xC0208200, 0x8D970D6C, ++ 0xDF680148, 0x986B014C, 0xA06A0154, 0xC1600140, ++ 0xB6010000, 0xFC30FFFE, 0xDC605F5A, 0x8E09C000, ++ 0xB1610144, 0xCB32FFFE, 0xE8625F5C, 0xA1208400, ++ 0xCD970D6C, 0x81970D7E, 0xA8970E5E, 0xC16B5F58, ++ 0x056A0160, 0x7E2F0034, 0x654BC000, 0x0B420000, ++ 0x7E370004, 0x34CC0D3E, 0x316A5F5C, 0x75200018, ++ 0x6F800E66, 0x09970CD8, 0x168001FA, 0x6860013C, ++ 0x3B97035E, 0x61230939, 0x75635F46, 0x0C200891, ++ 0x5C605F36, 0x1E970393, 0x09CC0263, 0x50970236, ++ 0x2E230897, 0x75635F46, 0x7C800213, 0x1F680148, ++ 0x0E6A014C, 0x4E690140, 0x6060014C, 0x10620144, ++ 0x760E0000, 0x1F30FFFF, 0x2F090000, 0x57610140, ++ 0xB1620148, 0xED208001, 0xCD970D6C, 0xAA970970, ++ 0xC9690148, 0xB968014C, 0xAF6A0140, 0xF66B0154, ++ 0xD7610140, 0x8E0A0000, 0x8E0A0000, 0xD762014C, ++ 0xBC30FFFE, 0xC6600148, 0xDB200000, 0xA7600144, ++ 0xC9630150, 0xBC209000, 0x8E970D6A, 0xF968014C, ++ 0x89690148, 0xEF6A0140, 0xC6600148, 0x8D084000, ++ 0xA4300002, 0xF60E0000, 0xF6620140, 0xA2300001, ++ 0xE060014C, 0xB2200010, 0x94695F52, 0xEC220000, ++ 0xB5190000, 0xCD615F52, 0xD3695F6C, 0xAF238000, ++ 0xDC635F56, 0x91484000, 0x816B5F34, 0xC92D0002, ++ 0xFF424000, 0xBA1F0000, 0xA0C80D47, 0xCB235F7A, ++ 0x9249C000, 0xFE2F0002, 0xCD1D0000, 0xBFCC08D7, ++ 0xD249C000, 0x8E390000, 0x98CC0D47, 0xF2695F56, ++ 0x8E390000, 0xFED408DA, 0xCA625F56, 0x982F0006, ++ 0xAE2E0001, 0xEA8008CC, 0xC2685F52, 0xA36B5F52, ++ 0xDE34000F, 0xBC3700F0, 0xB9CC08E2, 0xCE1C8000, ++ 0x3ACC08E4, 0x628008E6, 0x4E1C8000, 0x1FCC08E6, ++ 0x6E32FFFC, 0x018008E7, 0x0F31FFFC, 0x60198000, ++ 0x6B615F56, 0x236B5F52, 0x31310004, 0x4835000F, ++ 0x3F37000F, 0x4E1F4000, 0x6CC808FC, 0x14004000, ++ 0x63645F52, 0x2931FFF8, 0x19394001, 0x49615F6A, ++ 0x36010000, 0x51310003, 0x6C615F68, 0x1F30FFFF, ++ 0x2A2C0D06, 0x6E2308FB, 0x70884000, 0x1C605F6C, ++ 0x686A0148, 0x2F69014C, 0x18680140, 0x420D8000, ++ 0x2A31FFFE, 0x6B615F60, 0x7E6B0148, 0x0E0A0000, ++ 0x750F8000, 0x0163014C, 0x3C30FFFE, 0x58605F62, ++ 0x4B32FFFE, 0x09625F66, 0x05970C69, 0x5A200051, ++ 0x3160B444, 0x64685F56, 0x456B5F60, 0x1E34000F, ++ 0x47300003, 0x36010000, 0x2434FF00, 0x600CC000, ++ 0x1060B448, 0x6C3500FF, 0x6361B44A, 0x23685F68, ++ 0x206B5F62, 0x506A5F66, 0x76010000, 0x2434FF00, ++ 0x600CC000, 0x3660B44C, 0x2C3500FF, 0x4561B44E, ++ 0xAF62B454, 0xC8200925, 0xD321090A, 0xBF2300A6, ++ 0xEF800C80, 0xAE210001, 0xBA61015E, 0xCE208000, ++ 0xC960015C, 0x89970E08, 0xA36B5F52, 0xC5685F6C, ++ 0xBF37000F, 0xF43B0100, 0xF263B144, 0x9F21085B, ++ 0xDF2C0002, 0xAA410000, 0xA4685F56, 0xC2230D47, ++ 0x9E34000F, 0xE3645F52, 0xC7300003, 0xBA605F68, ++ 0x82800D7E, 0xC3970956, 0xE0970961, 0xB968014C, ++ 0xEF6A0140, 0x89690148, 0xB66B0154, 0xCE0A0000, ++ 0x9762014C, 0xEF6A0140, 0xC9630150, 0x97610140, ++ 0xFC30FFFE, 0x8E0A0000, 0xB1620148, 0xDB200000, ++ 0xE7600144, 0xBC209000, 0x8E970D6A, 0xCE690140, ++ 0x9F680148, 0xE86A0148, 0xD7610140, 0x8D084000, ++ 0xE060014C, 0x9F30FFFF, 0xB60E0000, 0xF1620148, ++ 0x9B200000, 0xC78008BE, 0xDF680148, 0x8E6A014C, ++ 0x8E690140, 0xE060014C, 0xD0620144, 0xAF090000, ++ 0xF60E0000, 0x97610140, 0xB1620148, 0xED208001, ++ 0x0E800D6C, 0x7968014C, 0x49690148, 0x2F6A0140, ++ 0x57610140, 0x360E0000, 0x31620148, 0x57020000, ++ 0x4B32FFFE, 0x0E0A0000, 0x17680154, 0x50620144, ++ 0x010C0000, 0x68600150, 0x40208200, 0x0E800D6C, ++ 0x6F6A0140, 0x09690148, 0x3968014C, 0x71620148, ++ 0x17610140, 0x7C30FFFE, 0x4E0A0000, 0x17680154, ++ 0x10620144, 0x410C0000, 0x68600150, 0x00208200, ++ 0x4E800D6C, 0x32635F4E, 0x0A6B5F42, 0x7A6A5F46, ++ 0x9C200008, 0xCD210000, 0xC5330002, 0xA9D0098A, ++ 0xD4038000, 0x8B32FFFE, 0xBE33FFFF, 0xD70EC000, ++ 0xC6230995, 0x94800327, 0xB19702AF, 0xFA6A5F46, ++ 0x909702A3, 0xFA6A5F46, 0xD09702A3, 0xBA6A5F46, ++ 0xD09702A3, 0xBA6A5F46, 0x909702A3, 0xFA6A5F46, ++ 0x909702A3, 0xDF695F48, 0xFA6A5F46, 0x8C350001, ++ 0xA5C809A8, 0xF6200028, 0xD9970354, 0xAC685F4A, ++ 0xF9695F4C, 0x8B32FFFE, 0x8D048000, 0xE6C409A2, ++ 0x0F2D0001, 0x60615F4C, 0x75605F4A, 0x0520FFFF, ++ 0x4D210000, 0x3A6A5F46, 0x242309A9, 0x54800327, ++ 0x52970644, 0x3A6A5F46, 0x32200010, 0x4D210000, ++ 0x2B6B5F4E, 0x54800327, 0x4320FFFC, 0x39970365, ++ 0x61361F00, 0x32C801F6, 0x31320008, 0x79620138, ++ 0x3F2A0011, 0x53C401F6, 0x7797037A, 0x316B0130, ++ 0x36010000, 0x5235FFFE, 0x57C801F4, 0x1808C000, ++ 0x56C009BE, 0x2FCC01F4, 0x096B5F44, 0x682E0002, ++ 0x23625F46, 0x7E2F0002, 0x50635F44, 0x3E33FFFF, ++ 0x4B32FFFE, 0x170EC000, 0x0B32FFFE, 0x74970385, ++ 0x57680138, 0x3E695F44, 0x01030000, 0x652B0003, ++ 0x26C409CE, 0x5D200003, 0x7C2C0003, 0x2A072000, ++ 0x793B0000, 0x0ECC01F8, 0x1B695F46, 0x642E0010, ++ 0x35034000, 0x6C31FFFD, 0x4E09C000, 0x020E4000, ++ 0x042A0800, 0x57C401F8, 0x5797029D, 0x1B200000, ++ 0x6A210120, 0x0A6B5F42, 0x3A6A5F46, 0x43330001, ++ 0xACD009E3, 0xED2309E4, 0xD4800327, 0xB19702AF, ++ 0xCC970BA4, 0xBA6A5F46, 0xB6200028, 0xCD210000, ++ 0xD7970327, 0x969702A0, 0xBE695F44, 0xCD685F46, ++ 0x8931FFFF, 0xD70D0000, 0xD0610124, 0x9F30FFFF, ++ 0xD70D0000, 0xB6610120, 0xA6970CCB, 0xE0690134, ++ 0x8E6A0120, 0xCC61B010, 0xEB2E0068, 0x8462B000, ++ 0x8362B008, 0xF8208808, 0xFB60B01C, 0xBF2300A6, ++ 0xEF940CD0, 0xB069B024, 0x8E390000, 0xC6D00A0A, ++ 0x09690124, 0x61208400, 0x4A2D0068, 0x0361B004, ++ 0x7B60B01C, 0x3F2300A6, 0x2F940CD0, 0x5669B020, ++ 0x72310002, 0x05D00A0C, 0x09970CD8, 0x558001FC, ++ 0x09970CD8, 0x4D685F46, 0x7E695F44, 0x0E6A0120, ++ 0x46600124, 0x170D0000, 0x31610128, 0x46690130, ++ 0x176B0134, 0x7C30FFFE, 0x760E0000, 0x3662012C, ++ 0x28630130, 0x79610134, 0x6C220000, 0x09625F3C, ++ 0x6920E000, 0x39970210, 0x14680164, 0x67690150, ++ 0x98380000, 0xE0D00E47, 0xF66B0154, 0x896A0144, ++ 0xF968014C, 0x98610154, 0xB82F0001, 0xC9630150, ++ 0xCE690140, 0x9762014C, 0x81600140, 0xD4004000, ++ 0x820D8000, 0xD0610148, 0xE832FFFF, 0xAC088000, ++ 0xE7600144, 0x80208200, 0x8D970D6C, 0xF5680168, ++ 0xB66B0154, 0xD8380000, 0xE0D00E47, 0x8E6A014C, ++ 0x89690148, 0xC9630150, 0xF1620148, 0xBA098000, ++ 0xD7610140, 0x820D8000, 0xA832FFFF, 0xC20D8000, ++ 0xB661014C, 0xDB20F000, 0xCD970D6C, 0x9F680148, ++ 0xEF69014C, 0xAF6A0140, 0xBA230000, 0xC6630144, ++ 0xE060014C, 0x970D0000, 0x90610148, 0xF60E0000, ++ 0xB6620140, 0xED208001, 0xCD970D6C, 0xA86A0148, ++ 0xF968014C, 0x8E690140, 0xB66B0154, 0xF6620140, ++ 0xB60E0000, 0xDF30FFFF, 0xF60E0000, 0xB1620148, ++ 0xAF090000, 0xF1610144, 0xFE33FFFF, 0x89630150, ++ 0xE7208010, 0x8D970D6C, 0x82690164, 0xF968014C, ++ 0x0E390000, 0x60D00E47, 0x4E690140, 0x286A0148, ++ 0x506B0150, 0x10610148, 0x36620140, 0x782F0001, ++ 0x49630150, 0x2F090000, 0x31610144, 0x6D208001, ++ 0x0D970D6C, 0x466A0150, 0x766B0154, 0x3968014C, ++ 0x49690148, 0x170EC000, 0x1F620150, 0x600F0000, ++ 0x1D33FFFE, 0x7E635F5C, 0x5F6B0144, 0x17610140, ++ 0x180B0000, 0x67630148, 0x7C30FFFE, 0x180B0000, ++ 0x46630144, 0x00208200, 0x0D970D6C, 0x41970D7E, ++ 0xA3690168, 0xF16A5F5C, 0xCE390000, 0xA0D00E47, ++ 0xE8970E5E, 0xB5200018, 0xAF800E66, 0xE020FFFD, ++ 0xF9970365, 0xA1361F00, 0xB2C801F6, 0xF1320008, ++ 0xB9620138, 0xFF2A0011, 0xD3C401F6, 0xB797037A, ++ 0xF16B0130, 0xB6010000, 0x9235FFFE, 0xD7C801F4, ++ 0x9808C000, 0xDBC00A97, 0xEFCC01F4, 0x896B5F44, ++ 0xA82E0002, 0xE3625F46, 0xFE2F0002, 0x90635F44, ++ 0xC100C000, 0xBE33FFFF, 0xA00F0000, 0xCB32FFFE, ++ 0x170EC000, 0x4B32FFFE, 0x74970385, 0x17680138, ++ 0x7E695F44, 0x01030000, 0x252B0003, 0x64C40AA9, ++ 0x5D200003, 0x3F2C0005, 0x2A072000, 0x793B0000, ++ 0x0ECC01F8, 0x5B695F46, 0x642E0010, 0x2A31FFFE, ++ 0x420E4000, 0x042A0800, 0x17C401F8, 0x5797029D, ++ 0x1B200000, 0x4D210000, 0x5F6A5F44, 0x17970327, ++ 0x0C970BA4, 0x7A6A5F46, 0x76200028, 0x0D210000, ++ 0x6832FFFF, 0x17970327, 0x169702A0, 0x68685F44, ++ 0x1B695F46, 0x57020000, 0x75034000, 0x1F30FFFF, ++ 0x4931FFFF, 0x140C8000, 0x06600124, 0x750C4000, ++ 0x67600128, 0x200CC000, 0x20600120, 0x66970CCB, ++ 0x20690134, 0x496A0128, 0x5F610130, 0x0C61B010, ++ 0x6B2E0068, 0x0462B000, 0x0362B008, 0x78208808, ++ 0x3B60B01C, 0x7F2300A6, 0x6F940CD0, 0x3069B024, ++ 0x0E390000, 0x73D40ADC, 0x49970CD8, 0x168001FA, ++ 0x49690124, 0x21208400, 0x0A2D0068, 0x4361B004, ++ 0xBB60B01C, 0xFF2300A6, 0xEF940CD0, 0x9669B020, ++ 0xF2310002, 0xB0D40ADA, 0x8E6A0120, 0xF8208808, ++ 0xEB2E0068, 0x8462B000, 0x8362B008, 0xFB60B01C, ++ 0xBF2300A6, 0xEF940CD0, 0xF069B024, 0x8E390000, ++ 0xC8D00ADA, 0xA1208400, 0xBB60B01C, 0xFF2300A6, ++ 0xAF940CD0, 0xD669B020, 0xF2310002, 0xB0D40ADA, ++ 0x89970CD8, 0xCD685F46, 0xEF690120, 0xA7600128, ++ 0xD70D0000, 0x9761012C, 0xAC220000, 0xC9625F3C, ++ 0x9B20F000, 0xF9970210, 0xDF680148, 0x8E6A014C, ++ 0xCE690140, 0xA060014C, 0x90620144, 0xEF090000, ++ 0xD7610140, 0xB60E0000, 0xB1620148, 0xED208001, ++ 0x8D970D6C, 0xF968014C, 0xC9690148, 0xAF6A0140, ++ 0xD7610140, 0xA3018000, 0x970D0000, 0xD0610148, ++ 0x9F30FFFF, 0xCE0A0000, 0xD7680154, 0x90620144, ++ 0x810C0000, 0xE8600150, 0xC0208200, 0x8D970D6C, ++ 0xE06A0154, 0xB968014C, 0xB96B0140, 0xDF620150, ++ 0x09690148, 0x67630148, 0x580B0000, 0x06630144, ++ 0x5F30FFFF, 0x2F090000, 0x17610140, 0x6D208001, ++ 0x4D970D6C, 0x3968014C, 0x2F6A0140, 0x49690148, ++ 0x31620148, 0x4E0A0000, 0x57680154, 0x10620144, ++ 0x57610140, 0x010C0000, 0x28600150, 0x40208200, ++ 0x0D970D6C, 0x7968014C, 0x766B0154, 0x09690148, ++ 0x2F6A0140, 0x49630150, 0x57610140, 0x36695F58, ++ 0x4E0A0000, 0x1762014C, 0x2F2D0030, 0x664A4000, ++ 0x2F2D0006, 0x47494000, 0x673607FC, 0x13320002, ++ 0x79620154, 0x14038000, 0x03330001, 0x7ED40B49, ++ 0x6E2E0001, 0x282E0002, 0x10620144, 0x6832FFFF, ++ 0x31620148, 0x40351F00, 0x50310008, 0x39610158, ++ 0x6920E000, 0x0D970D6C, 0x3E680144, 0x4E6A014C, ++ 0x0E690140, 0x506B0150, 0x760E0000, 0x1762014C, ++ 0x0100C000, 0x43330001, 0x52D40B5C, 0x192C0001, ++ 0x5F2C0002, 0x1F30FFFF, 0x170D0000, 0x57610140, ++ 0x8D210000, 0xD0610148, 0xE920E000, 0x8D970D6C, ++ 0xD06B0150, 0x97680154, 0x8E6A014C, 0xC163014C, ++ 0xE8600150, 0x8E600154, 0x81030000, 0xC3330001, ++ 0xB4D40B6E, 0xD92C0001, 0xDF2C0002, 0x90620144, ++ 0xCE0A0000, 0xB6620140, 0x9F30FFFF, 0xF60E0000, ++ 0xB1620148, 0xED208001, 0xCD970D6C, 0x89690148, ++ 0x896A0144, 0xD06B0150, 0xD7610140, 0xB1620148, ++ 0xC100C000, 0xBE33FFFF, 0x89630150, 0xCE600154, ++ 0x01030000, 0x43330001, 0x5BD40B84, 0x192C0001, ++ 0x5F2C0002, 0x27600144, 0x00208200, 0x4D970D6C, ++ 0x68690144, 0x286A0148, 0x3968014C, 0x766B0154, ++ 0x36620140, 0x49630150, 0x4E600154, 0x01030000, ++ 0x43330001, 0x12D40B93, 0x192C0001, 0x5F2C0002, ++ 0x2060014C, 0x7A0A4000, 0x71620148, 0x3C30FFFE, ++ 0x0E0A0000, 0x50620144, 0x40208200, 0x0D970D6C, ++ 0x49690148, 0x206A0154, 0x186B014C, 0x57610140, ++ 0x9F620150, 0xFE33FFFF, 0xCE09C000, 0xA3800878, ++ 0xF2635F4E, 0x8A6B5F42, 0x9C200008, 0xCD210000, ++ 0xDF6A5F44, 0x85330002, 0x86D00BB0, 0xEC6B5F46, ++ 0xA832FFFF, 0xD70EC000, 0xEF230BC0, 0x94800327, ++ 0xF19702AF, 0x9F6A5F44, 0x909702A3, 0xDF6A5F44, ++ 0xAC685F4A, 0xF9695F4C, 0xCB32FFFE, 0x8D048000, ++ 0xA5C40BBB, 0xCF2D0001, 0xE0615F4C, 0xB5605F4A, ++ 0xFA6A5F46, 0x8520FFFF, 0x8D210000, 0xF19702AF, ++ 0xBA6A5F46, 0xF2200010, 0xCD210000, 0xAB6B5F4E, ++ 0xD4800327, 0x93800200, 0x81030000, 0xC637FFFF, ++ 0xEECC0200, 0xAE2C0BCB, 0xB0884000, 0xE9800BCC, ++ 0x9A970364, 0xDF20000E, 0xFE97036D, 0xA43C000E, ++ 0xEFCC01F4, 0x952001FF, 0xBE97036D, 0xFE605F3C, ++ 0xBF340003, 0xEFCC01F4, 0xC92E000E, 0x8B32FFFE, ++ 0xB4970385, 0xD797029D, 0xE822000E, 0x9B200000, ++ 0xCD210000, 0x97970327, 0xA0685F34, 0xC92101D8, ++ 0x1F610106, 0x7D2C0008, 0x73490000, 0x1F2C0002, ++ 0x65480000, 0x23615F4A, 0x36605F4C, 0x67685F3C, ++ 0x58695F40, 0x3C30FFFE, 0x1B605F3E, 0x6F090000, ++ 0x02C40BEE, 0x57605F40, 0x502001A0, 0x2A230BF3, ++ 0x6C600104, 0x3D635F36, 0x3D8002D7, 0x72200010, ++ 0x2C600104, 0x58800420, 0x529700EB, 0x2A220003, ++ 0x2F62B438, 0x56695FCA, 0x42685EDE, 0x2C220000, ++ 0x4A61B400, 0x2862B406, 0x18380000, 0x7CC8009C, ++ 0x15340080, 0x43C80C05, 0x6F200C16, 0x27230C06, ++ 0x5A8000AB, 0x1B605EDE, 0x24685EEC, 0x5E23009C, ++ 0x6C220000, 0x0A625EEC, 0x14695EDE, 0x5B6A5EF0, ++ 0x18380000, 0x7AC800F3, 0x60198000, 0x176A5F02, ++ 0x60198000, 0x396A5EA0, 0x1CD000AB, 0x5E36FDFF, ++ 0x20625EA0, 0x5A8000AB, 0x51215EDE, 0x2F220006, ++ 0x04970F9D, 0x77215EEC, 0x70510000, 0x30510000, ++ 0x70884000, 0x2F220030, 0x2F62B438, 0x70695FCE, ++ 0xAC685EF0, 0xEC220000, 0xE061B420, 0x8262B426, ++ 0xD8380000, 0x9FC8009D, 0x95340080, 0xEDC80C2B, ++ 0xE5200C31, 0xAF230C2C, 0x9A8000AB, 0xF5605EF0, ++ 0xA8685EFE, 0xFD23009D, 0xEC220000, 0x86625EFE, ++ 0xE1800C0A, 0xBF215EF0, 0xAF220006, 0xC4970F9D, ++ 0xBB215EFE, 0xF0510000, 0xF0510000, 0xB0884000, ++ 0xAF220300, 0xEF62B438, 0xF0695FCE, 0xA0685F02, ++ 0xEC220000, 0x8161B440, 0xA362B446, 0xD8380000, ++ 0x99C8009E, 0xD5340080, 0xCEC80C46, 0xAF200C4C, ++ 0xCF230C47, 0x9A8000AB, 0xB9605F02, 0xEC685F10, ++ 0xFB23009E, 0xAC220000, 0x82625F10, 0xE1800C0A, ++ 0xB3215F02, 0xEF220006, 0xC4970F9D, 0xBF215F10, ++ 0xF0510000, 0xB0510000, 0xB0884000, 0xC2685EDE, ++ 0x91215EDE, 0xD8380000, 0xC0D00C5F, 0xA1205EEC, ++ 0xA5518000, 0xE6500000, 0xD8695EA0, 0xA6500000, ++ 0xC0390200, 0x81615EA0, 0x918B4000, 0xC100C000, ++ 0x2F220006, 0x7F2300A6, 0x67800FC0, 0x2C685EF0, ++ 0x7F215EF0, 0x18380000, 0x00D00C5F, 0x6D205EFE, ++ 0x66800C58, 0x20685F02, 0x33215F02, 0x58380000, ++ 0x00D00C5F, 0x69205F10, 0x66800C58, 0x02685EDE, ++ 0x51215EDE, 0x18380000, 0x3FD40C57, 0x588000A6, ++ 0x2C685EF0, 0x7F215EF0, 0x58380000, 0x1ED000A6, ++ 0x2D205EFE, 0x66800C58, 0x7D605EEC, 0x0E615EEE, ++ 0x518B4000, 0x31605EFE, 0x0A615F00, 0x518B4000, ++ 0xB5605F10, 0xC6615F12, 0xD18B4000, 0xAC685EF0, ++ 0xCD210000, 0x98380000, 0xA5C80C94, 0xEF61B434, ++ 0xD16A5FCE, 0xA361B426, 0x8162B420, 0xD5340080, ++ 0x85C80C93, 0xD4635E9C, 0xFF215EF0, 0xAF220006, ++ 0xC4970F9D, 0x8D6B5E9C, 0x9A8000AB, 0xE3615EF0, ++ 0x918B4000, 0xD7620116, 0xC7200C98, 0x9A8000AB, ++ 0x86970C6F, 0xCE6A0116, 0xE620B404, 0xAC500011, ++ 0xE0500003, 0xA850C400, 0x85500001, 0xC7500180, ++ 0x26500000, 0x6462B414, 0x5E2000A6, 0x082100A6, ++ 0x7F2300A6, 0x29800C7A, 0x20690102, 0x5B200000, ++ 0x45350020, 0x14C801F2, 0x18218000, 0x6F615ED4, ++ 0x3D605EDA, 0x7E605EDC, 0x518B4000, 0x36695ED4, ++ 0x58380000, 0x3AC800F3, 0x0E390000, 0x49D400EF, ++ 0x3D605EDA, 0x518B4000, 0x76695ED4, 0x18380000, ++ 0x3AC800F3, 0x4E390000, 0x49D400EF, 0x3E605EDC, ++ 0x518B4000, 0x20685ED4, 0x33215ED4, 0x58380000, ++ 0x24D400F1, 0x70510000, 0x518B4000, 0x18695ECC, ++ 0x63685ED2, 0x0E390000, 0x27D4009B, 0x58380000, ++ 0x5CC8009B, 0x3E23009B, 0x1A8000AB, 0x5D215ECC, ++ 0x25518000, 0x5B200000, 0x7A605ED2, 0x118B4000, ++ 0x58695ECC, 0x3A605ED2, 0x0E390000, 0x58695EA0, ++ 0x09D400EF, 0x49390008, 0x41615EA0, 0x118B4000, ++ 0x396A5EA0, 0x4E685ECC, 0x5D215ECC, 0x1736FFF7, ++ 0x60625EA0, 0x18380000, 0x24D400F1, 0x70510000, ++ 0x918B4000, 0xC2685F52, 0xD8218000, 0xB6144000, ++ 0xE6CC00A0, 0x8D615F52, 0xBC2300A0, 0xEC200CE9, ++ 0xDA8000AB, 0xB4200400, 0x9360B144, 0xC3210200, ++ 0x8A68B144, 0xDE34000F, 0xF5190000, 0x8561B144, ++ 0xE3645F52, 0xB6010000, 0x90310008, 0xE839A0C8, ++ 0xB04B4000, 0xE72D002C, 0xC7494000, 0x97020000, ++ 0x83330001, 0xD0377F00, 0xC963010A, 0xB0320003, ++ 0xCD625F68, 0x97020000, 0x8832FFF8, 0xF83A4001, ++ 0xA8625F6A, 0xD7020000, 0xE832FFFF, 0x9D2E0D06, ++ 0xE2230D1A, 0x878A4000, 0xAA205F7A, 0xD18B4000, ++ 0xC9205F82, 0x918B4000, 0x8E205F8A, 0xD18B4000, ++ 0xA0205F92, 0xD18B4000, 0xE7205F9A, 0x918B4000, ++ 0xE3205FA2, 0x918B4000, 0xA4205FAA, 0xD18B4000, ++ 0x8A205FB2, 0xD18B4000, 0xCD205FBA, 0x918B4000, ++ 0x82205FC2, 0xD18B4000, 0xDC605F6C, 0xB3490000, ++ 0xDF2C0002, 0x844B0000, 0x9F2C0002, 0xD24A0000, ++ 0x1F2C0002, 0x65480000, 0x6F615F58, 0x1C635F56, ++ 0x6B625F5A, 0x1F605F5C, 0x27970E26, 0x716A5F5C, ++ 0x536B010C, 0x2F3A0000, 0x0BC80D36, 0x6C213000, ++ 0x3A098000, 0x6C0B4000, 0x5861010E, 0x32C00D31, ++ 0x7ECC0E45, 0x05685F5A, 0x29230D36, 0x79635F54, ++ 0x026B5F68, 0x66800E2B, 0x6769010A, 0x056B5F56, ++ 0x10310008, 0x4AC80D67, 0x576A5F58, 0x22390080, ++ 0x4B2E0035, 0x07458000, 0x01970D7E, 0x42685F52, ++ 0x24230D43, 0x4B341000, 0x59CC102C, 0x1D2000A0, ++ 0x40645F53, 0x36695F58, 0x1E970273, 0x4169010E, ++ 0x4D223000, 0x3A0A4000, 0x2CC80D63, 0x54680108, ++ 0x32620114, 0x58380000, 0x69C80D50, 0x00970C95, ++ 0x45970C69, 0x0169010E, 0x2D20B444, 0x6C500011, ++ 0x05500001, 0x6850C400, 0x45500001, 0x3135FFFF, ++ 0x2A410000, 0x6B6A0114, 0x5F2C0002, 0x26500000, ++ 0x6F62B454, 0x0A200D61, 0x1C210D61, 0x7F2300A6, ++ 0xAF800C80, 0xFA203000, 0xCE60010E, 0x8D210000, ++ 0xDB610108, 0x8D615F52, 0x988000A6, 0xEC220000, ++ 0xDB62015E, 0x918B4000, 0xAE210001, 0xFA61015E, ++ 0x8960015C, 0xDC635F56, 0xC9970E08, 0xA36B5F52, ++ 0xC5685F6C, 0xBF37000F, 0xB43B0100, 0xF263B144, ++ 0xB2695F56, 0xDF2C0002, 0xEA410000, 0x93695F5A, ++ 0x9F2C0002, 0xEA410000, 0xD0695F5C, 0x9F2C0002, ++ 0xEA410000, 0xA5800D47, 0x82685F52, 0xFA69B140, ++ 0x3C30FFFE, 0x53D0038F, 0x79635F54, 0x24300002, ++ 0x41030000, 0x1E34000F, 0x3E3CFFFF, 0x79228000, ++ 0x4D120000, 0x181D8000, 0x2361B140, 0x796A5EA0, ++ 0x38CC0D8F, 0x7636FFFB, 0x60625EA0, 0x2A3B2000, ++ 0x63685F32, 0x3A635F52, 0x0D344000, 0x6AC80D99, ++ 0x05685F36, 0x599700AB, 0x41685F54, 0x3F2300A6, ++ 0x1A8000AB, 0x42685F52, 0x7A69B140, 0x2F238000, ++ 0x5E34000F, 0x17020000, 0x093EFFFF, 0x4E138000, ++ 0x9419C000, 0xE361B140, 0xFF30FFF8, 0x9438A084, ++ 0xCC500020, 0xBD680118, 0x97695F54, 0xC218C000, ++ 0xE4600118, 0xBA1CC000, 0xB8CC0DE3, 0xF161011E, ++ 0xA3685F68, 0xE363011C, 0xC160011A, 0x85970C69, ++ 0xF96B011A, 0xAD20B444, 0x8E500041, 0xC5500001, ++ 0x87500180, 0xE6500000, 0xF602C000, 0x9336FF00, ++ 0x8162B44C, 0xDB3700FF, 0xF263B44E, 0xBF222000, ++ 0xEF62B454, 0x9F6B011E, 0x9B200000, 0xE760011E, ++ 0xB93B0000, 0xD2CC0DC3, 0xFF2300A6, 0xAC200DC6, ++ 0xFA210DC6, 0xAF800C80, 0x9B68011C, 0xFA69B140, ++ 0xCA6A0118, 0x8D1D0000, 0xA361B140, 0xEC1E0000, ++ 0x93620118, 0xE2C80DDF, 0xDB200000, 0xAE210001, ++ 0xD4038000, 0x97174000, 0xBECC0DD6, 0xD92C0001, ++ 0x8931FFFF, 0xC0800DD0, 0xD461011C, 0x87300003, ++ 0xB5695F32, 0xC160011A, 0xDB354000, 0xAAC80DAF, ++ 0xE9200DAF, 0xA46B5F36, 0x9A8000AB, 0xE3685F32, ++ 0x13695F36, 0x4D344000, 0x5DC800A6, 0x26894000, ++ 0x6F3A0000, 0x10C8038F, 0x3D635F36, 0x4D6B5F4A, ++ 0x6C600104, 0x1F610106, 0x2C625F3E, 0x71635F48, ++ 0x27970C63, 0x75680104, 0x676A0106, 0x286B5F48, ++ 0x7160B428, 0x1E21B42A, 0x30510000, 0x4100C000, ++ 0x2434FF00, 0x541A0000, 0x6062B42C, 0x1B3700FF, ++ 0x1363B42E, 0x756A5F3E, 0x73200041, 0x1060B424, ++ 0x4E62B434, 0x32210DEC, 0x3F2300A6, 0x6B940C7D, ++ 0xA46B5F36, 0xD18B4000, 0xFD635F36, 0xBC200120, ++ 0xCD210000, 0x86220020, 0x8E6B5F4C, 0xC4800DE8, ++ 0xF9635F54, 0xA76B5F6A, 0x9D200140, 0xCD210000, ++ 0x86220020, 0xFD605F60, 0xCE615F62, 0x89625F66, ++ 0xDB635F5E, 0x85970C69, 0xA4685F60, 0xF66A5F62, ++ 0x826B5F5E, 0xD060B448, 0xFF21B44A, 0xB0510000, ++ 0x8100C000, 0xE434FF00, 0xD41A0000, 0x8162B44C, ++ 0xDB3700FF, 0xB263B44E, 0x906A5F66, 0xF3200041, ++ 0x3160B444, 0x6F62B454, 0x46200E43, 0x17210E11, ++ 0x7F2300A6, 0x2F800C80, 0x39635F54, 0x5B200000, ++ 0x4B210140, 0x2722002C, 0x276B5F6A, 0x7D605F60, ++ 0x0E615F62, 0x49625F66, 0x5B635F5E, 0x05970C69, ++ 0x546A5F5E, 0x24685F60, 0x17695F62, 0x54038000, ++ 0x0537FF00, 0x4218C000, 0x5060B448, 0x0D3600FF, ++ 0x0262B44A, 0x6061B44C, 0x5B200000, 0x1360B44E, ++ 0x506A5F66, 0x11200011, 0x3160B444, 0x6F62B454, ++ 0x10210E2F, 0x7F2300A6, 0x4D940C80, 0x206B5F54, ++ 0x518B4000, 0x25210041, 0x2F800D3A, 0x44210021, ++ 0x6F800D3A, 0x176A5F58, 0x02690164, 0x602E0028, ++ 0x0E390000, 0x4BD00E5A, 0x6F090000, 0x2A31FFFE, ++ 0x75680168, 0x3F418000, 0x3734001F, 0x682E0002, ++ 0x29408000, 0x75008000, 0x5F2C0002, 0x26500000, ++ 0x26500000, 0x518B4000, 0x4E208000, 0x29408000, ++ 0x5B200000, 0x29800E53, 0x20685F58, 0x4D210000, ++ 0x972C0028, 0xE6500000, 0xE6500000, 0xA6500000, ++ 0xEA410000, 0x918B4000, 0xAE230D3E, 0xE73607FC, ++ 0xD0C8038F, 0xB9635F54, 0x816B5F58, 0xC9625F66, ++ 0xA00CC000, 0xC44B0000, 0xDF2C0002, 0xA5480000, ++ 0xF9635F62, 0xB66B010E, 0x9B605F64, 0xF60DC000, ++ 0x9B610108, 0xE4970C53, 0xC1685F62, 0x94695F64, ++ 0xBD60B40C, 0xCE61B40E, 0xD4680108, 0x906A5F66, ++ 0xF421B40A, 0x9B60B408, 0xB0510000, 0xD4200081, ++ 0x3A60B404, 0x6462B414, 0x41685F54, 0x10210E75, ++ 0x7F2300A6, 0x29800C7A, 0x36695F6E, 0x4E208000, ++ 0x54150000, 0x25C80E8B, 0x118B4000, 0x796A5EA0, ++ 0x39605F6E, 0x6D200E91, 0x7536FFFD, 0x20625EA0, ++ 0x5A8000AB, 0x2A685FDC, 0x36695F6E, 0x58380000, ++ 0x0AC80EF4, 0x54605F70, 0x712C0040, 0x33490000, ++ 0x17655F6E, 0x5C65B112, 0x6F31FFFB, 0x312D4010, ++ 0x664A4000, 0x2F6BB110, 0x092D0002, 0x6F0AC000, ++ 0x9BC00EE8, 0xF04B4000, 0xD62DFFF6, 0xB93B0000, ++ 0xF7D40EAD, 0x8D685F70, 0xA02D0012, 0xE64A4000, ++ 0xD42C0042, 0x844B0000, 0xB82DFFEE, 0xEF1F8000, ++ 0x9FCC0EEA, 0xD4004000, 0xFB215F72, 0x8F970FDD, ++ 0xFE695F72, 0xB92C0006, 0xA9350003, 0xDACC0EEF, ++ 0xBB215F72, 0xF422FFFC, 0xE1970FF3, 0x8D685F70, ++ 0xB9215FDC, 0xE0970F5B, 0xE6971027, 0xA4970C53, ++ 0xEC6B5F70, 0xA8685F72, 0xBD695F74, 0xD522B40A, ++ 0xBA63B408, 0xD1520000, 0xFD60B40C, 0x8E61B40E, ++ 0xD4200081, 0xBA60B404, 0x90200040, 0xD360B414, ++ 0xD0210EBA, 0xBF2300A6, 0x8B940C7A, 0xE0685F6E, ++ 0xBC695FEA, 0xFA3400FF, 0xF930FFFB, 0x852C401A, ++ 0xC44B0000, 0x8F2D0001, 0xB82F0001, 0xDD430000, ++ 0x802CFFF6, 0xD24A0000, 0xF92C0006, 0x844B0000, ++ 0xA5615FEA, 0xF82F0001, 0xEF0AC000, 0xA5C40EDD, ++ 0xFA230000, 0x9D430000, 0x976A5F6E, 0xCD685F70, ++ 0x0D3600FF, 0x5D3A1000, 0x4A62B130, 0x06970F33, ++ 0x4E208000, 0x39605F6E, 0x0C230E91, 0x7C800115, ++ 0x66210088, 0x34655F6F, 0x0D685F70, 0x76695F6E, ++ 0x3E2C0038, 0x65480000, 0x4E800E93, 0x3F9700F5, ++ 0x4D685F70, 0x39215FDC, 0x21230EE3, 0x63800F5B, ++ 0x396A5EA0, 0x5E350800, 0x6F615F6E, 0x1DC800A6, ++ 0x0A3A0002, 0x60625EA0, 0x588000A6, 0x2B68B148, ++ 0x62300001, 0x20D00F04, 0x21300007, 0x62D00F09, ++ 0x06300008, 0x7E3CFFFF, 0x4A64B148, 0x3F80009F, ++ 0x7A230000, 0x1363B148, 0x3C635FF2, 0x59635FF0, ++ 0x6D800EFE, 0x07710048, 0x29710149, 0x5471804B, ++ 0x01800F0B, 0x40685FFC, 0x736AB1F8, 0x2434FF00, ++ 0x46300008, 0x192C0001, 0x21361F00, 0x71320008, ++ 0x0E0A0000, 0x41C000F9, 0x7F225E90, 0x3930FFFB, ++ 0x0E2C4000, 0x4E0A0000, 0x63C000F3, 0x37605FD2, ++ 0x43625FD4, 0x122A000F, 0x0EC000ED, 0x518B4000, ++ 0x88685FD6, 0xFB695FD4, 0xD8380000, 0x8FC80F27, ++ 0xF3490000, 0x87615FD6, 0x918B4000, 0xF9290044, ++ 0xD1C00F2F, 0xAE685FD2, 0xA2615FD4, 0xF6010000, ++ 0x812D0044, 0xE1615FD2, 0xD18B4000, 0x9B1C0000, ++ 0xF7605FD2, 0xB4605FD4, 0x918B4000, 0xDE695FD6, ++ 0x98380000, 0xFAC800F3, 0xEA410000, 0x91605FD6, ++ 0x918B4000, 0xCE390000, 0xD7C800ED, 0xA64A4000, ++ 0xD8380000, 0xBAC800F3, 0x88404000, 0xEF3A0000, ++ 0xAEC80F47, 0xDB2C003A, 0xCB420000, 0x892E0038, ++ 0xC32CFFC6, 0xA9408000, 0x918B4000, 0xD12DFFFE, ++ 0xC8404000, 0x918B4000, 0x8E390000, 0xD7C800ED, ++ 0xA64A4000, 0xD8380000, 0xFAC800F3, 0x88404000, ++ 0xEF3A0000, 0xA0C80F58, 0xBE2C0038, 0xCB420000, ++ 0xAC2E003A, 0xC72CFFC8, 0xE9408000, 0x918B4000, ++ 0x892D0002, 0xC8404000, 0xD18B4000, 0x8E390000, ++ 0xD7C800ED, 0x98380000, 0xBAC800F3, 0xF6635E96, ++ 0x1B2C003A, 0x444B0000, 0x472CFFFE, 0x124A0000, ++ 0x793B0000, 0x20C80F6E, 0x2F3A0000, 0x4CC80F7B, ++ 0x5F2F0038, 0x2A42C000, 0x2C2E003A, 0x662FFFC8, ++ 0x08438000, 0x4B800F76, 0x7F424000, 0x2F3A0000, ++ 0x6BC80F74, 0x2C2E003A, 0x08438000, 0x4B800F76, ++ 0x092D0002, 0x7F424000, 0x66500000, 0x26500000, ++ 0x2F6B5E96, 0x662CFFC4, 0x518B4000, 0x092D0002, ++ 0x7F424000, 0x1F2F0038, 0x2A42C000, 0x4B800F76, ++ 0x95320001, 0xC5367FFF, 0xC6C80F93, 0xB22A0008, ++ 0xD7C00F8F, 0xA6500000, 0xA6500000, 0xE6500000, ++ 0xE6500000, 0xA6500000, 0xA6500000, 0xE6500000, ++ 0xA6500000, 0xC6C80F93, 0xEA800F83, 0x93260008, ++ 0xE6500000, 0x932EFFFF, 0xB8CC0F90, 0xD18B4000, ++ 0x93635E94, 0xC4970F9D, 0xCA6B5E94, 0x9A8000AB, ++ 0x93635E94, 0xC4970F9D, 0xC1030000, 0xAB685E94, ++ 0xDA8000AB, 0x91484000, 0xA7615E92, 0xD4605E90, ++ 0x06300008, 0x55D40FBE, 0x76635E96, 0x1634007F, ++ 0x5F30FFFF, 0x092D0002, 0x170D0000, 0x704B4000, ++ 0x62300001, 0x192C0001, 0x1B695E90, 0x6C1E0000, ++ 0x3FCC0FAE, 0x5B200000, 0x63024000, 0x1B368000, ++ 0x4035007F, 0x0D1D0000, 0x3E695E92, 0x4BC80FBC, ++ 0x31320008, 0x541A0000, 0x4F2D0001, 0x07464000, ++ 0x0100C000, 0x6F6B5E96, 0x58380000, 0x118B4000, ++ 0x7F424000, 0x28800FB8, 0x1B1C0000, 0x518B4000, ++ 0x14605E90, 0x51484000, 0x45625E94, 0x06300008, ++ 0x71D40FDB, 0x17020000, 0x06300008, 0x5634007F, ++ 0x6136007F, 0x2C1E0000, 0x17C800ED, 0x5F30FFFF, ++ 0x3A6A5E90, 0x67615E92, 0x492D0002, 0x170D0000, ++ 0x7F424000, 0x1C6A5E94, 0x3E695E92, 0x62300001, ++ 0x192C0001, 0x6C1E0000, 0x74CC0FD8, 0x1B200000, ++ 0x34380080, 0x70444000, 0x518B4000, 0x1B200000, ++ 0x46800FCC, 0x36635E96, 0x044B0000, 0x5F2C0002, ++ 0xA9434000, 0xD24A0000, 0xC92D0002, 0xBF424000, ++ 0xD71B8000, 0x9F2C0002, 0x924A0000, 0xC92D0002, ++ 0xFF424000, 0x971B8000, 0x9F2C0002, 0xD24A0000, ++ 0x892D0002, 0xFF424000, 0xF51AC000, 0xAF6B5E96, ++ 0xDF2C0002, 0x892D0002, 0x918B4000, 0xD4605E90, ++ 0xA7615E92, 0xF6635E96, 0xF3490000, 0x940C8000, ++ 0xA5480000, 0xCE390000, 0xE1C8101A, 0xA1340FFC, ++ 0xCFC81002, 0xAA280041, 0x96C01002, 0xCB240041, ++ 0xAA072000, 0xCF801007, 0xCC31FFFA, 0xA3024000, ++ 0xF436FFC0, 0xB5034000, 0xBC37003F, 0xFE695E92, ++ 0xD1484000, 0x8D048000, 0x88404000, 0xC92D0002, ++ 0x91484000, 0xD604C400, 0xC8404000, 0x80C4101A, ++ 0xC92D0002, 0x91484000, 0xAC220000, 0xE2048400, ++ 0x88404000, 0xC0C4101A, 0xC92D0002, 0x91484000, ++ 0xA2048400, 0xC8404000, 0xEF6B5E96, 0x8D685E90, ++ 0xD18B4000, 0x8A685F14, 0x99215F14, 0xD8380000, ++ 0x05D01023, 0x65518000, 0x518B4000, 0x0100C000, ++ 0x49220002, 0x3F2300A6, 0x27800FC0, 0x4A685F14, ++ 0x5D215F1A, 0x18380000, 0x05D01023, 0x518B4000, ++ 0x0A685F14, 0x59215F14, 0x58380000, 0x24D400F1, ++ 0x55340080, 0x0FC81034, 0x09220002, 0x42800F98, ++ 0x30510000, 0x4E685F1A, 0x54635E9C, 0x18380000, ++ 0x33CC103A, 0x518B4000, 0x5D215F1A, 0x09220002, ++ 0x60970F94, 0x0D6B5E9C, 0x29801035, 0x60000000, ++ 0x20000000 ++}; ++ ++// Align to PKA_BUFFER_RAM_SIZE. This is greater than the actual buffer ++// length so that the image is zero padded. ++static const uint32_t fw1_farm_img_data_buf[2048] = ++{ ++ 0x267001C9, 0x132040FA, 0x26502421, 0x032040D0, ++ 0x295046C7, 0x0D500000, 0x258C0200, 0x0F70AAC9, ++ 0x3B7000C8, 0x2D70001D, 0x2670001F, 0x296A4010, ++ 0x086B4014, 0x39621FF8, 0x16631FF4, 0x15684000, ++ 0x34694004, 0x1E601FF6, 0x3F611FF2, 0x346A4008, ++ 0x156B400C, 0x32621FFA, 0x1B631FF0, 0x219700BB, ++ 0x1E684034, 0x2170001E, 0x3A34003F, 0x281A0000, ++ 0x3F621FFE, 0x0628000B, 0x20C4004A, 0x1124002C, ++ 0x21884000, 0x2980004A, 0x30800033, 0x22800048, ++ 0x3480003E, 0x2980004A, 0x2C800040, 0x2C80002C, ++ 0x3980003A, 0x27800042, 0x21800044, 0x2A800046, ++ 0x276A4018, 0x34621FFC, 0x339701D9, 0x09300002, ++ 0x39D00063, 0x3930FFFE, 0x36800059, 0x276A4018, ++ 0x34621FFC, 0x2A97025F, 0x09300002, 0x39D00063, ++ 0x3930FFFE, 0x34800064, 0x2E970327, 0x268C0400, ++ 0x16614018, 0x36800059, 0x2F970733, 0x36800059, ++ 0x2A9706EF, 0x36800059, 0x29970735, 0x36800059, ++ 0x319706F1, 0x36800059, 0x3D970422, 0x36800059, ++ 0x27970767, 0x36800059, 0x3B7000C8, 0x24200021, ++ 0x358C5000, 0x26800073, 0x2B707FC8, 0x08702084, ++ 0x2D70001D, 0x36200000, 0x2D010000, 0x1E220001, ++ 0x2F970085, 0x01684084, 0x26340020, 0x0ECC0055, ++ 0x3920000F, 0x238C0100, 0x09300002, 0x39D00063, ++ 0x1B601FFC, 0x2A681FF0, 0x246A4014, 0x2D010000, ++ 0x2460400C, 0x2F970085, 0x29681FFC, 0x3930FFFE, ++ 0x036A1FF6, 0x276B1FF8, 0x08624000, 0x37634010, ++ 0x0D6A1FFE, 0x3F9700C3, 0x0E6A1FF2, 0x246B1FF4, ++ 0x05624004, 0x3A634014, 0x006A1FFA, 0x35230000, ++ 0x06624008, 0x358C5000, 0x3463401C, 0x106440C9, ++ 0x3C800006, 0x376B1FE4, 0x228B4000, 0x3C6B1FE6, ++ 0x228B4000, 0x3F8C0480, 0x24BC004E, 0x1B61401C, ++ 0x228B4000, 0x2D010000, 0x3930FFFE, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x09300002, ++ 0x202A0002, 0x0B614000, 0x1B624010, 0x29604008, ++ 0x1D218808, 0x23800079, 0x0B631FEC, 0x166B4000, ++ 0x086A1FF4, 0x27604000, 0x06614004, 0x2A634008, ++ 0x1B624010, 0x16624014, 0x37218001, 0x25970079, ++ 0x35068000, 0x186B4008, 0x0D691FF2, 0x24634000, ++ 0x06614004, 0x29604008, 0x1B624010, 0x2A320001, ++ 0x262EFFFF, 0x36058000, 0x1531FFFE, 0x214B4000, ++ 0x20250002, 0x0E494000, 0x2819C000, 0x07CC00A5, ++ 0x16624014, 0x2C218200, 0x25970079, 0x396B1FEC, ++ 0x228B4000, 0x37694008, 0x268C0400, 0x0D684024, ++ 0x04140000, 0x18D400B0, 0x36200000, 0x228B4000, ++ 0x00240001, 0x1A084000, 0x228B4000, 0x13684030, ++ 0x37380001, 0x21604030, 0x228B4000, 0x13684030, ++ 0x0834FFFE, 0x21604030, 0x228B4000, 0x386A40C4, ++ 0x3F694030, 0x1B360001, 0x1732FFF9, 0x18350001, ++ 0x1831FFFA, 0x011A4000, 0x228B4000, 0x07018000, ++ 0x28310006, 0x18350001, 0x0D614030, 0x2C320007, ++ 0x1B360001, 0x0A6240C4, 0x228B4000, 0x29604008, ++ 0x06614004, 0x16624014, 0x37218001, 0x268C0400, ++ 0x1B61401C, 0x2A694010, 0x27604000, 0x36064000, ++ 0x1B624010, 0x228B4000, 0x29604008, 0x06614004, ++ 0x16624014, 0x2D218018, 0x268C0400, 0x1B61401C, ++ 0x296A4010, 0x27604000, 0x2F260001, 0x1B624010, ++ 0x228B4000, 0x29604008, 0x06614004, 0x16624014, ++ 0x2C218200, 0x268C0400, 0x1B61401C, 0x246A4014, ++ 0x27604000, 0x1B624010, 0x228B4000, 0x1C2100FF, ++ 0x288000EE, 0x1A210000, 0x05631FE4, 0x24611FEC, ++ 0x21681FF2, 0x2B6040A0, 0x0B691FF4, 0x27604000, ++ 0x29604008, 0x18614010, 0x268C0400, 0x0970081C, ++ 0x2470881D, 0x01F000F9, 0x3930FFFE, 0x27490000, ++ 0x29310001, 0x3A200003, 0x1DD40075, 0x1231FFFF, ++ 0x286540B4, 0x216B1FFE, 0x036A1FF6, 0x3D33FFFF, ++ 0x3FD00110, 0x276B1FF8, 0x08624000, 0x06624008, ++ 0x37634010, 0x3F8C0480, 0x24BC004E, 0x3C70011F, ++ 0x0970081C, 0x2470881D, 0x13F0010E, 0x38800112, ++ 0x3F8C0480, 0x24BC004E, 0x196840A0, 0x21694024, ++ 0x1F090000, 0x30C801D6, 0x07024000, 0x1D2E0001, ++ 0x16624014, 0x1F31FFFB, 0x0E684028, 0x2670001F, ++ 0x2F34001F, 0x2E184000, 0x322C0001, 0x2E020000, ++ 0x09240008, 0x1334FFE0, 0x08300005, 0x0B691FF4, ++ 0x206040A2, 0x2D6040A6, 0x322C0001, 0x1F090000, ++ 0x25C40135, 0x356940A0, 0x1C050000, 0x252DFFFF, ++ 0x1531FFFE, 0x21510000, 0x21510000, 0x03691FFA, ++ 0x1C050000, 0x252DFFFF, 0x1531FFFE, 0x21510000, ++ 0x21510000, 0x322C0001, 0x16691FEC, 0x0834FFFE, ++ 0x2B3D00FF, 0x19CC013D, 0x27681FF4, 0x0B240003, ++ 0x0834FFFE, 0x08601FEC, 0x2B26000C, 0x21621FEA, ++ 0x2226005F, 0x35200060, 0x35230000, 0x160B2000, ++ 0x252DFFFF, 0x026140AA, 0x1E2D0001, 0x15072000, ++ 0x3F6B1FEA, 0x28004000, 0x3530FFFD, 0x1F0AC000, ++ 0x35230000, 0x0D631FEA, 0x160B2000, 0x3520000C, ++ 0x35230000, 0x29290007, 0x26C40155, 0x2A250007, ++ 0x23800156, 0x1B210007, 0x1A084000, 0x2D1B4000, ++ 0x33634088, 0x306940AA, 0x3530FFFD, 0x1E2D0001, ++ 0x15072000, 0x252A0008, 0x2A621FE8, 0x2B008000, ++ 0x1D2E0001, 0x1334FFE0, 0x08300005, 0x322C0001, ++ 0x296B1FF0, 0x16691FEC, 0x03601FEE, 0x1A074000, ++ 0x24634000, 0x3A33FFFE, 0x0E530000, 0x0E530000, ++ 0x0E530000, 0x0E530000, 0x0A330002, 0x2A634008, ++ 0x33070000, 0x0B2B0003, 0x09280004, 0x02C0018C, ++ 0x322C0001, 0x34604010, 0x3F8C0480, 0x24BC004E, ++ 0x3C70011F, 0x2A70001C, 0x2470881D, 0x09F0017B, ++ 0x0E691FFE, 0x0D684024, 0x1231FFFF, 0x37D0018B, ++ 0x00691FF6, 0x04140000, 0x3CD001D3, 0x1A084000, ++ 0x22694028, 0x0335001F, 0x3330FFFB, 0x2E184000, ++ 0x36C801D0, 0x322C0001, 0x00601FE2, 0x2670001F, ++ 0x2B008000, 0x3D3CFFFF, 0x30218000, 0x19110000, ++ 0x3A33FFFE, 0x20340010, 0x21C80197, 0x1641C000, ++ 0x0F270002, 0x0E530000, 0x23800199, 0x0E530000, ++ 0x1641C000, 0x31681FEE, 0x356940A0, 0x34604010, ++ 0x166B4000, 0x3304C000, 0x322C0001, 0x0834FFFE, ++ 0x06614004, 0x29604008, 0x0568401C, 0x3F8C0480, ++ 0x24BC004E, 0x3C70011F, 0x2A70001C, 0x1B70821D, ++ 0x19F001A8, 0x3D340008, 0x30C801BA, 0x0E691FFE, ++ 0x0D684024, 0x1231FFFF, 0x36D001BA, 0x00691FF6, ++ 0x04140000, 0x3CD001D3, 0x1A084000, 0x22694028, ++ 0x3330FFFB, 0x0335001F, 0x2E184000, 0x36C801D0, ++ 0x322C0001, 0x00601FE2, 0x2670001F, 0x1B691FE8, ++ 0x3E20000E, 0x29310001, 0x1231FFFF, 0x28D001C2, ++ 0x092CFFFF, 0x378001BE, 0x39694000, 0x0C2207FA, ++ 0x186B4008, 0x096140A8, 0x256340A4, 0x076240AC, ++ 0x236040AE, 0x2E7000B2, 0x3F8C0480, 0x24BC004E, ++ 0x31700484, 0x24E001CD, 0x31200001, 0x20800075, ++ 0x3F200009, 0x2670001F, 0x20800075, 0x3C200005, ++ 0x2670001F, 0x20800075, 0x37200007, 0x2670001F, ++ 0x20800075, 0x08631FE0, 0x35230000, 0x25671FFF, ++ 0x227001C4, 0x229700ED, 0x063C0001, 0x3BC801E2, ++ 0x063C0001, 0x3180022B, 0x2F681FFA, 0x266040A4, ++ 0x3A8C0180, 0x24BC004E, 0x34700184, 0x34E001E7, ++ 0x3B6940A8, 0x126840A2, 0x0B614000, 0x322C0001, ++ 0x296B1FF0, 0x34604010, 0x2A634008, 0x3A8C0180, ++ 0x24BC004E, 0x2A70001C, 0x2470881D, 0x05691FFC, ++ 0x2D3D0000, 0x3DC8022D, 0x252DFFFF, 0x28C8020D, ++ 0x28004000, 0x0034FFF0, 0x3420000B, 0x0ACC022B, ++ 0x156A1FEC, 0x0200C000, 0x1A048000, 0x266340A8, ++ 0x256340A4, 0x3F8C0480, 0x24BC004E, 0x34700184, ++ 0x24E00204, 0x256040A8, 0x1A048000, 0x3A8C0180, ++ 0x24BC004E, 0x32700284, 0x2CE0020A, 0x252DFFFF, ++ 0x17CC0205, 0x2A681FF0, 0x16691FEC, 0x1C050000, ++ 0x036A1FF6, 0x316B1FE2, 0x256040A8, 0x0A6140A4, ++ 0x076240AC, 0x29681FFC, 0x0C2B0002, 0x092CFFFF, ++ 0x206340AE, 0x336040B2, 0x2C8C5080, 0x24BC004E, ++ 0x31700484, 0x3EE0021D, 0x06691FF0, 0x3D201FE8, ++ 0x096140A8, 0x0A500001, 0x09300002, 0x266040A4, ++ 0x36200000, 0x2D6040A6, 0x3A8C0180, 0x24BC004E, ++ 0x34700184, 0x35E00229, 0x31200001, 0x3A6B1FE0, ++ 0x228B4000, 0x06691FF0, 0x156A1FEC, 0x28004000, ++ 0x1A048000, 0x03601FEE, 0x268C0400, 0x2F970085, ++ 0x2D010000, 0x268C0400, 0x2C970259, 0x1E691FE2, ++ 0x252DFFFF, 0x37C8021E, 0x2C611FE2, 0x3297024D, ++ 0x1B360001, 0x0DCC0246, 0x28200078, 0x31681FEE, ++ 0x06691FF0, 0x2C970259, 0x2A681FF0, 0x2E230237, ++ 0x2D010000, 0x2A800259, 0x2A681FF0, 0x1D691FEE, ++ 0x2C970259, 0x31681FEE, 0x2E230237, 0x2D010000, ++ 0x2A800259, 0x2C681FF6, 0x252DFFFF, 0x07024000, ++ 0x2F36FFF0, 0x21320003, 0x3930FFFE, 0x1F060000, ++ 0x0E4A8000, 0x28004000, 0x3C34000F, 0x1A120000, ++ 0x228B4000, 0x0A6140A4, 0x256040A8, 0x3A8C0180, ++ 0x24BC004E, 0x34700184, 0x228B4000, 0x0E631FE6, ++ 0x2B9702A1, 0x239702AF, 0x39681FD6, 0x0E6A1FF2, ++ 0x00691FF6, 0x276B1FF8, 0x1F060000, 0x03270001, ++ 0x0B37FFFE, 0x1F05C000, 0x296B1FF0, 0x32611FF6, ++ 0x3304C000, 0x3C621FF2, 0x1D601FFA, 0x18601FF0, ++ 0x268C0400, 0x339701D9, 0x02030000, 0x053F0001, ++ 0x1FCC029E, 0x238C0100, 0x166A1FD6, 0x06691FF0, ++ 0x28004000, 0x35098000, 0x1A048000, 0x2F970085, ++ 0x2D010000, 0x15684000, 0x35098000, 0x35068000, ++ 0x2F970085, 0x276B1FF8, 0x00691FF6, 0x03270001, ++ 0x0B37FFFE, 0x1C09C000, 0x3A6B1FD6, 0x0E6A1FF2, ++ 0x32611FF6, 0x1F0AC000, 0x3C621FF2, 0x268C0400, ++ 0x339701D9, 0x326B1FD8, 0x166A1FD6, 0x06691FF0, ++ 0x1E631FFA, 0x35098000, 0x34611FF0, 0x02030000, ++ 0x053F0001, 0x1FCC029E, 0x238C0100, 0x1A210000, ++ 0x3C9702E6, 0x22970312, 0x2A681FF0, 0x2460400C, ++ 0x268C0400, 0x31200001, 0x2B800077, 0x37200007, ++ 0x2480029E, 0x0B631FEC, 0x0D691FF2, 0x006A1FFA, ++ 0x06614004, 0x0B691FF4, 0x2C621FD8, 0x15614014, ++ 0x2D3D0000, 0x29C8029F, 0x28004000, 0x0C240002, ++ 0x0834FFFE, 0x0B601FD6, 0x228B4000, 0x0B631FEC, ++ 0x39681FD6, 0x0D691FF2, 0x086A1FF4, 0x28004000, ++ 0x2F970085, 0x399700A9, 0x0F280002, 0x1BC0029F, ++ 0x0C240002, 0x39604014, 0x2F9700B3, 0x0B691FF4, ++ 0x39681FD6, 0x35054000, 0x056A1FF0, 0x18614010, ++ 0x08624000, 0x1F060000, 0x1F060000, 0x23260002, ++ 0x06624008, 0x0B62400C, 0x2C218200, 0x25970079, ++ 0x226B1FF2, 0x086A1FF4, 0x3304C000, 0x2D010000, ++ 0x2F970085, 0x399700A9, 0x0F280002, 0x1BC0029F, ++ 0x0C240002, 0x39604014, 0x35068000, 0x1B624010, ++ 0x39681FD6, 0x396A400C, 0x186B4008, 0x1F060000, ++ 0x2A681FF0, 0x29634004, 0x06624008, 0x27604000, ++ 0x2C218200, 0x25970079, 0x166A1FD6, 0x3A69400C, ++ 0x2A681FF0, 0x35068000, 0x2F970085, 0x229700B7, ++ 0x396B1FEC, 0x228B4000, 0x0B631FEC, 0x2A681FF0, ++ 0x1A048000, 0x2460400C, 0x1A048000, 0x0C240002, ++ 0x19044000, 0x086A1FF4, 0x0D691FF2, 0x3930FFFE, ++ 0x0D500000, 0x0D500000, 0x09300002, 0x2F970085, ++ 0x399700A9, 0x39604014, 0x1B684008, 0x156B400C, ++ 0x2F260001, 0x06691FF0, 0x03280001, 0x1B624010, ++ 0x29604008, 0x06614004, 0x24634000, 0x2C2A0001, ++ 0x36058000, 0x1531FFFE, 0x21510000, 0x21510000, ++ 0x19078000, 0x3A33FFFE, 0x0E530000, 0x0E530000, ++ 0x3B218002, 0x25970079, 0x23260002, 0x1B624010, ++ 0x246A4014, 0x03691FFA, 0x1B684008, 0x319700CB, ++ 0x396B1FEC, 0x228B4000, 0x0B631FEC, 0x2F9700B3, ++ 0x166B4000, 0x1668400C, 0x2763400C, 0x0D691FF2, ++ 0x246A4014, 0x219700E1, 0x3A6B1FD6, 0x0D691FF2, ++ 0x1668400C, 0x1F05C000, 0x086A1FF4, 0x319700CB, ++ 0x2A681FF0, 0x086A1FF4, 0x2D010000, 0x269700D6, ++ 0x229700B7, 0x396B1FEC, 0x228B4000, 0x05631FE4, ++ 0x2A681FF0, 0x2460400C, 0x08691FF8, 0x29611FDE, ++ 0x086A1FF4, 0x21621FDC, 0x350A4000, 0x040E4000, ++ 0x0CD40332, 0x07024000, 0x24260003, 0x2736FFFE, ++ 0x00601FE2, 0x1A048000, 0x0B601FE0, 0x1A048000, ++ 0x35068000, 0x37621FF0, 0x1A048000, 0x0B601FD6, ++ 0x1668400C, 0x2897007D, 0x056A1FF0, 0x1668400C, ++ 0x1A048000, 0x2897007D, 0x0B6A1FF8, 0x32681FE2, ++ 0x296B1FF0, 0x3304C000, 0x00691FF6, 0x2F970085, ++ 0x268C0400, 0x0E6B4024, 0x05631FD2, 0x1A378000, ++ 0x07CC0415, 0x39681FE0, 0x296B1FF0, 0x3304C000, ++ 0x0D691FF2, 0x086A1FF4, 0x2F970085, 0x32681FE2, ++ 0x3930FFFE, 0x0A500001, 0x39681FE0, 0x0D691FF2, ++ 0x2F970085, 0x3B201FD8, 0x0D500000, 0x0D500000, ++ 0x0D691FF2, 0x1531FFFE, 0x0E494000, 0x29310001, ++ 0x05D40418, 0x1231FFFF, 0x36200000, 0x00601FD4, ++ 0x32230001, 0x1E220001, 0x0200C000, 0x2E148000, ++ 0x31C8036D, 0x32681FD4, 0x1A048000, 0x00601FD4, ++ 0x1A074000, 0x35054000, 0x35068000, 0x02CC0366, ++ 0x32681FE2, 0x296B1FF0, 0x3304C000, 0x1A210000, ++ 0x186A1FDE, 0x3397041C, 0x3930FFFE, 0x0B480000, ++ 0x1A388000, 0x05300001, 0x24D0037D, 0x2C250001, ++ 0x25800379, 0x2D3D0000, 0x35C803AF, 0x268C0400, ++ 0x16614018, 0x26218040, 0x25970079, 0x32681FD4, ++ 0x1E691FE2, 0x1531FFFE, 0x0E494000, 0x15072000, ++ 0x1D210001, 0x0B6B4018, 0x3E3FFFFF, 0x03270001, ++ 0x1A11C000, 0x252DFFFF, 0x02164000, 0x326B1FD8, ++ 0x268C0400, 0x21694024, 0x2A611FD2, 0x3BC803A7, ++ 0x1F1F8000, 0x3AC803A0, 0x2C621FD8, 0x21681FF2, ++ 0x0C2107F6, 0x3297041B, 0x1E220001, 0x16624014, ++ 0x39681FD6, 0x29604008, 0x37218001, 0x25970079, ++ 0x15691FD6, 0x32681FE2, 0x086A1FF4, 0x2F260001, ++ 0x3397041C, 0x23218010, 0x25970079, 0x32681FE2, ++ 0x1A210000, 0x086A1FF4, 0x2F260001, 0x3397041C, ++ 0x26218040, 0x25970079, 0x2C800370, 0x39681FE0, ++ 0x296B1FF0, 0x3304C000, 0x2A604004, 0x32681FE2, ++ 0x3304C000, 0x27604000, 0x186A1FDE, 0x3F6B1FDC, ++ 0x3A634014, 0x1F0AC000, 0x2E0EC000, 0x1AD403BD, ++ 0x2D02C000, 0x1B624010, 0x2F218400, 0x25970079, ++ 0x18691FD2, 0x1F1C4000, 0x0DCC03CA, 0x1531FFFE, ++ 0x22484000, 0x063C0001, 0x122D0002, 0x0E494000, ++ 0x2E184000, 0x2DC8040B, 0x268C0400, 0x00684020, ++ 0x05300001, 0x30D00415, 0x09300002, 0x22D003D8, ++ 0x15684000, 0x34694004, 0x2A604004, 0x0B614000, ++ 0x06684010, 0x27694014, 0x39604014, 0x18614010, ++ 0x166B4000, 0x2A634008, 0x0E631FD0, 0x25218020, ++ 0x25970079, 0x2DD003E1, 0x39681FE0, 0x1E691FE2, ++ 0x2A8003E3, 0x32681FE2, 0x15691FE0, 0x086A1FF4, ++ 0x2F260001, 0x3397041C, 0x268C0400, 0x226A4024, ++ 0x25218020, 0x25970079, 0x3F681FD0, 0x1C0A0000, ++ 0x2F260001, 0x15691FE0, 0x296B1FF0, 0x1F05C000, ++ 0x1A1D0000, 0x00CC03F8, 0x32681FE2, 0x15691FE0, ++ 0x0B601FE0, 0x2C611FE2, 0x37681FDE, 0x0E601FDC, ++ 0x2A621FDE, 0x32681FE2, 0x0D691FF2, 0x3297041B, ++ 0x296A4010, 0x1A048000, 0x3930FFFE, 0x268C0400, ++ 0x084B0000, 0x0D500000, 0x0D500000, 0x023F0000, ++ 0x26C80370, 0x23218010, 0x25970079, 0x052CFFFC, ++ 0x268C0400, 0x0D500000, 0x2C800370, 0x1E691FE2, ++ 0x39681FE0, 0x086A1FF4, 0x2F970085, 0x16624014, ++ 0x31200001, 0x1A210000, 0x156B400C, 0x1B631FF0, ++ 0x20800075, 0x24200017, 0x1B210007, 0x3D800412, ++ 0x3A200003, 0x0621001F, 0x3D800412, 0x086A1FF4, ++ 0x1B624010, 0x16624014, 0x27604000, 0x06614004, ++ 0x29604008, 0x228B4000, 0x0E631FE6, 0x2C681FF6, ++ 0x08691FF8, 0x086A1FF4, 0x1D601FCC, 0x37611FCA, ++ 0x39621FF8, 0x24260003, 0x2736FFFE, 0x39621FCE, ++ 0x296B1FF0, 0x19078000, 0x19078000, 0x1D631FF6, ++ 0x19078000, 0x1B631FF0, 0x2E970327, 0x063C0001, ++ 0x28C80437, 0x063C0001, 0x2A800455, 0x2A681FF0, ++ 0x0B6A1FCE, 0x19088000, 0x2897007D, 0x06691FF0, ++ 0x0B6A1FCE, 0x2B034000, 0x28004000, 0x19078000, ++ 0x24634000, 0x19088000, 0x19088000, 0x2097008A, ++ 0x06691FF0, 0x0B6A1FCE, 0x28004000, 0x19088000, ++ 0x3930FFFE, 0x0A500001, 0x0F280002, 0x09300002, ++ 0x19088000, 0x19088000, 0x18601FF0, 0x2097008A, ++ 0x03691FCC, 0x066A1FCA, 0x32611FF6, 0x39621FF8, ++ 0x31200001, 0x268C0400, 0x2B800077, 0x0D601FD0, ++ 0x296A4010, 0x15684000, 0x2C621FD8, 0x08601FDA, ++ 0x10691FDC, 0x2A681FF0, 0x07024000, 0x36064000, ++ 0x36064000, 0x2897007D, 0x1E6A1FD8, 0x3A681FDA, ++ 0x1B624010, 0x27604000, 0x3F681FD0, 0x063C0001, ++ 0x09CC0471, 0x216B1FFE, 0x071BC000, 0x25D0046F, ++ 0x229706BB, 0x0D601FD0, 0x33800476, 0x379706AD, ++ 0x33800476, 0x0D3C0003, 0x08CC0476, 0x36970483, ++ 0x31200001, 0x0D601FD0, 0x3F681FD0, 0x35230000, ++ 0x2D010000, 0x293D000D, 0x0ACC047D, 0x34230007, ++ 0x3C800480, 0x2E3D000C, 0x36C80480, 0x2923001F, ++ 0x268C0400, 0x39634018, 0x2B800077, 0x08631FD6, ++ 0x37681FB2, 0x03691FFA, 0x086A1FF4, 0x2F970085, ++ 0x16624014, 0x2F681FFA, 0x226B1FF2, 0x136A1FDC, ++ 0x1D691FB4, 0x1A048000, 0x2A604004, 0x05614008, ++ 0x24634000, 0x25218020, 0x25970079, 0x3A681FB6, ++ 0x3930FFFE, 0x0A500001, 0x3A6B1FD6, 0x228B4000, ++ 0x1A048000, 0x3930FFFE, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x228B4000, 0x086A1FF4, ++ 0x1D2E0001, 0x1B624010, 0x0B614000, 0x29604008, ++ 0x268C0400, 0x2A70001C, 0x2470881D, 0x36058000, ++ 0x1A048000, 0x228B4000, 0x27604000, 0x27681FF4, ++ 0x05614008, 0x34604010, 0x268C0400, 0x15624018, ++ 0x2E020000, 0x29218080, 0x23800079, 0x08631FD6, ++ 0x387000C4, 0x249700EB, 0x246B1FF4, 0x08270003, ++ 0x0B37FFFE, 0x0D631FDC, 0x2D010000, 0x2A3D0001, ++ 0x238C0100, 0x1ACC0457, 0x3D6A40A2, 0x176840A8, ++ 0x2F260001, 0x27970498, 0x21681FF2, 0x086A1FF4, ++ 0x27970498, 0x2F260001, 0x2736FFFE, 0x0F6240A2, ++ 0x026240A6, 0x3A6B1FD6, 0x228B4000, 0x08631FD6, ++ 0x3A6B1FD6, 0x228B4000, 0x08631FD6, 0x136A1FDC, ++ 0x06691FF0, 0x3D201FB2, 0x2D230012, 0x35098000, ++ 0x36058000, 0x15410000, 0x3E2C0002, 0x0A2FFFFF, ++ 0x0FCC04D4, 0x37681FB2, 0x2897007D, 0x136A1FDC, ++ 0x3A681FB6, 0x1D32FFFC, 0x2897007D, 0x2E97052B, ++ 0x16691FB6, 0x21681FF2, 0x1E220001, 0x2A9704AA, ++ 0x1E220001, 0x1B691FB2, 0x3F970530, 0x3A6B1FD6, ++ 0x228B4000, 0x08631FD6, 0x3F6B1FDC, 0x0D691FF2, ++ 0x1D6A1FD4, 0x1F05C000, 0x2E97051D, 0x15691FBA, ++ 0x1E220001, 0x3F970530, 0x106A1FD0, 0x03691FFA, ++ 0x2E97051D, 0x216B1FFE, 0x03691FFA, 0x071BC000, ++ 0x1ED404FF, 0x3F6B1FDC, 0x036A1FC0, 0x1F05C000, ++ 0x1F05C000, 0x2E97051D, 0x34800502, 0x15691FBA, ++ 0x2C681FC0, 0x2697049F, 0x13691FD0, 0x34681FBE, ++ 0x036A1FC0, 0x286040AC, 0x096140A8, 0x096240A4, ++ 0x358C5000, 0x28700384, 0x3A6B1FD6, 0x228B4000, ++ 0x136A1FDC, 0x15691FBA, 0x16624014, 0x1632FFFE, ++ 0x35098000, 0x0B614000, 0x0A6140A4, 0x16691FB6, ++ 0x1D6A1FB8, 0x05614008, 0x0B691FF4, 0x05624004, ++ 0x1E2D0001, 0x18614010, 0x228B4000, 0x1B684008, ++ 0x2B800527, 0x0B631FEC, 0x0B614000, 0x06624008, ++ 0x2B008000, 0x13218800, 0x25970079, 0x086A1FF4, ++ 0x27970498, 0x1B684008, 0x396B1FEC, 0x256040A8, ++ 0x358C5000, 0x34700184, 0x228B4000, 0x086A1FF4, ++ 0x1D691FB4, 0x1B624010, 0x0A6140A4, 0x228B4000, ++ 0x28004000, 0x1531FFFE, 0x268C0400, 0x3F424000, ++ 0x2B800527, 0x2C8C5080, 0x24BC004E, 0x13204096, ++ 0x228B4000, 0x2C8C5080, 0x24BC004E, 0x13204096, ++ 0x3E500C63, 0x228B4000, 0x2C681FF6, 0x252DFFFF, ++ 0x07024000, 0x2F36FFF0, 0x21320003, 0x3930FFFE, ++ 0x1F060000, 0x0E4A8000, 0x28004000, 0x3C34000F, ++ 0x1A120000, 0x02624090, 0x228B4000, 0x036A1FC0, ++ 0x096140A8, 0x096240A4, 0x238C0100, 0x34700184, ++ 0x0E6A1FF2, 0x05624004, 0x086A1FF4, 0x16624014, ++ 0x0B614000, 0x05614008, 0x238C0100, 0x20694080, ++ 0x18350001, 0x03CC055B, 0x228B4000, 0x1D2E0001, ++ 0x1B624010, 0x25218020, 0x23800079, 0x08631FD6, ++ 0x16502DE7, 0x3F502084, 0x36970539, 0x13502931, ++ 0x35970535, 0x0F6B4080, 0x25370020, 0x0FCC071D, ++ 0x13503548, 0x03501CE4, 0x36970539, 0x315024A9, ++ 0x35970535, 0x0350A148, 0x0A5035A4, 0x36970539, ++ 0x3350252E, 0x35970535, 0x0E502929, 0x145035B0, ++ 0x36970539, 0x3F502108, 0x35970535, 0x2B5025A9, ++ 0x1D502CA6, 0x36970539, 0x1450288A, 0x35970535, ++ 0x2350B4EB, 0x18509525, 0x36970539, 0x37501086, ++ 0x35970535, 0x0F502D67, 0x035035AD, 0x36970539, ++ 0x1C501991, 0x35970535, 0x0F6B4080, 0x00631FEE, ++ 0x235098C4, 0x27509DAF, 0x36970539, 0x1450316C, ++ 0x35970535, 0x00509148, 0x1E502CC6, 0x36970539, ++ 0x1A50358E, 0x35970535, 0x355099AB, 0x3A6B1FD6, ++ 0x228B4000, 0x08631FD6, 0x30700090, 0x3A97050C, ++ 0x358C5000, 0x23700080, 0x13204096, 0x3E500C63, ++ 0x235024E4, 0x13204096, 0x3E500C63, 0x045030A6, ++ 0x35970535, 0x2850B12C, 0x395020EE, 0x36970539, ++ 0x0B5028AF, 0x35970535, 0x3D50A90A, 0x3D50AD8C, ++ 0x35970535, 0x29503D6B, 0x1850C54A, 0x36970539, ++ 0x0F6B4080, 0x00631FEE, 0x23700080, 0x1C50352B, ++ 0x35970535, 0x326B1FEE, 0x236A4080, 0x07330006, ++ 0x14D405B9, 0x2B320006, 0x27D005DE, 0x3220000D, ++ 0x21800457, 0x3E500C63, 0x16502D8B, 0x36970539, ++ 0x3450252F, 0x35970535, 0x3950252B, 0x3350210B, ++ 0x36970539, 0x1B5018E5, 0x35970535, 0x3E500C63, ++ 0x205044D1, 0x36970539, 0x3D502409, 0x35970535, ++ 0x0550A531, 0x065018CB, 0x35970535, 0x3E500C63, ++ 0x32504409, 0x36970539, 0x2450112C, 0x35970535, ++ 0x3650B62D, 0x0D50300C, 0x35970535, 0x3E500C63, ++ 0x025035AA, 0x35970535, 0x2550B50D, 0x3B502520, ++ 0x35970535, 0x1B501C63, 0x3350140D, 0x35970535, ++ 0x3A6B1FD6, 0x228B4000, 0x2E97052B, 0x3F6B1FDC, ++ 0x0D691FF2, 0x1D6A1FD4, 0x1F05C000, 0x2E97051D, ++ 0x1E691FB8, 0x3F681FD0, 0x2697049F, 0x13691FD0, ++ 0x12220002, 0x3F970530, 0x1E691FB8, 0x2C681FC0, ++ 0x249704A2, 0x00691FC0, 0x15220003, 0x3F970530, ++ 0x3A97050C, 0x358C5000, 0x23700080, 0x13204096, ++ 0x3E500C63, 0x3F502084, 0x13204096, 0x3E500C63, ++ 0x0B5035CF, 0x35970535, 0x3E500C63, 0x0C502D07, ++ 0x36970539, 0x195034AD, 0x35970535, 0x3E500C63, ++ 0x325024A5, 0x36970539, 0x165029AE, 0x35970535, ++ 0x0F503144, 0x2F502531, 0x36970539, 0x0250194A, ++ 0x35970535, 0x295010C8, 0x0E50318C, 0x36970539, ++ 0x085028CF, 0x35970535, 0x24502569, 0x195019AD, ++ 0x36970539, 0x25501004, 0x35970535, 0x3E50B08C, ++ 0x11502D29, 0x36970539, 0x1B5019A6, 0x35970535, ++ 0x3E500C63, 0x3450140C, 0x36970539, 0x2750218F, ++ 0x35970535, 0x2550AD0B, 0x04502940, 0x35970535, ++ 0x3E500C63, 0x0C50300B, 0x36970539, 0x3C5011AB, ++ 0x35970535, 0x3250B585, 0x3B502520, 0x35970535, ++ 0x3E500C63, 0x0E5035A9, 0x35970535, 0x3350B54D, ++ 0x15502C0B, 0x35970535, 0x1B501C63, 0x3350140D, ++ 0x35970535, 0x3A6B1FD6, 0x228B4000, 0x08631FD6, ++ 0x2E97052B, 0x03691FCC, 0x3F6B1FDC, 0x2F681FFA, ++ 0x1E220001, 0x3304C000, 0x2A9704AA, 0x2897051B, ++ 0x08691FCE, 0x3F6B1FDC, 0x21681FF2, 0x1E220001, ++ 0x3304C000, 0x3304C000, 0x2A9704AA, 0x2897051B, ++ 0x30700090, 0x3A97050C, 0x358C5000, 0x13204096, ++ 0x3E500C63, 0x0B502A25, 0x13204096, 0x3E500C63, ++ 0x2250248F, 0x35970535, 0x0250292A, 0x285020AF, ++ 0x36970539, 0x25501004, 0x35970535, 0x00502D04, ++ 0x295038AE, 0x36970539, 0x245024E5, 0x35970535, ++ 0x1650A088, 0x2A50392E, 0x36970539, 0x19502D4B, ++ 0x35970535, 0x3E500C63, 0x0A502924, 0x36970539, ++ 0x0F502CEB, 0x35970535, 0x00502DCB, 0x3B5011AA, ++ 0x36970539, 0x3F502108, 0x35970535, 0x3E500C63, ++ 0x15502C0B, 0x36970539, 0x2A5020C8, 0x35970535, ++ 0x2550AD0B, 0x0D502925, 0x35970535, 0x1B501C63, ++ 0x3550140B, 0x36970539, 0x185019AA, 0x35970535, ++ 0x3A6B1FD6, 0x228B4000, 0x08631FD6, 0x21681FF2, ++ 0x10691FDC, 0x086A1FF4, 0x19044000, 0x27604000, ++ 0x27970498, 0x21681FF2, 0x35054000, 0x19044000, ++ 0x27970498, 0x07024000, 0x39694000, 0x29681FCA, ++ 0x2F970085, 0x3A97050C, 0x13204096, 0x268C0400, ++ 0x3E500C63, 0x225020C6, 0x36970539, 0x325024A5, ++ 0x35970535, 0x3E500C63, 0x0E502D0C, 0x36970539, ++ 0x1C502884, 0x35970535, 0x3E500C63, 0x335021A8, ++ 0x36970539, 0x00502C2B, 0x35970535, 0x1450296A, ++ 0x30502028, 0x35970535, 0x0D50A509, 0x09502944, ++ 0x35970535, 0x3E500C63, 0x325024C9, 0x35970535, ++ 0x1B50A549, 0x2A502144, 0x36970539, 0x3D502409, ++ 0x35970535, 0x358C5000, 0x0F6B4080, 0x3E370008, ++ 0x0CCC06AB, 0x2720001B, 0x21800457, 0x3A6B1FD6, ++ 0x228B4000, 0x08631FD6, 0x2C681FC0, 0x3930FFFE, ++ 0x0A500001, 0x1B204098, 0x1A5000E4, 0x1B204098, ++ 0x025004E5, 0x36970539, 0x325008E6, 0x35970535, ++ 0x238C0100, 0x3A6B1FD6, 0x228B4000, 0x08631FD6, ++ 0x2C681FC0, 0x3930FFFE, 0x358C5000, 0x0A500001, ++ 0x1B204098, 0x175018E6, 0x296B1FF0, 0x2C681FF6, ++ 0x08691FF8, 0x10631FC4, 0x18601FC6, 0x3C611FC8, ++ 0x3F6B1FDC, 0x39681FD6, 0x18631FCA, 0x1D601FCC, ++ 0x34681FBE, 0x0B691FF4, 0x2F6B1FC0, 0x1E2D0001, ++ 0x3A611FF8, 0x1B631FF0, 0x1E601FF6, 0x358C5000, ++ 0x2E970327, 0x226B1FC4, 0x056A1FC6, 0x0E691FC8, ++ 0x1B631FF0, 0x31621FF6, 0x3A611FF8, 0x2A6B1FCA, ++ 0x006A1FCC, 0x0D631FDC, 0x24621FD6, 0x268C0400, ++ 0x02030000, 0x053F0001, 0x1CCC06ED, 0x15691FBA, ++ 0x2D97054B, 0x13691FBC, 0x2D97054B, 0x136A1FDC, ++ 0x15691FBA, 0x2A681FF0, 0x35068000, 0x2F970085, ++ 0x31200001, 0x3A6B1FD6, 0x228B4000, 0x19220000, ++ 0x3C8006F3, 0x00220080, 0x3C8006F3, 0x09661FFF, ++ 0x0E631FE6, 0x309704B3, 0x249704CE, 0x2E9704CB, ++ 0x309704E9, 0x2E97052B, 0x18691FD2, 0x14220004, ++ 0x3F970530, 0x08691FCE, 0x3F6B1FDC, 0x21681FF2, ++ 0x12220002, 0x3304C000, 0x3304C000, 0x2A9704AA, ++ 0x2897051B, 0x3A97050C, 0x1A21889C, 0x0A614092, ++ 0x358C5000, 0x23700080, 0x1E691FE2, 0x3797053E, ++ 0x13204096, 0x095029E7, 0x035030A7, 0x13204096, ++ 0x095029E7, 0x325024A5, 0x35970535, 0x3397055F, ++ 0x02194000, 0x3CC80720, 0x3797053E, 0x1B204098, ++ 0x035030A7, 0x36970539, 0x325024A5, 0x35970535, ++ 0x3C800713, 0x358C5000, 0x29200013, 0x21800457, ++ 0x358C5000, 0x236A4080, 0x09360020, 0x04CC0729, ++ 0x35970633, 0x358C5000, 0x29970676, 0x31200001, ++ 0x21800457, 0x1E6A1FEE, 0x1C6B4090, 0x27320005, ++ 0x1A1EC000, 0x1B360001, 0x28C80731, 0x3220000D, ++ 0x21800457, 0x3D200002, 0x21800457, 0x0F220040, ++ 0x24800737, 0x162200C0, 0x24800737, 0x09661FFF, ++ 0x0E631FE6, 0x309704B3, 0x249704CE, 0x2E9704CB, ++ 0x166A1FBA, 0x03691FFA, 0x2E97051D, 0x3F6B1FDC, ++ 0x03691FFA, 0x0B6A1FCE, 0x1F05C000, 0x2E97051D, ++ 0x1B6A1FBE, 0x00691FF6, 0x2E97051D, 0x3F6B1FDC, ++ 0x00691FF6, 0x106A1FD0, 0x1F05C000, 0x2E97051D, ++ 0x22681FFE, 0x07180000, 0x2CD00756, 0x1B691FB2, ++ 0x3F681FBC, 0x249704A2, 0x1B691FB2, 0x2C681FC0, ++ 0x249704A2, 0x2B800762, 0x3F6B1FDC, 0x03691FFA, ++ 0x106A1FBC, 0x1F05C000, 0x1F05C000, 0x2E97051D, ++ 0x3F6B1FDC, 0x00691FF6, 0x036A1FC0, 0x1F05C000, ++ 0x1F05C000, 0x2E97051D, 0x39970595, 0x358C5000, ++ 0x29970676, 0x31200001, 0x21800457, 0x0C220020, ++ 0x29800769, 0x09661FFF, 0x0E631FE6, 0x309704B3, ++ 0x249704CE, 0x2E9704CB, 0x309704E9, 0x2E97052B, ++ 0x18691FD2, 0x12220002, 0x3F970530, 0x32681FD4, ++ 0x18691FD2, 0x27604000, 0x06614004, 0x24681FCE, ++ 0x29604008, 0x238C0100, 0x25218020, 0x1B61401C, ++ 0x27604000, 0x29604008, 0x12220002, 0x268C0400, ++ 0x15624018, 0x26218040, 0x1B61401C, 0x3A97050C, ++ 0x1A21889C, 0x0A614092, 0x358C5000, 0x23700080, ++ 0x1E691FE2, 0x3797053E, 0x13204096, 0x358C5000, ++ 0x2A5020A4, 0x13204096, 0x1F50A4A4, 0x35970535, ++ 0x145028E6, 0x1A503108, 0x35970535, 0x358C5000, ++ 0x2150ACE6, 0x17503529, 0x0F6B4080, 0x13204096, ++ 0x25370020, 0x0FCC071D, 0x1B50C1AC, 0x31502549, ++ 0x35970535, 0x3E500C63, 0x3C502168, 0x35970535, ++ 0x04502D09, 0x3D5011AC, 0x35970535, 0x0D50A509, ++ 0x0E5029D0, 0x35970535, 0x2450214C, 0x1050196B, ++ 0x35970535, 0x3E500C63, 0x12501D29, 0x35970535, ++ 0x3E500C63, 0x14509510, 0x35970535, 0x3E500C63, ++ 0x3F509DE7, 0x35970535, 0x0F6B4080, 0x00631FEE, ++ 0x02194000, 0x38C807B8, 0x3797053E, 0x3F80078A, ++ 0x358C5000, 0x236A4080, 0x09360020, 0x16CC07C7, ++ 0x30700090, 0x02501865, 0x35970535, 0x1B501C63, ++ 0x35970535, 0x38501463, 0x35970535, 0x2C681FC0, ++ 0x268C0400, 0x31200001, 0x21800457, 0x1E6A1FEE, ++ 0x1C6B4090, 0x27320005, 0x1A1EC000, 0x1B360001, ++ 0x35C807BC, 0x3220000D, 0x21800457, 0x1E79084F ++}; ++ ++static const uint32_t fw1_boot_img_data_buf[] = ++{ ++ 0x36200000, 0x11210002, 0x15710249, 0x31200001, ++ 0x2860B41C, 0x21970074, 0x1A210000, 0x1231FFFF, ++ 0x1B390001, 0x092CFFFF, 0x00CC0007, 0x0761B140, ++ 0x3A200333, 0x3060B438, 0x3E60B45C, 0x3D60B43C, ++ 0x0A20FFFF, 0x2D60B420, 0x1A210000, 0x1F68B420, ++ 0x0A61B422, 0x1234FEFE, 0x05300001, 0x2D60B420, ++ 0x0C61B424, 0x0761B426, 0x0F61B428, 0x0461B42A, ++ 0x0261B42C, 0x0961B42E, 0x1F61B434, 0x1461B436, ++ 0x21970074, 0x1C21A0CA, 0x33228000, 0x3F424000, ++ 0x032D0100, 0x092CFFFF, 0x18CC0023, 0x16710449, ++ 0x1CB8002B, 0x30224000, 0x2C80002C, 0x19220000, ++ 0x06210045, 0x0C61B424, 0x35230000, 0x2D63B42C, ++ 0x21970074, 0x13232000, 0x0C62B428, 0x3063B434, ++ 0x16210333, 0x278C0078, 0x37BC005E, 0x1C61B438, ++ 0x092CFFFF, 0x0CCC0032, 0x0A710649, 0x21970074, ++ 0x1721A0C8, 0x19220000, 0x3F424000, 0x122D0002, ++ 0x3F424000, 0x182D00FE, 0x092CFFFF, 0x0FCC003E, ++ 0x1A223000, 0x2F712049, 0x1FB8004B, 0x33214000, ++ 0x35230000, 0x3F222000, 0x2880004D, 0x1A210000, ++ 0x35230000, 0x1820B424, 0x19500011, 0x0A500001, ++ 0x1150C400, 0x0A500001, 0x0261B42C, 0x2663B42E, ++ 0x1C62B434, 0x39230333, 0x278C0078, 0x37BC005E, ++ 0x3363B438, 0x36200000, 0x2B60B140, 0x13710149, ++ 0x398C0000, 0x3C80005C, 0x3371FF49, 0x3C80005C, ++ 0x2A320001, 0x0A367FFF, 0x2CC80073, 0x252A0008, ++ 0x0EC0006F, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x2CC80073, 0x35800063, 0x26260008, ++ 0x0D500000, 0x262EFFFF, 0x11CC0070, 0x228B4000, ++ 0x0868B1F8, 0x3C34000F, 0x0128000A, 0x26C4007A, ++ 0x0224000A, 0x228B4000, 0x3320000A, 0x228B4000, ++ 0x01000000, 0x01000000, 0x01000000 ++}; ++ ++static const uint32_t fw1_master_img_data_buf[] = ++{ ++ 0x36200000, 0x11210002, 0x3C605FF4, 0x1B615FF6, ++ 0x36200000, 0x2560B148, 0x1A205FE0, 0x38215FE8, ++ 0x3B230008, 0x1F090000, 0x15C00104, 0x31200001, ++ 0x2860B41C, 0x2A9700B9, 0x329700C7, 0x1C208000, ++ 0x2B60B140, 0x01000000, 0x19220000, 0x0B685FFE, ++ 0x2469B1F8, 0x2B3C4600, 0x1ECC0013, 0x1D2E0001, ++ 0x28038000, 0x01000000, 0x0A2FFFFF, 0x1BCC0019, ++ 0x0B685FFE, 0x2469B1F8, 0x2B3C4600, 0x22C80021, ++ 0x25800013, 0x056B5FFA, 0x333B0000, 0x14D40026, ++ 0x363700FF, 0x2E63B47A, 0x3A200333, 0x3060B438, ++ 0x3E60B45C, 0x3D60B43C, 0x39230003, 0x2F22B400, ++ 0x0A20FFFF, 0x13408000, 0x1A210000, 0x21488000, ++ 0x23260002, 0x3F418000, 0x1234FEFE, 0x05300001, ++ 0x202A0002, 0x13408000, 0x3D260020, 0x0A2FFFFF, ++ 0x17CC002C, 0x36200000, 0x3E60B406, 0x2D60B416, ++ 0x2B60B426, 0x3860B436, 0x2860B446, 0x3B60B456, ++ 0x036B5FFC, 0x00210100, 0x05222F00, 0x29370080, ++ 0x27C80047, 0x1A210000, 0x1A223000, 0x1820B424, ++ 0x19500011, 0x0A500001, 0x1150C400, 0x0A500001, ++ 0x15410000, 0x3E2C0002, 0x0D500000, 0x1C62B434, ++ 0x10205E90, 0x0D220164, 0x0D970F97, 0x2469B1F8, ++ 0x15220333, 0x36200000, 0x278C0078, 0x30BC00FC, ++ 0x1F62B438, 0x2060B424, 0x2B60B426, 0x33610102, ++ 0x1035000F, 0x38610100, 0x0A68B400, 0x3369B420, ++ 0x32605FCA, 0x13615FCE, 0x353400FF, 0x2C380200, ++ 0x34605FCC, 0x2535FF00, 0x17390002, 0x08615FD0, ++ 0x1E970F24, 0x31200001, 0x2E605EA0, 0x202001A0, ++ 0x1760010C, 0x35203000, 0x1C60010E, 0x31200001, ++ 0x2560B148, 0x30695EA0, 0x33228000, 0x28004000, ++ 0x063C0001, 0x1FCC0078, 0x0462B140, 0x2280007E, ++ 0x28004000, 0x0C3C0004, 0x19CC007E, 0x1968B140, ++ 0x283C4000, 0x2B60B140, 0x1035000F, 0x1231FFFF, ++ 0x0B2D0082, 0x0D894000, 0x248C1D78, 0x318000A1, ++ 0x2F8C1D7A, 0x318000A1, 0x3D8C1DF8, 0x318000A1, ++ 0x368C1DFA, 0x318000A1, 0x298C1D7C, 0x318000A1, ++ 0x228C1D7E, 0x318000A1, 0x308C1DFC, 0x318000A1, ++ 0x3B8C1DFE, 0x318000A1, 0x238C1D79, 0x318000A1, ++ 0x288C1D7B, 0x318000A1, 0x3A8C1DF9, 0x318000A1, ++ 0x318C1DFB, 0x318000A1, 0x2E8C1D7D, 0x318000A1, ++ 0x258C1D7F, 0x318000A1, 0x378C1DFD, 0x318000A1, ++ 0x3C8C1DFF, 0x35B000FA, 0x07BC0C07, 0x29D80CD4, ++ 0x3FA00C08, 0x1DA40C2E, 0x1CA80C49, 0x11F80F12, ++ 0x39E80CF2, 0x32E00118, 0x336A5EA0, 0x362300AF, ++ 0x17360002, 0x33C800AF, 0x20AC0E9D, 0x31215EA2, ++ 0x07220014, 0x14970FB4, 0x27C80071, 0x21884000, ++ 0x30380000, 0x32C80112, 0x31215EA2, 0x07220014, ++ 0x1D800FD7, 0x36200000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x36200000, 0x2760B000, ++ 0x2960B008, 0x1E220001, 0x1B62B010, 0x3760B01C, ++ 0x10228800, 0x1862B01C, 0x228B4000, 0x0868B1F8, ++ 0x2D635E96, 0x3C34000F, 0x02030000, 0x022B000A, ++ 0x05C000CE, 0x3320000A, 0x02030000, 0x1A210000, ++ 0x1231FFFF, 0x1B390001, 0x092CFFFF, 0x1DCC00D0, ++ 0x0761B140, 0x33228000, 0x2D010000, 0x20310008, ++ 0x1A39A0CA, 0x3F424000, 0x19220000, 0x3F424000, ++ 0x0C220020, 0x392DFFBA, 0x3F424000, 0x3860B150, ++ 0x1A22C000, 0x22520000, 0x22520000, 0x19220000, ++ 0x302DFF7C, 0x3F424000, 0x172D0008, 0x3F424000, ++ 0x1E220001, 0x172D0008, 0x3F424000, 0x19220000, ++ 0x1A2D000C, 0x3F424000, 0x10228800, 0x3F424000, ++ 0x06220400, 0x0962B144, 0x2E020000, 0x033A0200, ++ 0x0962B144, 0x322C0001, 0x0A2FFFFF, 0x17CC00D5, ++ 0x1F6B5E96, 0x228B4000, 0x0422008D, 0x2480010D, ++ 0x09220089, 0x2480010D, 0x0C220083, 0x2480010D, ++ 0x0A220085, 0x2480010D, 0x13220005, 0x2480010D, ++ 0x01220087, 0x2480010D, 0x18220007, 0x2480010D, ++ 0x0D220011, 0x2480010D, 0x0222008B, 0x2480010D, ++ 0x1B22000B, 0x15625FF2, 0x32635FF0, 0x23320008, ++ 0x0A62B148, 0x33D00113, 0x228B4000, 0x31200001, ++ 0x2A9700B9, 0x329700C7, 0x398C0000, 0x35800116, ++ 0x33695F20, 0x3A20012C, 0x1C35C000, 0x36C8011F, ++ 0x12685F24, 0x043D4000, 0x08CC00AA, 0x3C2300AA, ++ 0x336A5EA0, 0x03210080, 0x2736FFFE, 0x01625EA0, ++ 0x37655F21, 0x288000B4, 0x33695F20, 0x12685F24, ++ 0x1C35C000, 0x2E3DC000, 0x3FC80120, 0x228B4000, ++ 0x01970F37, 0x26C801CC, 0x20605F24, 0x00685FFC, ++ 0x1A210000, 0x09615F2E, 0x3F340003, 0x212C013E, ++ 0x21884000, 0x36200000, 0x2360B122, 0x3D800142, ++ 0x146BB124, 0x38695F22, 0x36200000, 0x37370001, ++ 0x03CC0148, 0x3965B123, 0x3D800142, 0x2C800135, ++ 0x28800138, 0x2597010C, 0x1168B122, 0x3B69B124, ++ 0x2F34001F, 0x29310001, 0x19110000, 0x19D401C2, ++ 0x036B5FFC, 0x1C645F20, 0x0A37FF00, 0x0F330008, ++ 0x300B0000, 0x08C001BF, 0x3D6A5F24, 0x3F215F26, ++ 0x0C2E0040, 0x13408000, 0x3330FFFB, 0x1C2C4000, ++ 0x02970FF4, 0x35695F26, 0x362C000C, 0x13350003, ++ 0x06CC01BB, 0x3F215F26, 0x2222FFFE, 0x1C97100A, ++ 0x3E695F24, 0x382C0004, 0x244A0000, 0x042D0042, ++ 0x3F424000, 0x1D2E0001, 0x16420000, 0x1797103E, ++ 0x0E970C64, 0x19685F26, 0x3D695F28, 0x3660B408, ++ 0x1161B40A, 0x12685F24, 0x2421B40E, 0x3B60B40C, ++ 0x21510000, 0x24200021, 0x3560B404, 0x20200040, ++ 0x2660B414, 0x36200175, 0x0F210163, 0x362300AF, ++ 0x1D800C8B, 0x1F685F20, 0x316A5FE8, 0x353400FF, ++ 0x26605F22, 0x1D2E0001, 0x03625FE8, 0x02030000, ++ 0x3330FFFB, 0x0F2C4010, 0x244A0000, 0x382C0004, ++ 0x27490000, 0x2C3B0400, 0x1E2D0001, 0x350A4000, ++ 0x36C40186, 0x1A210000, 0x15410000, 0x12685F24, ++ 0x2B63B120, 0x3D2C0038, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x002CFFF6, 0x244A0000, ++ 0x052CFFCA, 0x146B5F2E, 0x36368000, 0x13CC019B, ++ 0x333B0000, 0x34C801B7, 0x332F003C, 0x3A40C000, ++ 0x0C685F30, 0x20605F24, 0x3E8001B7, 0x25605F2E, ++ 0x333B0000, 0x17CC01A0, 0x3E605F30, 0x278001A2, ++ 0x332F003C, 0x3A40C000, 0x33695F20, 0x1768B124, ++ 0x1E220001, 0x35230000, 0x193500FF, 0x190B4000, ++ 0x1912C000, 0x2E148000, 0x04CC01B0, 0x28970108, ++ 0x282301A2, 0x23635F24, 0x20200040, 0x258001C5, ++ 0x01970F37, 0x20C801CA, 0x20605F24, 0x1F685F20, ++ 0x3D6A5F24, 0x353400FF, 0x3980014F, 0x35215FDA, ++ 0x03970F50, 0x2D2301C4, 0x3B8001D1, 0x1F685F20, ++ 0x20970106, 0x353400FF, 0x2F8001C0, 0x2597010C, ++ 0x2F380400, 0x2860B120, 0x12685F24, 0x15970F4A, ++ 0x36200000, 0x336A5EA0, 0x1B645F21, 0x183A0001, ++ 0x01625EA0, 0x398000AF, 0x302301B0, 0x2B8001CD, ++ 0x3923012C, 0x23635F24, 0x392000C0, 0x1B645F21, ++ 0x398000AF, 0x2B695F32, 0x1C208000, 0x28150000, ++ 0x30C801D6, 0x228B4000, 0x35605F32, 0x392001D9, ++ 0x288000B4, 0x18685FD8, 0x3E215FD8, 0x30380000, ++ 0x2BC801FE, 0x1D970F72, 0x33605F34, 0x2D010000, ++ 0x3E2C0034, 0x0B480000, 0x3C6A5FEC, 0x02030000, ++ 0x3C34000F, 0x1D2E0001, 0x0E625FEC, 0x19220000, ++ 0x14625F3A, 0x3562013E, 0x0C330004, 0x3F37000F, ++ 0x3E2F01EE, 0x228B4000, 0x358003C6, 0x3A800550, ++ 0x2B8006EE, 0x328006FB, 0x32800211, 0x32800211, ++ 0x32800211, 0x32800211, 0x32800211, 0x32800211, ++ 0x32800211, 0x32800211, 0x32800211, 0x32800211, ++ 0x02800BD7, 0x32800211, 0x33605F34, 0x35605F32, ++ 0x398000AF, 0x112200C1, 0x38800214, 0x192200A3, ++ 0x38800214, 0x0F22008F, 0x38800214, 0x0A220085, ++ 0x38800214, 0x162200C0, 0x38800214, 0x152200A0, ++ 0x38800214, 0x122200A1, 0x38800214, 0x07220081, ++ 0x38800214, 0x01220087, 0x38800214, 0x19220000, ++ 0x07685F32, 0x1F625F38, 0x33230219, 0x16341000, ++ 0x05CC02B1, 0x3697036F, 0x01685F34, 0x2D6A5F38, ++ 0x35230229, 0x392C0035, 0x27460000, 0x2D695F34, ++ 0x32800284, 0x1160013C, 0x2B635F46, 0x3697036F, ++ 0x39200226, 0x38605F36, 0x3B9703A4, 0x00CC0274, ++ 0x37970247, 0x0A6A010C, 0x35680110, 0x3D2A01A0, ++ 0x3FC801D9, 0x30380000, 0x0ECC01D9, 0x28620110, ++ 0x1D970C74, 0x1A6A0110, 0x1820B424, 0x19500011, ++ 0x0A500001, 0x1150C400, 0x0A500001, 0x1B5001A0, ++ 0x0D500000, 0x1C62B434, 0x0421023D, 0x3A2301D9, ++ 0x12940C8E, 0x3D6B0112, 0x0F2201A0, 0x3862010C, ++ 0x36200000, 0x1A6A0110, 0x0C600112, 0x07600110, ++ 0x333B0000, 0x0BCC0396, 0x398000AF, 0x33635F38, ++ 0x011A4000, 0x0462B140, 0x1F6B5EA0, 0x2E020000, ++ 0x3E3B0004, 0x2D635EA0, 0x1A388000, 0x35605F32, ++ 0x2B008000, 0x0E300003, 0x2B605F4A, 0x2B008000, ++ 0x3F30FFF8, 0x1E384001, 0x2D605F4C, 0x1132FFFF, ++ 0x2E2E0D17, 0x2E23025B, 0x0E8A4000, 0x26605F4E, ++ 0x0A6A010C, 0x202001A0, 0x1A210000, 0x1C0A0000, ++ 0x11970DFB, 0x06970E19, 0x046B5F32, 0x14685F4E, ++ 0x3F37000F, 0x293B0100, 0x2E6A5F34, 0x2563B144, ++ 0x16420000, 0x36695F46, 0x3E2C0002, 0x15410000, ++ 0x266A5F3A, 0x3E2C0002, 0x16420000, 0x23695F3C, ++ 0x016B5F38, 0x3E2C0002, 0x15410000, 0x228B4000, ++ 0x3520C000, 0x35605F32, 0x13970C85, 0x0F220040, ++ 0x1820B424, 0x19500011, 0x01500003, 0x1150C400, ++ 0x0A500001, 0x0E500180, 0x0D500000, 0x1C62B434, ++ 0x352000AF, 0x192100AF, 0x362300AF, 0x17800C8E, ++ 0x28635E9C, 0x1B6B5FEE, 0x0A615E98, 0x192D0036, ++ 0x22484000, 0x312F0001, 0x29635FEE, 0x00349FFF, ++ 0x10404000, 0x19348000, 0x27C80297, 0x222DFFFE, ++ 0x0D4A4000, 0x172D0008, 0x22484000, 0x02625E9A, ++ 0x21510000, 0x30380000, 0x24C802AD, 0x20605E9E, ++ 0x14685E98, 0x33215FDC, 0x02970F61, 0x12970E9D, ++ 0x12685E9E, 0x1A6B5E9C, 0x30380000, 0x16CC02A1, ++ 0x228B4000, 0x306A5E9A, 0x3E215FD8, 0x2636FF00, ++ 0x28D002A8, 0x02970F61, 0x1A6B5E9C, 0x3B8001D1, ++ 0x23320008, 0x392C0035, 0x27460000, 0x3E695E9E, ++ 0x35800285, 0x2B970104, 0x39209000, 0x35605F32, ++ 0x14801034, 0x1C208000, 0x35605F32, 0x05801043, ++ 0x3B635F36, 0x19685F4A, 0x33695F4C, 0x1632FFFE, ++ 0x1A048000, 0x33C402BC, 0x1E2D0001, 0x01615F4C, ++ 0x2B605F4A, 0x26320002, 0x09685F3A, 0x2C8002CA, ++ 0x3B635F36, 0x30380000, 0x28D002C4, 0x33970365, ++ 0x09685F3A, 0x1C390000, 0x26C802CA, 0x09300002, ++ 0x10404000, 0x3930FFFE, 0x2D010000, 0x0F2D01A0, ++ 0x3E610106, 0x1632FFFE, 0x39C80363, 0x28038000, ++ 0x06330001, 0x0BD402D3, 0x172E0004, 0x280C8000, ++ 0x3B605F3A, 0x28038000, 0x3F37000F, 0x35C802DA, ++ 0x2F36FFF0, 0x092E0010, 0x1F6B5F40, 0x19625F3E, ++ 0x1A0B8000, 0x3CC402DF, 0x01625F40, 0x386A5F42, ++ 0x36200000, 0x133600C0, 0x2B320006, 0x37C802E7, ++ 0x232C0040, 0x262EFFFF, 0x308002E3, 0x19600104, ++ 0x1E970CB7, 0x352000AF, 0x0F970CC0, 0x0E970CC7, ++ 0x1D970C74, 0x07690104, 0x2B680104, 0x1F2D0030, ++ 0x0D4A4000, 0x122D0002, 0x214B4000, 0x123EFFFF, ++ 0x1A1EC000, 0x0DCC0333, 0x3421B424, 0x30510041, ++ 0x2360B428, 0x142D0004, 0x21510000, 0x3151C010, ++ 0x26510001, 0x11220038, 0x1C62B434, 0x1F2102EC, ++ 0x362300AF, 0x12940C8E, 0x3320003C, 0x3960B348, ++ 0x0E970C64, 0x1D970C74, 0x20680106, 0x3721B428, ++ 0x2B6A5F3E, 0x156B5FD0, 0x0451E000, 0x26510001, ++ 0x2E60B42C, 0x122D0002, 0x21510000, 0x24200311, ++ 0x2E63B420, 0x2060B424, 0x1C62B434, 0x19685F4A, ++ 0x33695F4C, 0x3660B408, 0x1161B40A, 0x056B5FCC, ++ 0x2F21B40C, 0x0451E000, 0x26510001, 0x17201061, ++ 0x3B63B400, 0x3560B404, 0x0962B414, 0x3A200003, ++ 0x3D605F50, 0x2620032C, 0x1C210336, 0x11970C8E, ++ 0x362300AF, 0x18940C8B, 0x0F685F50, 0x0834FFFE, ++ 0x3D605F50, 0x30380000, 0x37C80331, 0x398000AF, ++ 0x0F685F50, 0x0434FFFD, 0x3D605F50, 0x30380000, ++ 0x02CC00AF, 0x096B5F36, 0x01800CCE, 0x07970C94, ++ 0x25230203, 0x01800CCE, 0x302302EC, 0x01800C94, ++ 0x3B635F36, 0x30380000, 0x35D0033C, 0x33970365, ++ 0x09685F3A, 0x1C390000, 0x2BC80342, 0x09300002, ++ 0x10404000, 0x3930FFFE, 0x2D010000, 0x0F2D01A0, ++ 0x3E610106, 0x1632FFFE, 0x39C80363, 0x1F6B5F40, ++ 0x19625F3E, 0x1A0B8000, 0x20C4034C, 0x01625F40, ++ 0x28038000, 0x0D330003, 0x04D40350, 0x172E0004, ++ 0x280C8000, 0x3B605F3A, 0x0E970C64, 0x19685F4A, ++ 0x33695F4C, 0x3660B408, 0x1161B40A, 0x20680106, ++ 0x2B6A5F3E, 0x2421B40E, 0x21510000, 0x3B60B40C, ++ 0x24200021, 0x3560B404, 0x0962B414, 0x0A685F36, ++ 0x12210352, 0x362300AF, 0x1D800C8B, 0x096B5F36, ++ 0x2380010C, 0x2B635E90, 0x026B5F34, 0x010CC000, ++ 0x084B0000, 0x3E2C0002, 0x0B480000, 0x28635F4A, ++ 0x196B5E90, 0x2D605F4C, 0x228B4000, 0x336A5F40, ++ 0x36200000, 0x2E605F40, 0x1F3A0000, 0x37CC0CA6, ++ 0x228B4000, 0x0A20FFFF, 0x192D0036, 0x0D4A4000, ++ 0x2F2DFFFA, 0x0A625F42, 0x3A34003F, 0x2E148000, ++ 0x11CC0203, 0x228B4000, 0x0D4A4000, 0x122D0002, ++ 0x0F3607FC, 0x26C80205, 0x26320002, 0x19088000, ++ 0x14C00205, 0x2B008000, 0x05300001, 0x11D40389, ++ 0x1D2E0001, 0x3E30FFFF, 0x228B4000, 0x2D635E96, ++ 0x27200102, 0x2297037E, 0x12600130, 0x0C625F44, ++ 0x27200102, 0x2297037E, 0x1F6B5E96, 0x1F600134, ++ 0x07625F46, 0x228B4000, 0x0969010C, 0x2E68010E, ++ 0x3B3D01A0, 0x0CCC03A1, 0x0C2E01A0, 0x3862010C, ++ 0x30380000, 0x3AC803A0, 0x19088000, 0x19C00201, ++ 0x228B4000, 0x28620110, 0x0F630112, 0x398000AF, ++ 0x26680100, 0x2D635E96, 0x366AB140, 0x1D210001, ++ 0x35230000, 0x03280001, 0x300B0000, 0x1A11C000, ++ 0x28038000, 0x2E174000, 0x22C803B2, 0x29310001, ++ 0x03280001, 0x3AC403AC, 0x1F6B5E96, 0x228B4000, ++ 0x2D635E96, 0x19220000, 0x0A625E94, 0x1A6BB140, ++ 0x0A690100, 0x31200001, 0x2D02C000, 0x2B160000, ++ 0x386A5E94, 0x08CC03C0, 0x1D2E0001, 0x0A625E94, ++ 0x3E30FFFF, 0x252DFFFF, 0x1DCC03BA, 0x1F6B5E96, ++ 0x386A5E94, 0x228B4000, 0x09625F4E, 0x352C03C9, ++ 0x21884000, 0x32800211, 0x298003D9, 0x2C800453, ++ 0x26800456, 0x33800476, 0x2E800497, 0x2F8004FC, ++ 0x238004FF, 0x2980051A, 0x2880051D, 0x3B80053B, ++ 0x32800211, 0x32800211, 0x32800211, 0x32800211, ++ 0x32800211, 0x28230018, 0x1263013C, 0x20970375, ++ 0x2197038B, 0x0F6A0130, 0x02030000, 0x1A0B8000, ++ 0x15C003E2, 0x2E020000, 0x206B013C, 0x11685F44, ++ 0x36695F46, 0x25370020, 0x13CC03E8, 0x1D2E0001, ++ 0x12625F3C, 0x2D0E0000, 0x040E4000, 0x1632FFFE, ++ 0x36970396, 0x249702AE, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x32970338, 0x38200008, 0x18210124, ++ 0x356A5F46, 0x32970338, 0x389702B1, 0x09685F3A, ++ 0x09210010, 0x09300002, 0x0F600128, 0x35610104, ++ 0x3697036F, 0x1F970CDC, 0x20680130, 0x01690134, ++ 0x1C6A0120, 0x3D6B0124, 0x3460B010, 0x1561B014, ++ 0x3D680128, 0x1C69012C, 0x172E0068, 0x0862B000, ++ 0x3B2F0068, 0x2963B004, 0x016A0138, 0x382C0068, ++ 0x2960B008, 0x142D0068, 0x0861B00C, 0x1562B018, ++ 0x2368013C, 0x362300AF, 0x1A388000, 0x3760B01C, ++ 0x1E940CE1, 0x14685F4E, 0x2E6A5F34, 0x30380000, ++ 0x34C8041E, 0x21884000, 0x1C208000, 0x13408000, ++ 0x36200000, 0x3580042A, 0x09685F3A, 0x2169B024, ++ 0x012E0028, 0x1C390000, 0x3FD0041A, 0x09300002, ++ 0x382C0068, 0x1F090000, 0x1531FFFE, 0x0E68B028, ++ 0x3F418000, 0x2F34001F, 0x112E0002, 0x13408000, ++ 0x2B008000, 0x3E2C0002, 0x0D500000, 0x0D500000, ++ 0x13970CE9, 0x206A5F3C, 0x01685F34, 0x1632FFFE, ++ 0x33C80213, 0x286B0104, 0x25695F3A, 0x12625F3C, ++ 0x01625F40, 0x010CC000, 0x0F2D01A0, 0x35610104, ++ 0x27490000, 0x3E2C0002, 0x0B480000, 0x07615F4A, ++ 0x2D605F4C, 0x0E970C64, 0x19685F4A, 0x33695F4C, ++ 0x3B60B40C, 0x1C61B40E, 0x2B680104, 0x1A210000, ++ 0x1161B40A, 0x3660B408, 0x206A5F3C, 0x28200081, ++ 0x3560B404, 0x0962B414, 0x14210441, 0x362300AF, ++ 0x18940C8B, 0x36230213, 0x3080036F, 0x2E230028, ++ 0x1263013C, 0x228003DB, 0x20970375, 0x27200102, ++ 0x2297037E, 0x12600130, 0x0C625F44, 0x322C0001, ++ 0x3D605F3C, 0x1D32FFFC, 0x172E0004, 0x36970396, ++ 0x249702AE, 0x36200000, 0x15210120, 0x3E6A5F44, ++ 0x32970338, 0x3E6A5F44, 0x38200008, 0x18210124, ++ 0x32970338, 0x3E6A5F44, 0x25200010, 0x1B210128, ++ 0x32970338, 0x389702B1, 0x09685F3A, 0x07210018, ++ 0x09300002, 0x0260012C, 0x35610104, 0x3023000A, ++ 0x1263013C, 0x368003FC, 0x20970375, 0x2197038B, ++ 0x11685F44, 0x2D0E0000, 0x1632FFFE, 0x36970396, ++ 0x249702AE, 0x36200000, 0x15210120, 0x3E6A5F44, ++ 0x32970338, 0x356A5F46, 0x38200008, 0x18210124, ++ 0x32970338, 0x389702B1, 0x09685F3A, 0x0F6A0130, ++ 0x2E6B0134, 0x09300002, 0x0F600128, 0x2E0EC000, ++ 0x1632FFFE, 0x12625F3C, 0x15208009, 0x32970221, ++ 0x0C970D8F, 0x3E680148, 0x1F970E60, 0x1A210000, ++ 0x236A5F5C, 0x25200010, 0x0E800E7D, 0x06208100, ++ 0x1160013C, 0x20970375, 0x2197038B, 0x236B0130, ++ 0x3D695F44, 0x300B0000, 0x14C00205, 0x0834FFFE, ++ 0x26C80205, 0x040E4000, 0x1632FFFE, 0x36970396, ++ 0x249702AE, 0x36200000, 0x15210120, 0x3E6A5F44, ++ 0x32970338, 0x356A5F46, 0x38200008, 0x18210124, ++ 0x32970338, 0x389702B1, 0x026A0134, 0x12690124, ++ 0x262EFFFF, 0x040D8000, 0x1531FFFE, 0x0F2D01A0, ++ 0x0D4A4000, 0x122D0002, 0x0E494000, 0x2368013C, ++ 0x011A4000, 0x2EC8020B, 0x25695F3A, 0x026A0134, ++ 0x25310002, 0x23610128, 0x29340100, 0x22C804CB, ++ 0x236B0130, 0x2B008000, 0x1A0B8000, 0x312F0001, ++ 0x1D2E0001, 0x05300001, 0x28D004C8, 0x1D2E0001, ++ 0x040D8000, 0x2E61012C, 0x2E0EC000, 0x1632FFFE, ++ 0x12625F3C, 0x2368013C, 0x32970221, 0x0C970D8F, ++ 0x0C69015C, 0x3368014C, 0x05350100, 0x2CC804F5, ++ 0x1F970E60, 0x22520000, 0x172E0004, 0x07690168, ++ 0x3E680148, 0x1C390000, 0x3DD004DE, 0x1F090000, ++ 0x1531FFFE, 0x368004DF, 0x30218000, 0x04685F52, ++ 0x2A2EFFFC, 0x3F418000, 0x15381000, 0x36605F52, ++ 0x12971034, 0x016A0154, 0x2068015C, 0x1A210000, ++ 0x1632FFFE, 0x29340100, 0x25200010, 0x2BC804F4, ++ 0x04970E7E, 0x3E680148, 0x1F69014C, 0x236A5F5C, ++ 0x1F090000, 0x1531FFFE, 0x350A4000, 0x2B200018, ++ 0x0E800E7D, 0x2E6A5F58, 0x012E0028, 0x22520000, ++ 0x22520000, 0x22520000, 0x22520000, 0x388004D7, ++ 0x00208200, 0x1160013C, 0x26800499, 0x21200088, ++ 0x1160013C, 0x20970375, 0x03361F00, 0x23320008, ++ 0x33620138, 0x27200102, 0x2297037E, 0x12600130, ++ 0x2D6B0138, 0x0C625F44, 0x333B0000, 0x206B013C, ++ 0x0CCC050E, 0x2B800511, 0x26370040, 0x10CC0511, ++ 0x322C0001, 0x3D605F3C, 0x2D0E0000, 0x1632FFFE, ++ 0x36970396, 0x36200000, 0x15210120, 0x3E6A5F44, ++ 0x3B2303F7, 0x34800338, 0x2E200048, 0x1160013C, ++ 0x38800501, 0x20970375, 0x27200102, 0x2297037E, ++ 0x12600130, 0x0C625F44, 0x1A32FFFD, 0x36970396, ++ 0x249702AE, 0x36200000, 0x15210120, 0x3E6A5F44, ++ 0x32970338, 0x3E6A5F44, 0x38200008, 0x18210124, ++ 0x32970338, 0x389702B1, 0x39200533, 0x26605F4E, ++ 0x2A230400, 0x1263013C, 0x368003FC, 0x2C69B020, ++ 0x012E0028, 0x22520000, 0x22520000, 0x22520000, ++ 0x3F418000, 0x36230213, 0x15800CE9, 0x20970375, ++ 0x2A2001FF, 0x2297037E, 0x12600130, 0x3D605F3C, ++ 0x2E020000, 0x0C625F44, 0x1632FFFE, 0x36970396, ++ 0x36200000, 0x15210120, 0x3E6A5F44, 0x32970338, ++ 0x36200000, 0x3B605F3A, 0x0F600128, 0x09210010, ++ 0x35610104, 0x18230808, 0x1263013C, 0x368003FC, ++ 0x02030000, 0x0D37FFF8, 0x09CC0211, 0x3F2C0555, ++ 0x21884000, 0x3E80055D, 0x3E8005A4, 0x20800615, ++ 0x32800211, 0x2480062E, 0x3380065F, 0x32800211, ++ 0x32800211, 0x0620FFFC, 0x2C970376, 0x03361F00, ++ 0x2DC80207, 0x23320008, 0x33620138, 0x3F2A0011, ++ 0x2EC40207, 0x2197038B, 0x05300001, 0x39D00569, ++ 0x112E0002, 0x25347FFF, 0x26C80205, 0x2E680138, ++ 0x07625F46, 0x2D010000, 0x24290003, 0x21C40571, ++ 0x3A200003, 0x392C0003, 0x07018000, 0x15072000, ++ 0x333B0000, 0x14CC0209, 0x3D695F44, 0x092E0010, ++ 0x040E4000, 0x082A0800, 0x356A5F46, 0x26C40209, ++ 0x1132FFFF, 0x040E4000, 0x1632FFFE, 0x36970396, ++ 0x249702AE, 0x36200000, 0x15210120, 0x146B5F42, ++ 0x3E6A5F44, 0x06330001, 0x23D00589, 0x2C23058A, ++ 0x34800338, 0x2F9702C0, 0x146B5F42, 0x38200008, ++ 0x18210124, 0x356A5F46, 0x0A330002, 0x32D00592, ++ 0x36230593, 0x34800338, 0x2F9702C0, 0x0A6B5F3A, ++ 0x356A5F46, 0x1B210128, 0x2B635F46, 0x25200010, ++ 0x32970338, 0x389702B1, 0x196B5F46, 0x3D680128, ++ 0x026A0134, 0x0260012C, 0x1632FFFE, 0x38635F3A, ++ 0x12625F3C, 0x1320E000, 0x3E23060E, 0x34800221, ++ 0x0B20FFF8, 0x2C970376, 0x03361F00, 0x2DC80207, ++ 0x23320008, 0x33620138, 0x3F2A0011, 0x2EC40207, ++ 0x24200082, 0x2297037E, 0x12600130, 0x0C625F44, ++ 0x24200082, 0x2297037E, 0x1F600134, 0x05300001, ++ 0x2AD005B6, 0x112E0002, 0x25347FFF, 0x26C80205, ++ 0x2E680138, 0x07625F46, 0x2D010000, 0x24290003, ++ 0x21C405BE, 0x3A200003, 0x332C0006, 0x07018000, ++ 0x15072000, 0x333B0000, 0x14CC0209, 0x3D695F44, ++ 0x2D680134, 0x092E0010, 0x1231FFFF, 0x040E4000, ++ 0x082A0800, 0x26C40209, 0x2E020000, 0x1632FFFE, ++ 0x2D0E0000, 0x040E4000, 0x102E0005, 0x1632FFFE, ++ 0x36970396, 0x249702AE, 0x36200000, 0x15210120, ++ 0x146B5F42, 0x3E6A5F44, 0x06330001, 0x2DD005DB, ++ 0x1132FFFF, 0x242305DE, 0x34800338, 0x2F9702C0, ++ 0x3E6A5F44, 0x329702B4, 0x146B5F42, 0x38200008, ++ 0x18210124, 0x356A5F46, 0x0A330002, 0x28D005E7, ++ 0x1132FFFF, 0x2F2305EA, 0x34800338, 0x2F9702C0, ++ 0x356A5F46, 0x329702B4, 0x12690124, 0x356A5F46, ++ 0x1531FFFE, 0x0F2D01A0, 0x22484000, 0x1632FFFE, ++ 0x040D8000, 0x214B4000, 0x34340001, 0x23C8020F, ++ 0x37370001, 0x23C8020F, 0x026A0134, 0x25200010, ++ 0x146B5F42, 0x1B210128, 0x0D330003, 0x32D005FE, ++ 0x362305FF, 0x34800338, 0x2F9702C0, 0x09685F3A, ++ 0x026A0134, 0x26605F4E, 0x2D200028, 0x1621012C, ++ 0x1132FFFF, 0x32970338, 0x389702B1, 0x14685F4E, ++ 0x026A0134, 0x3B605F3A, 0x39209000, 0x1A32FFFD, ++ 0x12625F3C, 0x32970221, 0x0C970D8F, 0x3368014C, ++ 0x1F970E60, 0x1A210000, 0x236A5F5C, 0x2B200018, ++ 0x0E800E7D, 0x20970375, 0x2197038B, 0x126B5F44, ++ 0x2E0EC000, 0x1632FFFE, 0x36970396, 0x249702AE, ++ 0x36200000, 0x15210120, 0x3E6A5F44, 0x32970338, ++ 0x38200008, 0x18210124, 0x356A5F46, 0x32970338, ++ 0x389702B1, 0x0A6B5F3A, 0x026A0134, 0x0A330002, ++ 0x0163012C, 0x1632FFFE, 0x12625F3C, 0x3620F000, ++ 0x3E23060E, 0x34800221, 0x0C20FFF9, 0x2C970376, ++ 0x0A625F42, 0x122D0002, 0x2B200018, 0x2297037E, ++ 0x1F600134, 0x0834FFFE, 0x26C80205, 0x112E0002, ++ 0x07625F46, 0x2920013C, 0x27508000, 0x0A500001, ++ 0x23290002, 0x22484000, 0x28038000, 0x1A32FFFD, ++ 0x2E0EC000, 0x3F340003, 0x20605F48, 0x1632FFFE, ++ 0x36970396, 0x249702AE, 0x356A5F46, 0x116B5F48, ++ 0x2B008000, 0x1132FFFF, 0x37370001, 0x21C8064D, ++ 0x2D0E0000, 0x15210120, 0x36200000, 0x32970338, ++ 0x116B5F48, 0x356A5F46, 0x37370001, 0x1DCC0686, ++ 0x29230686, 0x09685F3A, 0x2E01C000, 0x232C01A0, ++ 0x0A500001, 0x1632FFFE, 0x202A0002, 0x0D970F97, ++ 0x122801A0, 0x3B605F3A, 0x0D894000, 0x0B20FFF8, ++ 0x2C970376, 0x0A625F42, 0x2B200018, 0x2297037E, ++ 0x12600130, 0x0C625F44, 0x2B200018, 0x2297037E, ++ 0x1F600134, 0x0834FFFE, 0x26C80205, 0x112E0002, ++ 0x07625F46, 0x2920013C, 0x02509000, 0x0A500001, ++ 0x23290002, 0x22484000, 0x3D695F44, 0x38340002, ++ 0x20605F48, 0x1132FFFF, 0x28038000, 0x2E0EC000, ++ 0x2E0EC000, 0x040E4000, 0x1632FFFE, 0x36970396, ++ 0x249702AE, 0x36200000, 0x15210120, 0x146B5F42, ++ 0x3E6A5F44, 0x06330001, 0x26D00685, 0x29230686, ++ 0x34800338, 0x2F9702C0, 0x146B5F42, 0x356A5F46, ++ 0x38200008, 0x0A330002, 0x38D00691, 0x07018000, ++ 0x1132FFFF, 0x040E4000, 0x18210124, 0x3D230697, ++ 0x34800338, 0x18210124, 0x2F9702C0, 0x356A5F46, ++ 0x329702B4, 0x356A5F46, 0x329702B4, 0x146B5F42, ++ 0x356A5F46, 0x1B210128, 0x0D330003, 0x22D006BE, ++ 0x116B5F48, 0x2B008000, 0x1132FFFF, 0x37370001, ++ 0x34C806A2, 0x2D0E0000, 0x25200010, 0x32970338, ++ 0x116B5F48, 0x356A5F46, 0x37370001, 0x0CCC06C7, ++ 0x0F69013C, 0x01685F34, 0x356A5F46, 0x223D9000, ++ 0x1ECC06BC, 0x2E2C0028, 0x084B0000, 0x3E2C0002, ++ 0x27490000, 0x3E2C0002, 0x2D1B4000, 0x27490000, ++ 0x3E2C0002, 0x2D1B4000, 0x27490000, 0x2D200028, ++ 0x2D1B4000, 0x2FC806BC, 0x382306C7, 0x34800338, ++ 0x382306C7, 0x36800655, 0x25200010, 0x2F9702C0, ++ 0x356A5F46, 0x329702B4, 0x116B5F48, 0x356A5F46, ++ 0x37370001, 0x31C806A8, 0x329702B4, 0x389702B1, ++ 0x3D6A5F48, 0x09685F3A, 0x17360002, 0x28C806D1, ++ 0x356A5F46, 0x01690134, 0x1132FFFF, 0x040E4000, ++ 0x1632FFFE, 0x12625F3C, 0x09300002, 0x0260012C, ++ 0x2368013C, 0x32970221, 0x2D695F58, 0x142D0032, ++ 0x22484000, 0x38340002, 0x19CC06E7, 0x016A0154, ++ 0x3A20A000, 0x28038000, 0x06330001, 0x19D406E1, ++ 0x1D2E0001, 0x112E0002, 0x3D33FFFF, 0x2E0EC000, ++ 0x1632FFFE, 0x11625F5C, 0x08970D7B, 0x0C970D8F, ++ 0x3368014C, 0x1F970E60, 0x1A210000, 0x236A5F5C, ++ 0x2B200018, 0x0E800E7D, 0x02030000, 0x0D37FFF8, ++ 0x09CC0211, 0x332C06F3, 0x21884000, 0x388006FE, ++ 0x328007B8, 0x138009BF, 0x01800A98, 0x32800211, ++ 0x328007B8, 0x32800211, 0x01800A98, 0x30380000, ++ 0x09CC0211, 0x05800BD6, 0x0620FFFC, 0x2C970376, ++ 0x122D0002, 0x2B200018, 0x2297037E, 0x12600130, ++ 0x1F600134, 0x0834FFFE, 0x26C80205, 0x112E0002, ++ 0x23290002, 0x22484000, 0x07625F46, 0x34340001, ++ 0x20605F48, 0x2B008000, 0x3530FFFD, 0x2D0E0000, ++ 0x2D0E0000, 0x1632FFFE, 0x36970396, 0x249702AE, ++ 0x36200000, 0x15210120, 0x146B5F42, 0x356A5F46, ++ 0x06330001, 0x3FD0071C, 0x3B23071D, 0x34800338, ++ 0x2F9702C0, 0x1497098E, 0x356A5F46, 0x2D200028, ++ 0x1A210000, 0x32970338, 0x389702B1, 0x1A685F46, ++ 0x36695F46, 0x3530FFFD, 0x2B0C4000, 0x01600120, ++ 0x1531FFFE, 0x20610124, 0x026A0134, 0x3930FFFE, ++ 0x232C01A0, 0x1132FFFF, 0x1A210000, 0x084B0000, ++ 0x3E2C0002, 0x2819C000, 0x262EFFFF, 0x02CC072F, ++ 0x2435FFFE, 0x28C8020D, 0x1F970CDC, 0x01690134, ++ 0x1C6A0120, 0x3D6B0124, 0x03208400, 0x172E0068, ++ 0x3B2F0068, 0x1861B010, 0x0862B000, 0x2963B004, ++ 0x3760B01C, 0x362300AF, 0x1E940CE1, 0x2C69B020, ++ 0x25310002, 0x37D00748, 0x13970CE9, 0x2280020D, ++ 0x13970CE9, 0x1A685F46, 0x19220000, 0x0C600124, ++ 0x2D010000, 0x1531FFFE, 0x2E0D0000, 0x23610128, ++ 0x070D4000, 0x2E0D0000, 0x2E61012C, 0x12625F3C, ++ 0x31200001, 0x1A60013E, 0x39209000, 0x32970221, ++ 0x3A20A000, 0x08970D7B, 0x28680164, 0x116A0148, ++ 0x30380000, 0x1BD00E5E, 0x1F69014C, 0x070E8000, ++ 0x2E610140, 0x23620148, 0x35098000, 0x2D61014C, ++ 0x1531FFFE, 0x23610144, 0x00208200, 0x0E970D7D, ++ 0x2B680168, 0x1C6A014C, 0x30380000, 0x1BD00E5E, ++ 0x12690148, 0x23620148, 0x35098000, 0x2E610140, ++ 0x35098000, 0x1632FFFE, 0x040D8000, 0x2D61014C, ++ 0x3620F000, 0x0E970D7D, 0x3E680148, 0x1C690140, ++ 0x19220000, 0x20620144, 0x0160014C, 0x2E0D0000, ++ 0x2E610140, 0x3230FFFC, 0x0C600148, 0x1B208001, ++ 0x0E970D7D, 0x116A0148, 0x3368014C, 0x2D6B0154, ++ 0x2D620140, 0x2D010000, 0x3530FFFD, 0x0F600144, ++ 0x05300001, 0x1C0A0000, 0x040D8000, 0x20610148, ++ 0x020FC000, 0x12630150, 0x0F208010, 0x0E970D7D, ++ 0x28680164, 0x1C690140, 0x30380000, 0x1BD00E5E, ++ 0x116A0148, 0x3368014C, 0x206B0150, 0x20610148, ++ 0x2D620140, 0x312F0001, 0x12630150, 0x1C0A0000, ++ 0x20620144, 0x1B208001, 0x0E970D7D, 0x0C6A0150, ++ 0x2D6B0154, 0x3368014C, 0x12690148, 0x2E0EC000, ++ 0x3E620150, 0x126A0144, 0x2E610140, 0x1C0A0000, ++ 0x23620148, 0x010F0000, 0x3A33FFFE, 0x3D635F5C, ++ 0x3930FFFE, 0x0F600144, 0x00208200, 0x0E970D7D, ++ 0x0C970D8F, 0x07690168, 0x236A5F5C, 0x1C390000, ++ 0x1BD00E5E, 0x06970E75, 0x2B200018, 0x0E800E7D, ++ 0x0120FFFD, 0x2C970376, 0x122D0002, 0x2B200018, ++ 0x2297037E, 0x12600130, 0x1F600134, 0x0834FFFE, ++ 0x26C80205, 0x112E0002, 0x23290002, 0x22484000, ++ 0x07625F46, 0x38340002, 0x20605F48, 0x2B008000, ++ 0x07018000, 0x3930FFFE, 0x1A32FFFD, 0x2D0E0000, ++ 0x040E4000, 0x1632FFFE, 0x36970396, 0x249702AE, ++ 0x1497098E, 0x356A5F46, 0x2D200028, 0x1A210000, ++ 0x1132FFFF, 0x32970338, 0x36200000, 0x356A5F46, ++ 0x1A210000, 0x1132FFFF, 0x32970338, 0x389702B1, ++ 0x356A5F46, 0x30970655, 0x36695F46, 0x1A685F46, ++ 0x1931FFFD, 0x2D610120, 0x29310001, 0x1F090000, ++ 0x20610124, 0x1F970CDC, 0x01690134, 0x1C6A0120, ++ 0x1861B010, 0x172E0068, 0x0862B000, 0x0662B008, ++ 0x31208808, 0x3760B01C, 0x362300AF, 0x1E940CE1, ++ 0x2169B024, 0x1C390000, 0x1AD0089A, 0x12690124, ++ 0x03208400, 0x142D0068, 0x0661B004, 0x3760B01C, ++ 0x362300AF, 0x1E940CE1, 0x2C69B020, 0x25310002, ++ 0x2BD4089A, 0x36695F46, 0x1C6A0120, 0x31208808, ++ 0x040E4000, 0x2E620120, 0x172E0068, 0x0862B000, ++ 0x0662B008, 0x3760B01C, 0x362300AF, 0x1E940CE1, ++ 0x2169B024, 0x1C390000, 0x1AD0089A, 0x03208400, ++ 0x3760B01C, 0x362300AF, 0x1E940CE1, 0x2C69B020, ++ 0x25310002, 0x2BD4089A, 0x13970CE9, 0x1A685F46, ++ 0x1F690120, 0x0F600128, 0x3930FFFE, 0x2E0D0000, ++ 0x2E61012C, 0x289703B4, 0x11615F3C, 0x3620F000, ++ 0x202A0002, 0x19C4089C, 0x3E695F48, 0x14350002, ++ 0x2BCC089C, 0x32970221, 0x07970967, 0x1E970972, ++ 0x016A0154, 0x3368014C, 0x336B0140, 0x3E620150, ++ 0x12690148, 0x0F630148, 0x300B0000, 0x0C630144, ++ 0x3E30FFFF, 0x1F090000, 0x2E610140, 0x1B208001, ++ 0x0E970D7D, 0x1B970981, 0x3368014C, 0x1F6A0140, ++ 0x12690148, 0x2D6B0154, 0x1C0A0000, 0x2E62014C, ++ 0x3E30FFFF, 0x2E0D0000, 0x2E610140, 0x05300001, ++ 0x2E0D0000, 0x20610148, 0x36200000, 0x0F600144, ++ 0x12630150, 0x39209000, 0x08970D7B, 0x3E680148, ++ 0x1C690140, 0x1C6A014C, 0x1A084000, 0x0160014C, ++ 0x20610148, 0x2D620140, 0x2D010000, 0x3E30FFFF, ++ 0x2E0D0000, 0x3D610150, 0x3F208800, 0x0E970D7D, ++ 0x3368014C, 0x1F6A0140, 0x12690148, 0x2D6B0154, ++ 0x1C0A0000, 0x2E62014C, 0x3E30FFFF, 0x1F090000, ++ 0x2E610140, 0x3930FFFE, 0x1C0A0000, 0x23620148, ++ 0x12630150, 0x39209000, 0x08970D7B, 0x3368014C, ++ 0x12690148, 0x1F6A0140, 0x0C600148, 0x1A084000, ++ 0x28038000, 0x2D0E0000, 0x2E62014C, 0x09300002, ++ 0x010F0000, 0x01630140, 0x1C208000, 0x08970D7B, ++ 0x3A20A000, 0x08970D7B, 0x2E680154, 0x1C6A014C, ++ 0x2D010000, 0x29310001, 0x39D40874, 0x322C0001, ++ 0x3E2C0002, 0x0160014C, 0x2D620140, 0x2D010000, ++ 0x3E30FFFF, 0x2B0C4000, 0x0F600144, 0x2D010000, ++ 0x3E30FFFF, 0x2E0D0000, 0x20610148, 0x00208200, ++ 0x0E970D7D, 0x3E680148, 0x306B014C, 0x016A0154, ++ 0x02600140, 0x2D010000, 0x3930FFFE, 0x38605F5A, ++ 0x1C09C000, 0x23610144, 0x1632FFFE, 0x11625F5C, ++ 0x03208400, 0x0E970D7D, 0x0C970D8F, 0x06970E75, ++ 0x026B5F58, 0x0A6A0160, 0x3D2F0034, 0x0B4BC000, ++ 0x16420000, 0x3D370004, 0x3ECC0D4F, 0x236A5F5C, ++ 0x2B200018, 0x0E800E7D, 0x13970CE9, 0x2480020B, ++ 0x1160013C, 0x3697036F, 0x1F23094A, 0x2B635F46, ++ 0x122008A2, 0x38605F36, 0x3B9703A4, 0x00CC0274, ++ 0x37970247, 0x142308A8, 0x2B635F46, 0x3E800224, ++ 0x3E680148, 0x1C6A014C, 0x1C690140, 0x0160014C, ++ 0x20620144, 0x2D0E0000, 0x3E30FFFF, 0x1F090000, ++ 0x2E610140, 0x23620148, 0x1B208001, 0x0E970D7D, ++ 0x1B970981, 0x12690148, 0x3368014C, 0x1F6A0140, ++ 0x2D6B0154, 0x2E610140, 0x1C0A0000, 0x1C0A0000, ++ 0x2E62014C, 0x3930FFFE, 0x0C600148, 0x36200000, ++ 0x0F600144, 0x12630150, 0x39209000, 0x08970D7B, ++ 0x3368014C, 0x12690148, 0x1F6A0140, 0x0C600148, ++ 0x1A084000, 0x09300002, 0x2D0E0000, 0x2D620140, ++ 0x05300001, 0x0160014C, 0x25200010, 0x28695F52, ++ 0x19220000, 0x2B190000, 0x1A615F52, 0x26695F6C, ++ 0x1F238000, 0x38635F56, 0x22484000, 0x026B5F34, ++ 0x122D0002, 0x3F424000, 0x351F0000, 0x1DC80D58, ++ 0x16235F7A, 0x2449C000, 0x3D2F0002, 0x1A1D0000, ++ 0x36CC08E8, 0x2449C000, 0x1C390000, 0x2CCC0D58, ++ 0x25695F56, 0x1C390000, 0x3CD408EB, 0x14625F56, ++ 0x302F0006, 0x1D2E0001, 0x018008DD, 0x04685F52, ++ 0x076B5F52, 0x3C34000F, 0x393700F0, 0x27CC08F3, ++ 0x1C1C8000, 0x21CC08F5, 0x118008F7, 0x1C1C8000, ++ 0x2ACC08F7, 0x1D32FFFC, 0x1E8008F8, 0x1E31FFFC, ++ 0x01198000, 0x17615F56, 0x076B5F52, 0x23310004, ++ 0x1035000F, 0x3F37000F, 0x1C1F4000, 0x0DC8090D, ++ 0x28004000, 0x07645F52, 0x1331FFF8, 0x32394001, ++ 0x12615F6A, 0x2D010000, 0x22310003, 0x19615F68, ++ 0x3E30FFFF, 0x012C0D17, 0x0F23090C, 0x21884000, ++ 0x38605F6C, 0x116A0148, 0x1F69014C, 0x30680140, ++ 0x040D8000, 0x1531FFFE, 0x17615F60, 0x3D6B0148, ++ 0x1C0A0000, 0x2B0F8000, 0x0263014C, 0x3930FFFE, ++ 0x30605F62, 0x1632FFFE, 0x12625F66, 0x15970C7A, ++ 0x34200051, 0x2360B444, 0x09685F56, 0x0A6B5F60, ++ 0x3C34000F, 0x0E300003, 0x2D010000, 0x0934FF00, ++ 0x010CC000, 0x2060B448, 0x193500FF, 0x0761B44A, ++ 0x07685F68, 0x016B5F62, 0x206A5F66, 0x2D010000, ++ 0x0934FF00, 0x010CC000, 0x2D60B44C, 0x193500FF, ++ 0x0A61B44E, 0x1F62B454, 0x0F200936, 0x3221091B, ++ 0x362300AF, 0x0B800C91, 0x1D210001, 0x3561015E, ++ 0x1C208000, 0x1260015C, 0x00970E1F, 0x076B5F52, ++ 0x0A685F6C, 0x3F37000F, 0x293B0100, 0x2563B144, ++ 0x3921086C, 0x3E2C0002, 0x15410000, 0x09685F56, ++ 0x18230D58, 0x3C34000F, 0x07645F52, 0x0E300003, ++ 0x35605F68, 0x0A800D8F, 0x07970967, 0x1E970972, ++ 0x3368014C, 0x1F6A0140, 0x12690148, 0x2D6B0154, ++ 0x1C0A0000, 0x2E62014C, 0x1F6A0140, 0x12630150, ++ 0x2E610140, 0x3930FFFE, 0x1C0A0000, 0x23620148, ++ 0x36200000, 0x0F600144, 0x39209000, 0x08970D7B, ++ 0x1C690140, 0x3E680148, 0x116A0148, 0x2E610140, ++ 0x1A084000, 0x0160014C, 0x3E30FFFF, 0x2D0E0000, ++ 0x23620148, 0x36200000, 0x198008CF, 0x3E680148, ++ 0x1C6A014C, 0x1C690140, 0x0160014C, 0x20620144, ++ 0x1F090000, 0x2D0E0000, 0x2E610140, 0x23620148, ++ 0x1B208001, 0x08800D7D, 0x3368014C, 0x12690148, ++ 0x1F6A0140, 0x2E610140, 0x2D0E0000, 0x23620148, ++ 0x2E020000, 0x1632FFFE, 0x1C0A0000, 0x2E680154, ++ 0x20620144, 0x020C0000, 0x11600150, 0x00208200, ++ 0x08800D7D, 0x1F6A0140, 0x12690148, 0x3368014C, ++ 0x23620148, 0x2E610140, 0x3930FFFE, 0x1C0A0000, ++ 0x2E680154, 0x20620144, 0x020C0000, 0x11600150, ++ 0x00208200, 0x08800D7D, 0x25635F4E, 0x146B5F42, ++ 0x356A5F46, 0x38200008, 0x1A210000, 0x0A330002, ++ 0x07D0099B, 0x28038000, 0x1632FFFE, 0x3D33FFFF, ++ 0x2E0EC000, 0x062309A6, 0x34800338, 0x2F9702C0, ++ 0x356A5F46, 0x329702B4, 0x356A5F46, 0x329702B4, ++ 0x356A5F46, 0x329702B4, 0x356A5F46, 0x329702B4, ++ 0x356A5F46, 0x329702B4, 0x3E695F48, 0x356A5F46, ++ 0x18350001, 0x1FC809B9, 0x2D200028, 0x33970365, ++ 0x19685F4A, 0x33695F4C, 0x1632FFFE, 0x1A048000, ++ 0x19C409B3, 0x1E2D0001, 0x01615F4C, 0x2B605F4A, ++ 0x0A20FFFF, 0x1A210000, 0x356A5F46, 0x162309BA, ++ 0x34800338, 0x30970655, 0x356A5F46, 0x25200010, ++ 0x1A210000, 0x176B5F4E, 0x34800338, 0x0620FFFC, ++ 0x2C970376, 0x03361F00, 0x2DC80207, 0x23320008, ++ 0x33620138, 0x3F2A0011, 0x2EC40207, 0x2197038B, ++ 0x236B0130, 0x2D010000, 0x2435FFFE, 0x26C80205, ++ 0x3008C000, 0x3BC009CF, 0x17CC0205, 0x126B5F44, ++ 0x112E0002, 0x07625F46, 0x3D2F0002, 0x20635F44, ++ 0x3D33FFFF, 0x1632FFFE, 0x2E0EC000, 0x1632FFFE, ++ 0x36970396, 0x2E680138, 0x3D695F44, 0x02030000, ++ 0x0B2B0003, 0x19C409DF, 0x3A200003, 0x392C0003, ++ 0x15072000, 0x333B0000, 0x14CC0209, 0x36695F46, ++ 0x092E0010, 0x2B034000, 0x1931FFFD, 0x1C09C000, ++ 0x040E4000, 0x082A0800, 0x26C40209, 0x249702AE, ++ 0x36200000, 0x15210120, 0x146B5F42, 0x356A5F46, ++ 0x06330001, 0x0BD009F4, 0x0F2309F5, 0x34800338, ++ 0x2F9702C0, 0x0C970BB5, 0x356A5F46, 0x2D200028, ++ 0x1A210000, 0x32970338, 0x389702B1, 0x3D695F44, ++ 0x1A685F46, 0x1231FFFF, 0x2E0D0000, 0x20610124, ++ 0x3E30FFFF, 0x2E0D0000, 0x2D610120, 0x1F970CDC, ++ 0x01690134, 0x1C6A0120, 0x1861B010, 0x172E0068, ++ 0x0862B000, 0x0662B008, 0x31208808, 0x3760B01C, ++ 0x362300AF, 0x1E940CE1, 0x2169B024, 0x1C390000, ++ 0x18D00A1B, 0x12690124, 0x03208400, 0x142D0068, ++ 0x0661B004, 0x3760B01C, 0x362300AF, 0x1E940CE1, ++ 0x2C69B020, 0x25310002, 0x1ED00A1D, 0x13970CE9, ++ 0x2280020D, 0x13970CE9, 0x1A685F46, 0x3D695F44, ++ 0x1C6A0120, 0x0C600124, 0x2E0D0000, 0x23610128, ++ 0x0C690130, 0x2E6B0134, 0x3930FFFE, 0x2D0E0000, ++ 0x2D62012C, 0x11630130, 0x33610134, 0x19220000, ++ 0x12625F3C, 0x1320E000, 0x32970221, 0x28680164, ++ 0x0F690150, 0x30380000, 0x1BD00E5E, 0x2D6B0154, ++ 0x126A0144, 0x3368014C, 0x30610154, 0x312F0001, ++ 0x12630150, 0x1C690140, 0x2E62014C, 0x02600140, ++ 0x28004000, 0x040D8000, 0x20610148, 0x1132FFFF, ++ 0x19088000, 0x0F600144, 0x00208200, 0x0E970D7D, ++ 0x2B680168, 0x2D6B0154, 0x30380000, 0x1BD00E5E, ++ 0x1C6A014C, 0x12690148, 0x12630150, 0x23620148, ++ 0x35098000, 0x2E610140, 0x040D8000, 0x1132FFFF, ++ 0x040D8000, 0x2D61014C, 0x3620F000, 0x0E970D7D, ++ 0x3E680148, 0x1F69014C, 0x1F6A0140, 0x35230000, ++ 0x0C630144, 0x0160014C, 0x2E0D0000, 0x20610148, ++ 0x2D0E0000, 0x2D620140, 0x1B208001, 0x0E970D7D, ++ 0x116A0148, 0x3368014C, 0x1C690140, 0x2D6B0154, ++ 0x2D620140, 0x2D0E0000, 0x3E30FFFF, 0x2D0E0000, ++ 0x23620148, 0x1F090000, 0x23610144, 0x3D33FFFF, ++ 0x12630150, 0x0F208010, 0x0E970D7D, 0x04690164, ++ 0x3368014C, 0x1C390000, 0x1BD00E5E, 0x1C690140, ++ 0x116A0148, 0x206B0150, 0x20610148, 0x2D620140, ++ 0x312F0001, 0x12630150, 0x1F090000, 0x23610144, ++ 0x1B208001, 0x0E970D7D, 0x0C6A0150, 0x2D6B0154, ++ 0x3368014C, 0x12690148, 0x2E0EC000, 0x3E620150, ++ 0x010F0000, 0x3A33FFFE, 0x3D635F5C, 0x3E6B0144, ++ 0x2E610140, 0x300B0000, 0x0F630148, 0x3930FFFE, ++ 0x300B0000, 0x0C630144, 0x00208200, 0x0E970D7D, ++ 0x0C970D8F, 0x07690168, 0x236A5F5C, 0x1C390000, ++ 0x1BD00E5E, 0x06970E75, 0x2B200018, 0x0E800E7D, ++ 0x0120FFFD, 0x2C970376, 0x03361F00, 0x2DC80207, ++ 0x23320008, 0x33620138, 0x3F2A0011, 0x2EC40207, ++ 0x2197038B, 0x236B0130, 0x2D010000, 0x2435FFFE, ++ 0x26C80205, 0x3008C000, 0x3FC00AA8, 0x17CC0205, ++ 0x126B5F44, 0x112E0002, 0x07625F46, 0x3D2F0002, ++ 0x20635F44, 0x0200C000, 0x3D33FFFF, 0x010F0000, ++ 0x1632FFFE, 0x2E0EC000, 0x1632FFFE, 0x36970396, ++ 0x2E680138, 0x3D695F44, 0x02030000, 0x0B2B0003, ++ 0x16C40ABA, 0x3A200003, 0x3F2C0005, 0x15072000, ++ 0x333B0000, 0x14CC0209, 0x36695F46, 0x092E0010, ++ 0x1531FFFE, 0x040E4000, 0x082A0800, 0x26C40209, ++ 0x249702AE, 0x36200000, 0x1A210000, 0x3E6A5F44, ++ 0x32970338, 0x0C970BB5, 0x356A5F46, 0x2D200028, ++ 0x1A210000, 0x1132FFFF, 0x32970338, 0x389702B1, ++ 0x11685F44, 0x36695F46, 0x2E020000, 0x2B034000, ++ 0x3E30FFFF, 0x1231FFFF, 0x280C8000, 0x0C600124, ++ 0x2B0C4000, 0x0F600128, 0x010CC000, 0x01600120, ++ 0x1F970CDC, 0x01690134, 0x126A0128, 0x3E610130, ++ 0x1861B010, 0x172E0068, 0x0862B000, 0x0662B008, ++ 0x31208808, 0x3760B01C, 0x362300AF, 0x1E940CE1, ++ 0x2169B024, 0x1C390000, 0x26D40AED, 0x13970CE9, ++ 0x2480020B, 0x12690124, 0x03208400, 0x142D0068, ++ 0x0661B004, 0x3760B01C, 0x362300AF, 0x1E940CE1, ++ 0x2C69B020, 0x25310002, 0x20D40AEB, 0x1C6A0120, ++ 0x31208808, 0x172E0068, 0x0862B000, 0x0662B008, ++ 0x3760B01C, 0x362300AF, 0x1E940CE1, 0x2169B024, ++ 0x1C390000, 0x11D00AEB, 0x03208400, 0x3760B01C, ++ 0x362300AF, 0x1E940CE1, 0x2C69B020, 0x25310002, ++ 0x20D40AEB, 0x13970CE9, 0x1A685F46, 0x1F690120, ++ 0x0F600128, 0x2E0D0000, 0x2E61012C, 0x19220000, ++ 0x12625F3C, 0x3620F000, 0x32970221, 0x3E680148, ++ 0x1C6A014C, 0x1C690140, 0x0160014C, 0x20620144, ++ 0x1F090000, 0x2E610140, 0x2D0E0000, 0x23620148, ++ 0x1B208001, 0x0E970D7D, 0x3368014C, 0x12690148, ++ 0x1F6A0140, 0x2E610140, 0x07018000, 0x2E0D0000, ++ 0x20610148, 0x3E30FFFF, 0x1C0A0000, 0x2E680154, ++ 0x20620144, 0x020C0000, 0x11600150, 0x00208200, ++ 0x0E970D7D, 0x016A0154, 0x3368014C, 0x336B0140, ++ 0x3E620150, 0x12690148, 0x0F630148, 0x300B0000, ++ 0x0C630144, 0x3E30FFFF, 0x1F090000, 0x2E610140, ++ 0x1B208001, 0x0E970D7D, 0x3368014C, 0x1F6A0140, ++ 0x12690148, 0x23620148, 0x1C0A0000, 0x2E680154, ++ 0x20620144, 0x2E610140, 0x020C0000, 0x11600150, ++ 0x00208200, 0x0E970D7D, 0x3368014C, 0x2D6B0154, ++ 0x12690148, 0x1F6A0140, 0x12630150, 0x2E610140, ++ 0x2D695F58, 0x1C0A0000, 0x2E62014C, 0x1F2D0030, ++ 0x0D4A4000, 0x1F2D0006, 0x0E494000, 0x0F3607FC, ++ 0x26320002, 0x33620154, 0x28038000, 0x06330001, ++ 0x22D40B5A, 0x1D2E0001, 0x112E0002, 0x20620144, ++ 0x1132FFFF, 0x23620148, 0x00351F00, 0x20310008, ++ 0x33610158, 0x1320E000, 0x0E970D7D, 0x3D680144, ++ 0x1C6A014C, 0x1C690140, 0x206B0150, 0x2D0E0000, ++ 0x2E62014C, 0x0200C000, 0x06330001, 0x25D40B6D, ++ 0x322C0001, 0x3E2C0002, 0x3E30FFFF, 0x2E0D0000, ++ 0x2E610140, 0x1A210000, 0x20610148, 0x1320E000, ++ 0x0E970D7D, 0x206B0150, 0x2E680154, 0x1C6A014C, ++ 0x0263014C, 0x11600150, 0x1C600154, 0x02030000, ++ 0x06330001, 0x3DD40B7F, 0x322C0001, 0x3E2C0002, ++ 0x20620144, 0x1C0A0000, 0x2D620140, 0x3E30FFFF, ++ 0x2D0E0000, 0x23620148, 0x1B208001, 0x0E970D7D, ++ 0x12690148, 0x126A0144, 0x206B0150, 0x2E610140, ++ 0x23620148, 0x0200C000, 0x3D33FFFF, 0x12630150, ++ 0x1C600154, 0x02030000, 0x06330001, 0x22D40B95, ++ 0x322C0001, 0x3E2C0002, 0x0F600144, 0x00208200, ++ 0x0E970D7D, 0x11690144, 0x116A0148, 0x3368014C, ++ 0x2D6B0154, 0x2D620140, 0x12630150, 0x1C600154, ++ 0x02030000, 0x06330001, 0x23D40BA4, 0x322C0001, ++ 0x3E2C0002, 0x0160014C, 0x350A4000, 0x23620148, ++ 0x3930FFFE, 0x1C0A0000, 0x20620144, 0x00208200, ++ 0x0E970D7D, 0x12690148, 0x016A0154, 0x306B014C, ++ 0x2E610140, 0x3E620150, 0x3D33FFFF, 0x1C09C000, ++ 0x09800889, 0x25635F4E, 0x146B5F42, 0x38200008, ++ 0x1A210000, 0x3E6A5F44, 0x0A330002, 0x1BD00BC1, ++ 0x196B5F46, 0x1132FFFF, 0x2E0EC000, 0x0B230BD1, ++ 0x34800338, 0x2F9702C0, 0x3E6A5F44, 0x329702B4, ++ 0x3E6A5F44, 0x19685F4A, 0x33695F4C, 0x1632FFFE, ++ 0x1A048000, 0x1AC40BCC, 0x1E2D0001, 0x01615F4C, ++ 0x2B605F4A, 0x356A5F46, 0x0A20FFFF, 0x1A210000, ++ 0x2F9702C0, 0x356A5F46, 0x25200010, 0x1A210000, ++ 0x176B5F4E, 0x34800338, 0x32800211, 0x02030000, ++ 0x0C37FFFF, 0x09CC0211, 0x0F2C0BDC, 0x21884000, ++ 0x07800BDD, 0x20970375, 0x3E20000E, 0x2297037E, ++ 0x093C000E, 0x17CC0205, 0x2A2001FF, 0x2297037E, ++ 0x3D605F3C, 0x3F340003, 0x17CC0205, 0x122E000E, ++ 0x1632FFFE, 0x36970396, 0x249702AE, 0x1122000E, ++ 0x36200000, 0x1A210000, 0x32970338, 0x01685F34, ++ 0x122101D8, 0x3E610106, 0x3B2C0008, 0x27490000, ++ 0x3E2C0002, 0x0B480000, 0x07615F4A, 0x2D605F4C, ++ 0x0F685F3C, 0x30695F40, 0x3930FFFE, 0x36605F3E, ++ 0x1F090000, 0x10C40BFF, 0x2E605F40, 0x202001A0, ++ 0x04230C04, 0x19600104, 0x3B635F36, 0x328002E8, ++ 0x25200010, 0x19600104, 0x24800431, 0x369700FC, ++ 0x15220003, 0x1F62B438, 0x2C695FCA, 0x04685EDE, ++ 0x19220000, 0x1461B400, 0x1162B406, 0x30380000, ++ 0x36C800A5, 0x2A340080, 0x19C80C16, 0x1E200C27, ++ 0x1B230C17, 0x288000B4, 0x36605EDE, 0x09685EEC, ++ 0x332300A5, 0x19220000, 0x14625EEC, 0x28695EDE, ++ 0x366A5EF0, 0x30380000, 0x27C80104, 0x01198000, ++ 0x2E6A5F02, 0x01198000, 0x336A5EA0, 0x24D000B4, ++ 0x3C36FDFF, 0x01625EA0, 0x288000B4, 0x22215EDE, ++ 0x1F220006, 0x14970FB4, 0x2F215EEC, 0x21510000, ++ 0x21510000, 0x21884000, 0x1F220030, 0x1F62B438, ++ 0x21695FCE, 0x19685EF0, 0x19220000, 0x0161B420, ++ 0x0462B426, 0x30380000, 0x3AC800A6, 0x2A340080, ++ 0x09C80C3C, 0x17200C42, 0x0B230C3D, 0x288000B4, ++ 0x2B605EF0, 0x11685EFE, 0x3F2300A6, 0x19220000, ++ 0x0C625EFE, 0x17800C1B, 0x3F215EF0, 0x1F220006, ++ 0x14970FB4, 0x37215EFE, 0x21510000, 0x21510000, ++ 0x21884000, 0x1F220300, 0x1F62B438, 0x21695FCE, ++ 0x01685F02, 0x19220000, 0x0261B440, 0x0762B446, ++ 0x30380000, 0x3DC800A7, 0x2A340080, 0x08C80C57, ++ 0x0B200C5D, 0x02230C58, 0x288000B4, 0x33605F02, ++ 0x19685F10, 0x382300A7, 0x19220000, 0x04625F10, ++ 0x17800C1B, 0x27215F02, 0x1F220006, 0x14970FB4, ++ 0x3F215F10, 0x21510000, 0x21510000, 0x21884000, ++ 0x04685EDE, 0x22215EDE, 0x30380000, 0x1AD00C70, ++ 0x03205EEC, 0x0B518000, 0x0D500000, 0x30695EA0, ++ 0x0D500000, 0x00390200, 0x02615EA0, 0x228B4000, ++ 0x0200C000, 0x1F220006, 0x362300AF, 0x1D800FD7, ++ 0x19685EF0, 0x3F215EF0, 0x30380000, 0x1AD00C70, ++ 0x1B205EFE, 0x0C800C69, 0x01685F02, 0x27215F02, ++ 0x30380000, 0x1AD00C70, 0x13205F10, 0x0C800C69, ++ 0x04685EDE, 0x22215EDE, 0x30380000, 0x36D40C68, ++ 0x398000AF, 0x19685EF0, 0x3F215EF0, 0x30380000, ++ 0x35D000AF, 0x1B205EFE, 0x0C800C69, 0x3B605EEC, ++ 0x1C615EEE, 0x228B4000, 0x23605EFE, 0x14615F00, ++ 0x228B4000, 0x2B605F10, 0x0C615F12, 0x228B4000, ++ 0x19685EF0, 0x1A210000, 0x30380000, 0x0AC80CA5, ++ 0x1F61B434, 0x226A5FCE, 0x0761B426, 0x0262B420, ++ 0x2A340080, 0x0DC80CA4, 0x28635E9C, 0x3F215EF0, ++ 0x1F220006, 0x14970FB4, 0x1A6B5E9C, 0x288000B4, ++ 0x07615EF0, 0x228B4000, 0x2E620116, 0x0F200CA9, ++ 0x288000B4, 0x19970C80, 0x1C6A0116, 0x0D20B404, ++ 0x19500011, 0x01500003, 0x1150C400, 0x0A500001, ++ 0x0E500180, 0x0D500000, 0x0962B414, 0x352000AF, ++ 0x192100AF, 0x362300AF, 0x1D800C8B, 0x01690102, ++ 0x36200000, 0x0A350020, 0x20C80203, 0x30218000, ++ 0x1F615ED4, 0x3B605EDA, 0x3D605EDC, 0x228B4000, ++ 0x2D695ED4, 0x30380000, 0x27C80104, 0x1C390000, ++ 0x1DD40100, 0x3B605EDA, 0x228B4000, 0x2D695ED4, ++ 0x30380000, 0x27C80104, 0x1C390000, 0x1DD40100, ++ 0x3D605EDC, 0x228B4000, 0x01685ED4, 0x27215ED4, ++ 0x30380000, 0x16D40102, 0x21510000, 0x228B4000, ++ 0x30695ECC, 0x07685ED2, 0x1C390000, 0x06D400A4, ++ 0x30380000, 0x31C800A4, 0x342300A4, 0x288000B4, ++ 0x3A215ECC, 0x0B518000, 0x36200000, 0x35605ED2, ++ 0x228B4000, 0x30695ECC, 0x35605ED2, 0x1C390000, ++ 0x30695EA0, 0x1DD40100, 0x12390008, 0x02615EA0, ++ 0x228B4000, 0x336A5EA0, 0x1C685ECC, 0x3A215ECC, ++ 0x2E36FFF7, 0x01625EA0, 0x30380000, 0x16D40102, ++ 0x21510000, 0x228B4000, 0x04685F52, 0x30218000, ++ 0x2D144000, 0x04CC00A9, 0x1A615F52, 0x302300A9, ++ 0x06200CFA, 0x288000B4, 0x29200400, 0x2660B144, ++ 0x06210200, 0x1468B144, 0x3C34000F, 0x2B190000, ++ 0x0A61B144, 0x07645F52, 0x2D010000, 0x20310008, ++ 0x1139A0C8, 0x214B4000, 0x0F2D002C, 0x0E494000, ++ 0x2E020000, 0x06330001, 0x20377F00, 0x1263010A, ++ 0x21320003, 0x1A625F68, 0x2E020000, 0x1032FFF8, ++ 0x313A4001, 0x11625F6A, 0x2E020000, 0x1132FFFF, ++ 0x2E2E0D17, 0x04230D2B, 0x0E8A4000, 0x15205F7A, ++ 0x228B4000, 0x12205F82, 0x228B4000, 0x1C205F8A, ++ 0x228B4000, 0x01205F92, 0x228B4000, 0x0F205F9A, ++ 0x228B4000, 0x07205FA2, 0x228B4000, 0x09205FAA, ++ 0x228B4000, 0x14205FB2, 0x228B4000, 0x1A205FBA, ++ 0x228B4000, 0x04205FC2, 0x228B4000, 0x38605F6C, ++ 0x27490000, 0x3E2C0002, 0x084B0000, 0x3E2C0002, ++ 0x244A0000, 0x3E2C0002, 0x0B480000, 0x1F615F58, ++ 0x38635F56, 0x17625F5A, 0x3E605F5C, 0x1E970E3D, ++ 0x236A5F5C, 0x266B010C, 0x1F3A0000, 0x01C80D47, ++ 0x19213000, 0x35098000, 0x190B4000, 0x3061010E, ++ 0x39C00D42, 0x27CC0E5C, 0x0A685F5A, 0x04230D47, ++ 0x33635F54, 0x046B5F68, 0x07800E42, 0x0F69010A, ++ 0x0A6B5F56, 0x20310008, 0x08C80D78, 0x2E6A5F58, ++ 0x05390080, 0x162E0035, 0x0E458000, 0x0C970D8F, ++ 0x04685F52, 0x1B230D54, 0x16341000, 0x3ECC1043, ++ 0x3A2000A0, 0x00645F53, 0x2D695F58, 0x34970284, ++ 0x0269010E, 0x1A223000, 0x350A4000, 0x0BC80D74, ++ 0x28680108, 0x25620114, 0x30380000, 0x12C80D61, ++ 0x0A970CA6, 0x15970C7A, 0x0269010E, 0x1B20B444, ++ 0x19500011, 0x0A500001, 0x1150C400, 0x0A500001, ++ 0x2335FFFF, 0x15410000, 0x176A0114, 0x3E2C0002, ++ 0x0D500000, 0x1F62B454, 0x0B200D72, 0x27210D72, ++ 0x362300AF, 0x0B800C91, 0x35203000, 0x1C60010E, ++ 0x1A210000, 0x36610108, 0x1A615F52, 0x398000AF, ++ 0x19220000, 0x3662015E, 0x228B4000, 0x1D210001, ++ 0x3561015E, 0x1260015C, 0x38635F56, 0x00970E1F, ++ 0x076B5F52, 0x0A685F6C, 0x3F37000F, 0x293B0100, ++ 0x2563B144, 0x25695F56, 0x3E2C0002, 0x15410000, ++ 0x26695F5A, 0x3E2C0002, 0x15410000, 0x20695F5C, ++ 0x3E2C0002, 0x15410000, 0x17800D58, 0x04685F52, ++ 0x3569B140, 0x3930FFFE, 0x3CD003A0, 0x33635F54, ++ 0x09300002, 0x02030000, 0x3C34000F, 0x3D3CFFFF, ++ 0x33228000, 0x1A120000, 0x301D8000, 0x0761B140, ++ 0x336A5EA0, 0x2BCC0DA0, 0x2D36FFFB, 0x01625EA0, ++ 0x3D3CFFFF, 0x3A225F7A, 0x3530FFFD, 0x1F060000, ++ 0x22520000, 0x22520000, 0x153B2000, 0x07685F32, ++ 0x35635F52, 0x1A344000, 0x09C80DB0, 0x0A685F36, ++ 0x2E9700B4, 0x02685F54, 0x362300AF, 0x288000B4, ++ 0x04685F52, 0x3569B140, 0x1F238000, 0x3C34000F, ++ 0x2E020000, 0x123EFFFF, 0x1C138000, 0x2819C000, ++ 0x0761B140, 0x3F30FFF8, 0x2838A084, 0x18500020, ++ 0x3B680118, 0x2E695F54, 0x0418C000, 0x09600118, ++ 0x351CC000, 0x2BCC0DFA, 0x2361011E, 0x07685F68, ++ 0x0763011C, 0x0260011A, 0x15970C7A, 0x336B011A, ++ 0x1B20B444, 0x1C500041, 0x0A500001, 0x0E500180, ++ 0x0D500000, 0x2D02C000, 0x2636FF00, 0x0262B44C, ++ 0x363700FF, 0x2563B44E, 0x3F222000, 0x1F62B454, ++ 0x3E6B011E, 0x36200000, 0x0F60011E, 0x333B0000, ++ 0x3ECC0DDA, 0x362300AF, 0x08200DDD, 0x24210DDD, ++ 0x0B800C91, 0x3668011C, 0x3569B140, 0x146A0118, ++ 0x1A1D0000, 0x0761B140, 0x191E0000, 0x26620118, ++ 0x19C80DF6, 0x36200000, 0x1D210001, 0x28038000, ++ 0x2E174000, 0x39CC0DED, 0x322C0001, 0x1231FFFF, ++ 0x07800DE7, 0x2861011C, 0x0E300003, 0x2B695F32, ++ 0x0260011A, 0x36354000, 0x1FC80DC6, 0x19200DC6, ++ 0x096B5F36, 0x288000B4, 0x07685F32, 0x26695F36, ++ 0x1A344000, 0x33C800AF, 0x0D894000, 0x1F3A0000, ++ 0x3AC803A0, 0x3B635F36, 0x1A6B5F4A, 0x19600104, ++ 0x3E610106, 0x19625F3E, 0x23635F48, 0x1D970C74, ++ 0x2B680104, 0x0F6A0106, 0x116B5F48, 0x2360B428, ++ 0x3C21B42A, 0x21510000, 0x0200C000, 0x0934FF00, ++ 0x281A0000, 0x0162B42C, 0x363700FF, 0x2663B42E, ++ 0x2B6A5F3E, 0x27200041, 0x2060B424, 0x1C62B434, ++ 0x36210E03, 0x362300AF, 0x12940C8E, 0x096B5F36, ++ 0x228B4000, 0x3B635F36, 0x39200120, 0x1A210000, ++ 0x0C220020, 0x1C6B5F4C, 0x1A800DFF, 0x33635F54, ++ 0x0F6B5F6A, 0x3A200140, 0x1A210000, 0x0C220020, ++ 0x3B605F60, 0x1C615F62, 0x12625F66, 0x36635F5E, ++ 0x15970C7A, 0x09685F60, 0x2D6A5F62, 0x046B5F5E, ++ 0x2060B448, 0x3F21B44A, 0x21510000, 0x0200C000, ++ 0x0934FF00, 0x281A0000, 0x0262B44C, 0x363700FF, ++ 0x2563B44E, 0x206A5F66, 0x27200041, 0x2360B444, ++ 0x1F62B454, 0x16200E5A, 0x21210E28, 0x362300AF, ++ 0x0B800C91, 0x33635F54, 0x36200000, 0x16210140, ++ 0x0F22002C, 0x0F6B5F6A, 0x3B605F60, 0x1C615F62, ++ 0x12625F66, 0x36635F5E, 0x15970C7A, 0x286A5F5E, ++ 0x09685F60, 0x2E695F62, 0x28038000, 0x0A37FF00, ++ 0x0418C000, 0x2060B448, 0x1A3600FF, 0x0462B44A, ++ 0x0161B44C, 0x36200000, 0x2660B44E, 0x206A5F66, ++ 0x22200011, 0x2360B444, 0x1F62B454, 0x2A210E46, ++ 0x362300AF, 0x0E940C91, 0x016B5F54, 0x228B4000, ++ 0x0B210041, 0x08800D4B, 0x08210021, 0x08800D4B, ++ 0x2E6A5F58, 0x04690164, 0x012E0028, 0x1C390000, ++ 0x01D00E71, 0x1F090000, 0x1531FFFE, 0x2B680168, ++ 0x3F418000, 0x2F34001F, 0x112E0002, 0x13408000, ++ 0x2B008000, 0x3E2C0002, 0x0D500000, 0x0D500000, ++ 0x228B4000, 0x1C208000, 0x13408000, 0x36200000, ++ 0x1C800E6A, 0x01685F58, 0x1A210000, 0x2E2C0028, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x15410000, ++ 0x228B4000, 0x0A230D4F, 0x0F3607FC, 0x3AC803A0, ++ 0x33635F54, 0x026B5F58, 0x12625F66, 0x010CC000, ++ 0x084B0000, 0x3E2C0002, 0x0B480000, 0x33635F62, ++ 0x2D6B010E, 0x36605F64, 0x2D0DC000, 0x36610108, ++ 0x0E970C64, 0x02685F62, 0x28695F64, 0x3B60B40C, ++ 0x1C61B40E, 0x28680108, 0x206A5F66, 0x2921B40A, ++ 0x3660B408, 0x21510000, 0x28200081, 0x3560B404, ++ 0x0962B414, 0x02685F54, 0x20210E8C, 0x362300AF, ++ 0x1D800C8B, 0x2D695F6E, 0x1C208000, 0x28150000, ++ 0x17C80EA2, 0x228B4000, 0x336A5EA0, 0x33605F6E, ++ 0x14200EA8, 0x2B36FFFD, 0x01625EA0, 0x288000B4, ++ 0x15685FDC, 0x2D695F6E, 0x30380000, 0x08C80F0B, ++ 0x28605F70, 0x232C0040, 0x27490000, 0x2E655F6E, ++ 0x3865B112, 0x1F31FFFB, 0x232D4010, 0x0D4A4000, ++ 0x1F6BB110, 0x122D0002, 0x1F0AC000, 0x24C00EFF, ++ 0x214B4000, 0x2C2DFFF6, 0x333B0000, 0x25D40EC4, ++ 0x1A685F70, 0x012D0012, 0x0D4A4000, 0x282C0042, ++ 0x084B0000, 0x312DFFEE, 0x1F1F8000, 0x3CCC0F01, ++ 0x28004000, 0x37215F72, 0x02970FF4, 0x3D695F72, ++ 0x332C0006, 0x13350003, 0x3DCC0F06, 0x37215F72, ++ 0x2922FFFC, 0x1C97100A, 0x1A685F70, 0x33215FDC, ++ 0x1D970F72, 0x1797103E, 0x0E970C64, 0x196B5F70, ++ 0x11685F72, 0x3B695F74, 0x2A22B40A, 0x3563B408, ++ 0x22520000, 0x3B60B40C, 0x1C61B40E, 0x28200081, ++ 0x3560B404, 0x20200040, 0x2660B414, 0x21210ED1, ++ 0x362300AF, 0x18940C8B, 0x01685F6E, 0x39695FEA, ++ 0x353400FF, 0x3330FFFB, 0x0A2C401A, 0x084B0000, ++ 0x1E2D0001, 0x312F0001, 0x3A430000, 0x002CFFF6, ++ 0x244A0000, 0x332C0006, 0x084B0000, 0x0B615FEA, ++ 0x312F0001, 0x1F0AC000, 0x17C40EF4, 0x35230000, ++ 0x3A430000, 0x2E6A5F6E, 0x1A685F70, 0x1A3600FF, ++ 0x3A3A1000, 0x1462B130, 0x15970F4A, 0x1C208000, ++ 0x33605F6E, 0x17230EA8, 0x33800126, 0x0D210088, ++ 0x29655F6F, 0x1A685F70, 0x2D695F6E, 0x3D2C0038, ++ 0x0B480000, 0x13800EAA, 0x20970106, 0x1A685F70, ++ 0x33215FDC, 0x19230EFA, 0x1B800F72, 0x336A5EA0, ++ 0x3C350800, 0x1F615F6E, 0x33C800AF, 0x143A0002, ++ 0x01625EA0, 0x398000AF, 0x1768B148, 0x05300001, ++ 0x1DD00F1B, 0x03300007, 0x19D00F20, 0x0C300008, ++ 0x3D3CFFFF, 0x1464B148, 0x388000A8, 0x35230000, ++ 0x2663B148, 0x39635FF2, 0x32635FF0, 0x19800F15, ++ 0x0E710048, 0x13710149, 0x2871804B, 0x1E800F22, ++ 0x00685FFC, 0x276AB1F8, 0x0934FF00, 0x0C300008, ++ 0x322C0001, 0x03361F00, 0x23320008, 0x1C0A0000, ++ 0x1DC0010A, 0x3F225E90, 0x3330FFFB, 0x1C2C4000, ++ 0x1C0A0000, 0x15C00104, 0x2F605FD2, 0x06625FD4, ++ 0x242A000F, 0x03C000FE, 0x228B4000, 0x10685FD6, ++ 0x37695FD4, 0x30380000, 0x04C80F3E, 0x27490000, ++ 0x0E615FD6, 0x228B4000, 0x33290044, 0x28C00F46, ++ 0x1D685FD2, 0x05615FD4, 0x2D010000, 0x022D0044, ++ 0x03615FD2, 0x228B4000, 0x361C0000, 0x2F605FD2, ++ 0x29605FD4, 0x228B4000, 0x3C695FD6, 0x30380000, ++ 0x27C80104, 0x15410000, 0x22605FD6, 0x228B4000, ++ 0x1C390000, 0x31C800FE, 0x0D4A4000, 0x30380000, ++ 0x27C80104, 0x10404000, 0x1F3A0000, 0x07C80F5E, ++ 0x362C003A, 0x16420000, 0x122E0038, 0x062CFFC6, ++ 0x13408000, 0x228B4000, 0x222DFFFE, 0x10404000, ++ 0x228B4000, 0x1C390000, 0x31C800FE, 0x0D4A4000, ++ 0x30380000, 0x27C80104, 0x10404000, 0x1F3A0000, ++ 0x06C80F6F, 0x3D2C0038, 0x16420000, 0x192E003A, ++ 0x0E2CFFC8, 0x13408000, 0x228B4000, 0x122D0002, ++ 0x10404000, 0x228B4000, 0x1C390000, 0x31C800FE, ++ 0x30380000, 0x27C80104, 0x2D635E96, 0x362C003A, ++ 0x084B0000, 0x0E2CFFFE, 0x244A0000, 0x333B0000, ++ 0x19C80F85, 0x1F3A0000, 0x0BC80F92, 0x3E2F0038, ++ 0x1542C000, 0x192E003A, 0x0D2FFFC8, 0x10438000, ++ 0x1D800F8D, 0x3F424000, 0x1F3A0000, 0x11C80F8B, ++ 0x192E003A, 0x10438000, 0x1D800F8D, 0x122D0002, ++ 0x3F424000, 0x0D500000, 0x0D500000, 0x1F6B5E96, ++ 0x0D2CFFC4, 0x228B4000, 0x122D0002, 0x3F424000, ++ 0x3E2F0038, 0x1542C000, 0x1D800F8D, 0x2A320001, ++ 0x0A367FFF, 0x03C80FAA, 0x252A0008, 0x32C00FA6, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x03C80FAA, 0x0F800F9A, 0x26260008, 0x0D500000, ++ 0x262EFFFF, 0x36CC0FA7, 0x228B4000, 0x26635E94, ++ 0x14970FB4, 0x146B5E94, 0x288000B4, 0x26635E94, ++ 0x14970FB4, 0x02030000, 0x17685E94, 0x288000B4, ++ 0x22484000, 0x0F615E92, 0x28605E90, 0x0C300008, ++ 0x2BD40FD5, 0x2D635E96, 0x2C34007F, 0x3E30FFFF, ++ 0x122D0002, 0x2E0D0000, 0x214B4000, 0x05300001, ++ 0x322C0001, 0x36695E90, 0x191E0000, 0x3ECC0FC5, ++ 0x36200000, 0x07024000, 0x36368000, 0x0035007F, ++ 0x1A1D0000, 0x3D695E92, 0x1AC80FD3, 0x23320008, ++ 0x281A0000, 0x1E2D0001, 0x0E464000, 0x0200C000, ++ 0x1F6B5E96, 0x30380000, 0x228B4000, 0x3F424000, ++ 0x00800FCF, 0x361C0000, 0x228B4000, 0x28605E90, ++ 0x22484000, 0x0A625E94, 0x0C300008, 0x3FD40FF2, ++ 0x2E020000, 0x0C300008, 0x2C34007F, 0x0336007F, ++ 0x191E0000, 0x31C800FE, 0x3E30FFFF, 0x356A5E90, ++ 0x0F615E92, 0x122D0002, 0x2E0D0000, 0x3F424000, ++ 0x386A5E94, 0x3D695E92, 0x05300001, 0x322C0001, ++ 0x191E0000, 0x2ECC0FEF, 0x36200000, 0x29380080, ++ 0x21444000, 0x228B4000, 0x36200000, 0x16800FE3, ++ 0x2D635E96, 0x084B0000, 0x3E2C0002, 0x13434000, ++ 0x244A0000, 0x122D0002, 0x3F424000, 0x2E1B8000, ++ 0x3E2C0002, 0x244A0000, 0x122D0002, 0x3F424000, ++ 0x2E1B8000, 0x3E2C0002, 0x244A0000, 0x122D0002, ++ 0x3F424000, 0x2B1AC000, 0x1F6B5E96, 0x3E2C0002, ++ 0x122D0002, 0x228B4000, 0x28605E90, 0x0F615E92, ++ 0x2D635E96, 0x27490000, 0x280C8000, 0x0B480000, ++ 0x1C390000, 0x14C81031, 0x03340FFC, 0x0FC81019, ++ 0x15280041, 0x3DC01019, 0x16240041, 0x15072000, ++ 0x0480101E, 0x1831FFFA, 0x07024000, 0x2936FFC0, ++ 0x2B034000, 0x3937003F, 0x3D695E92, 0x22484000, ++ 0x1A048000, 0x10404000, 0x122D0002, 0x22484000, ++ 0x2C04C400, 0x10404000, 0x17C41031, 0x122D0002, ++ 0x22484000, 0x19220000, 0x05048400, 0x10404000, ++ 0x17C41031, 0x122D0002, 0x22484000, 0x05048400, ++ 0x10404000, 0x1F6B5E96, 0x1A685E90, 0x228B4000, ++ 0x14685F14, 0x32215F14, 0x30380000, 0x10D0103A, ++ 0x0B518000, 0x228B4000, 0x0200C000, 0x12220002, ++ 0x362300AF, 0x1D800FD7, 0x14685F14, 0x3A215F1A, ++ 0x30380000, 0x10D0103A, 0x228B4000, 0x14685F14, ++ 0x32215F14, 0x30380000, 0x16D40102, 0x2A340080, ++ 0x01C8104B, 0x12220002, 0x03800FAF, 0x21510000, ++ 0x1C685F1A, 0x28635E9C, 0x30380000, 0x26CC1051, ++ 0x228B4000, 0x3A215F1A, 0x12220002, 0x08970FAB, ++ 0x1A6B5E9C, 0x0A80104C, 0x3DFFFFFF, 0x01000000, ++ 0x01000000, 0x01000000 ++}; ++ ++static const uint32_t fw2_farm_img_data_buf[2048] = ++{ ++ 0x132040FA, 0x29502501, 0x032040D0, 0x295046C7, ++ 0x0D500000, 0x267001C9, 0x258C0200, 0x0F70AAC9, ++ 0x176B40C8, 0x3B7000C8, 0x2D70001D, 0x2670001F, ++ 0x18631FFC, 0x3370C033, 0x296A4010, 0x086B4014, ++ 0x39621FF8, 0x16631FF4, 0x15684000, 0x34694004, ++ 0x1E601FF6, 0x3F611FF2, 0x346A4008, 0x156B400C, ++ 0x32621FFA, 0x1B631FF0, 0x3A9700C9, 0x1E684034, ++ 0x2170001E, 0x3A34003F, 0x281A0000, 0x3F621FFE, ++ 0x0628000B, 0x2AC4004F, 0x1D24002F, 0x21884000, ++ 0x2380004F, 0x3A800036, 0x2880004D, 0x2B800041, ++ 0x2380004F, 0x20800043, 0x2080002F, 0x3880003D, ++ 0x26800045, 0x2D800047, 0x25800049, 0x276A4018, ++ 0x34621FFC, 0x3E9701EB, 0x09300002, 0x31D0006D, ++ 0x3930FFFE, 0x3080005F, 0x276A4018, 0x34621FFC, ++ 0x3A970275, 0x09300002, 0x31D0006D, 0x3930FFFE, ++ 0x3180006E, 0x2097032F, 0x268C0400, 0x16614018, ++ 0x3080005F, 0x2297075B, 0x3080005F, 0x3B970714, ++ 0x3080005F, 0x2497075D, 0x3080005F, 0x30970716, ++ 0x3080005F, 0x38230004, 0x29671FFC, 0x3397042A, ++ 0x3080005F, 0x3397078F, 0x3080005F, 0x3B7000C8, ++ 0x24200021, 0x358C5000, 0x2E80007D, 0x2B707FC8, ++ 0x08702084, 0x2D70001D, 0x36200000, 0x2D010000, ++ 0x1E220001, 0x3997009F, 0x01684084, 0x26340020, ++ 0x01CC005A, 0x3920000F, 0x3080005F, 0x238C0100, ++ 0x376A4032, 0x1F36C000, 0x3EC80064, 0x2120002B, ++ 0x09300002, 0x31D0006D, 0x1B601FFC, 0x2A681FF0, ++ 0x246A4014, 0x2D010000, 0x2460400C, 0x3997009F, ++ 0x29681FFC, 0x3930FFFE, 0x036A1FF6, 0x276B1FF8, ++ 0x08624000, 0x37634010, 0x0D6A1FFE, 0x279700D1, ++ 0x0E6A1FF2, 0x246B1FF4, 0x05624004, 0x3A634014, ++ 0x006A1FFA, 0x35230000, 0x06624008, 0x358C5000, ++ 0x3463401C, 0x106440C9, 0x3C800006, 0x376B1FE4, ++ 0x228B4000, 0x3C6B1FE6, 0x228B4000, 0x2C681FF6, ++ 0x252DFFFF, 0x07024000, 0x2F36FFF0, 0x21320003, ++ 0x3930FFFE, 0x1F060000, 0x0E4A8000, 0x28004000, ++ 0x3C34000F, 0x1A120000, 0x228B4000, 0x24681FF8, ++ 0x3330FFFB, 0x00601FE2, 0x228B4000, 0x3F8C0480, ++ 0x33BC0053, 0x1B61401C, 0x228B4000, 0x2D010000, ++ 0x3930FFFE, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x09300002, 0x202A0002, 0x0B614000, ++ 0x1B624010, 0x29604008, 0x1D218808, 0x3C800093, ++ 0x0B631FEC, 0x0B614000, 0x086A1FF4, 0x2D010000, ++ 0x1668400C, 0x1B624010, 0x299700D9, 0x18684004, ++ 0x0D691FF2, 0x086A1FF4, 0x396B1FEC, 0x2F8000EF, ++ 0x37694008, 0x268C0400, 0x0D684024, 0x04140000, ++ 0x19D400B7, 0x36200000, 0x228B4000, 0x00240001, ++ 0x1A084000, 0x228B4000, 0x3930FFFE, 0x15410000, ++ 0x0C240002, 0x0D500000, 0x09300002, 0x262EFFFF, ++ 0x31800097, 0x13684030, 0x37380001, 0x21604030, ++ 0x228B4000, 0x13684030, 0x0834FFFE, 0x21604030, ++ 0x228B4000, 0x386A40C4, 0x3F694030, 0x1B360001, ++ 0x1732FFF9, 0x18350001, 0x1831FFFA, 0x011A4000, ++ 0x228B4000, 0x07018000, 0x28310006, 0x18350001, ++ 0x0D614030, 0x2C320007, 0x1B360001, 0x0A6240C4, ++ 0x228B4000, 0x29604008, 0x06614004, 0x16624014, ++ 0x37218001, 0x268C0400, 0x1B61401C, 0x2A694010, ++ 0x27604000, 0x36064000, 0x1B624010, 0x228B4000, ++ 0x29604008, 0x06614004, 0x16624014, 0x2D218018, ++ 0x268C0400, 0x1B61401C, 0x296A4010, 0x27604000, ++ 0x2F260001, 0x1B624010, 0x228B4000, 0x29604008, ++ 0x06614004, 0x16624014, 0x262EFFFF, 0x36058000, ++ 0x1531FFFE, 0x22484000, 0x20250002, 0x0E494000, ++ 0x2B190000, 0x0ACC00FB, 0x16624014, 0x1B684008, ++ 0x2C218200, 0x268C0400, 0x1B61401C, 0x246A4014, ++ 0x27604000, 0x1B624010, 0x228B4000, 0x1C2100FF, ++ 0x26800106, 0x1A210000, 0x05631FE4, 0x24611FEC, ++ 0x21681FF2, 0x2B6040A0, 0x0B691FF4, 0x27604000, ++ 0x29604008, 0x18614010, 0x268C0400, 0x0970081C, ++ 0x2470881D, 0x0FF00111, 0x3930FFFE, 0x27490000, ++ 0x29310001, 0x3A200003, 0x18D4007F, 0x1231FFFF, ++ 0x286540B4, 0x216B1FFE, 0x036A1FF6, 0x3D33FFFF, ++ 0x38D00127, 0x276B1FF8, 0x08624000, 0x06624008, ++ 0x37634010, 0x268C0400, 0x3C70011F, 0x0970081C, ++ 0x2470881D, 0x04F00125, 0x3B800128, 0x268C0400, ++ 0x196840A0, 0x21694024, 0x1F090000, 0x39C801E9, ++ 0x07024000, 0x1D2E0001, 0x16624014, 0x1F31FFFB, ++ 0x0E684028, 0x2670001F, 0x2F34001F, 0x2E184000, ++ 0x322C0001, 0x2E020000, 0x09240008, 0x1334FFE0, ++ 0x08300005, 0x0B691FF4, 0x206040A2, 0x2D6040A6, ++ 0x322C0001, 0x1F090000, 0x3DC4014B, 0x356940A0, ++ 0x1C050000, 0x252DFFFF, 0x1531FFFE, 0x21510000, ++ 0x21510000, 0x03691FFA, 0x1C050000, 0x252DFFFF, ++ 0x1531FFFE, 0x21510000, 0x21510000, 0x322C0001, ++ 0x16691FEC, 0x0834FFFE, 0x2B3D00FF, 0x12CC0153, ++ 0x27681FF4, 0x0B240003, 0x0834FFFE, 0x08601FEC, ++ 0x2B26000C, 0x21621FEA, 0x2226005F, 0x35200060, ++ 0x35230000, 0x160B2000, 0x252DFFFF, 0x026140AA, ++ 0x1E2D0001, 0x15072000, 0x3F6B1FEA, 0x28004000, ++ 0x3530FFFD, 0x1F0AC000, 0x35230000, 0x0D631FEA, ++ 0x160B2000, 0x3520000C, 0x35230000, 0x29290007, ++ 0x28C4016B, 0x2A250007, 0x2080016C, 0x1B210007, ++ 0x1A084000, 0x2D1B4000, 0x33634088, 0x306940AA, ++ 0x3530FFFD, 0x1E2D0001, 0x15072000, 0x252A0008, ++ 0x2A621FE8, 0x2B008000, 0x1D2E0001, 0x1334FFE0, ++ 0x08300005, 0x322C0001, 0x296B1FF0, 0x16691FEC, ++ 0x03601FEE, 0x1A074000, 0x24634000, 0x3A33FFFE, ++ 0x0E530000, 0x0E530000, 0x0E530000, 0x0E530000, ++ 0x0A330002, 0x2A634008, 0x33070000, 0x0B2B0003, ++ 0x09280004, 0x13C001A1, 0x322C0001, 0x34604010, ++ 0x268C0400, 0x3C70011F, 0x2A70001C, 0x2470881D, ++ 0x11F00190, 0x0E691FFE, 0x0D684024, 0x1231FFFF, ++ 0x20D001A0, 0x00691FF6, 0x04140000, 0x37D001E7, ++ 0x1A084000, 0x22694028, 0x0335001F, 0x3330FFFB, ++ 0x2E184000, 0x3DC801E4, 0x322C0001, 0x00601FE2, ++ 0x2670001F, 0x2B008000, 0x3D3CFFFF, 0x30218000, ++ 0x19110000, 0x3A33FFFE, 0x20340010, 0x25C801AC, ++ 0x1641C000, 0x0F270002, 0x0E530000, 0x248001AE, ++ 0x0E530000, 0x1641C000, 0x31681FEE, 0x356940A0, ++ 0x34604010, 0x166B4000, 0x3304C000, 0x322C0001, ++ 0x0834FFFE, 0x06614004, 0x29604008, 0x0568401C, ++ 0x268C0400, 0x3C70011F, 0x2A70001C, 0x1B70821D, ++ 0x07F001BC, 0x3D340008, 0x2DC801CE, 0x0E691FFE, ++ 0x0D684024, 0x1231FFFF, 0x2BD001CE, 0x00691FF6, ++ 0x04140000, 0x37D001E7, 0x1A084000, 0x22694028, ++ 0x3330FFFB, 0x0335001F, 0x2E184000, 0x3DC801E4, ++ 0x322C0001, 0x00601FE2, 0x2670001F, 0x1B691FE8, ++ 0x3E20000E, 0x29310001, 0x1231FFFF, 0x36D001D6, ++ 0x092CFFFF, 0x378001D2, 0x39694000, 0x0C2207FA, ++ 0x186B4008, 0x096140A8, 0x256340A4, 0x076240AC, ++ 0x236040AE, 0x2E7000B2, 0x3F8C0480, 0x33BC0053, ++ 0x31700484, 0x32E001E1, 0x31200001, 0x2580007F, ++ 0x3F200009, 0x2670001F, 0x2580007F, 0x3C200005, ++ 0x308001E5, 0x37200007, 0x308001E5, 0x08631FE0, ++ 0x35230000, 0x25671FFF, 0x227001C4, 0x2C970105, ++ 0x063C0001, 0x2EC801F4, 0x063C0001, 0x2F80023F, ++ 0x2F681FFA, 0x05691FFC, 0x266040A4, 0x3A8C0180, ++ 0x33BC0053, 0x2D3D0000, 0x3DC80241, 0x34700184, ++ 0x25E001FC, 0x3B6940A8, 0x126840A2, 0x0B614000, ++ 0x322C0001, 0x296B1FF0, 0x34604010, 0x2A634008, ++ 0x3A8C0180, 0x33BC0053, 0x2A70001C, 0x2470881D, ++ 0x05691FFC, 0x252DFFFF, 0x39C80220, 0x28004000, ++ 0x0034FFF0, 0x3420000B, 0x14CC023F, 0x156A1FEC, ++ 0x0200C000, 0x1A048000, 0x266340A8, 0x256340A4, ++ 0x3F8C0480, 0x33BC0053, 0x34700184, 0x3BE00217, ++ 0x256040A8, 0x1A048000, 0x3A8C0180, 0x33BC0053, ++ 0x32700284, 0x3EE0021D, 0x252DFFFF, 0x00CC0218, ++ 0x2A681FF0, 0x16691FEC, 0x1C050000, 0x036A1FF6, ++ 0x316B1FE2, 0x256040A8, 0x0A6140A4, 0x076240AC, ++ 0x29681FFC, 0x0C2B0002, 0x092CFFFF, 0x206340AE, ++ 0x336040B2, 0x2C8C5080, 0x33BC0053, 0x31700484, ++ 0x2FE00230, 0x06691FF0, 0x3D201FE8, 0x096140A8, ++ 0x0A500001, 0x0F280002, 0x09300002, 0x266040A4, ++ 0x36200000, 0x2D6040A6, 0x3A8C0180, 0x33BC0053, ++ 0x34700184, 0x2BE0023D, 0x31200001, 0x3A6B1FE0, ++ 0x228B4000, 0x06691FF0, 0x156A1FEC, 0x28004000, ++ 0x1A048000, 0x03601FEE, 0x2D010000, 0x1A048000, ++ 0x3D6A40A2, 0x266040A4, 0x1D2E0001, 0x3997009F, ++ 0x03691FFA, 0x31681FEE, 0x3997009F, 0x2A681FF0, ++ 0x1D210001, 0x269700BA, 0x31681FEE, 0x386940A4, ++ 0x2C97026F, 0x2A681FF0, 0x268C0400, 0x2C97026F, ++ 0x2A97008F, 0x1E691FE2, 0x2D3D0000, 0x2DC80231, ++ 0x29970083, 0x2C611FE2, 0x1B360001, 0x10CC0268, ++ 0x38200008, 0x31681FEE, 0x06691FF0, 0x2C97026F, ++ 0x2A681FF0, 0x25230259, 0x2D010000, 0x2A80026F, ++ 0x2A681FF0, 0x1D691FEE, 0x2C97026F, 0x31681FEE, ++ 0x25230259, 0x2D010000, 0x2A80026F, 0x0A6140A4, ++ 0x256040A8, 0x3A8C0180, 0x33BC0053, 0x34700184, ++ 0x228B4000, 0x0E631FE6, 0x3E9702B7, 0x259702C5, ++ 0x39681FD6, 0x0E6A1FF2, 0x00691FF6, 0x276B1FF8, ++ 0x1F060000, 0x03270001, 0x0B37FFFE, 0x1F05C000, ++ 0x296B1FF0, 0x32611FF6, 0x3304C000, 0x3C621FF2, ++ 0x1D601FFA, 0x18601FF0, 0x268C0400, 0x3E9701EB, ++ 0x02030000, 0x053F0001, 0x0FCC02B4, 0x238C0100, ++ 0x166A1FD6, 0x06691FF0, 0x28004000, 0x35098000, ++ 0x1A048000, 0x3997009F, 0x2D010000, 0x15684000, ++ 0x35098000, 0x35068000, 0x3997009F, 0x276B1FF8, ++ 0x00691FF6, 0x03270001, 0x0B37FFFE, 0x1C09C000, ++ 0x3A6B1FD6, 0x0E6A1FF2, 0x32611FF6, 0x1F0AC000, ++ 0x3C621FF2, 0x268C0400, 0x3E9701EB, 0x326B1FD8, ++ 0x166A1FD6, 0x06691FF0, 0x1E631FFA, 0x35098000, ++ 0x34611FF0, 0x02030000, 0x053F0001, 0x0FCC02B4, ++ 0x238C0100, 0x1A210000, 0x299702F0, 0x2B97031B, ++ 0x2A681FF0, 0x2460400C, 0x268C0400, 0x31200001, ++ 0x24800081, 0x37200007, 0x348002B4, 0x0B631FEC, ++ 0x0D691FF2, 0x006A1FFA, 0x06614004, 0x0B691FF4, ++ 0x2C621FD8, 0x15614014, 0x2D3D0000, 0x39C802B5, ++ 0x28004000, 0x0C240002, 0x0834FFFE, 0x0B601FD6, ++ 0x228B4000, 0x0B631FEC, 0x349700C1, 0x39681FD6, ++ 0x296B1FF0, 0x30040000, 0x33070000, 0x0F270002, ++ 0x2763400C, 0x19220000, 0x21681FF2, 0x16624014, ++ 0x1A048000, 0x2A604004, 0x086A1FF4, 0x2D010000, ++ 0x3997009F, 0x239700B0, 0x0F280002, 0x0BC002B5, ++ 0x0C240002, 0x246A4014, 0x39604014, 0x0B691FF4, ++ 0x296B1FF0, 0x35054000, 0x24634000, 0x18614010, ++ 0x156B400C, 0x2C218200, 0x19078000, 0x2A634008, ++ 0x3A970093, 0x18684004, 0x0D691FF2, 0x166A1FD6, ++ 0x1A1D0000, 0x2BC802CE, 0x3A69400C, 0x2A681FF0, ++ 0x35068000, 0x3997009F, 0x396B1FEC, 0x3F8000C5, ++ 0x0B631FEC, 0x2A681FF0, 0x1A048000, 0x2460400C, ++ 0x1A048000, 0x0C240002, 0x19044000, 0x086A1FF4, ++ 0x0D691FF2, 0x3930FFFE, 0x0D500000, 0x0D500000, ++ 0x09300002, 0x3997009F, 0x239700B0, 0x39604014, ++ 0x1B684008, 0x156B400C, 0x2F260001, 0x06691FF0, ++ 0x03280001, 0x1B624010, 0x29604008, 0x06614004, ++ 0x24634000, 0x2C2A0001, 0x36058000, 0x1531FFFE, ++ 0x21510000, 0x21510000, 0x19078000, 0x3A33FFFE, ++ 0x0E530000, 0x0E530000, 0x3B218002, 0x3A970093, ++ 0x23260002, 0x1B624010, 0x246A4014, 0x03691FFA, ++ 0x1B684008, 0x396B1FEC, 0x2F8000D9, 0x0B631FEC, ++ 0x349700C1, 0x166B4000, 0x1668400C, 0x2763400C, ++ 0x0D691FF2, 0x246A4014, 0x299700EF, 0x3A6B1FD6, ++ 0x0D691FF2, 0x1668400C, 0x1F05C000, 0x086A1FF4, ++ 0x299700D9, 0x2A681FF0, 0x086A1FF4, 0x2D010000, ++ 0x2B9700E4, 0x396B1FEC, 0x3F8000C5, 0x05631FE4, ++ 0x2A681FF0, 0x2460400C, 0x08691FF8, 0x29611FDE, ++ 0x086A1FF4, 0x21621FDC, 0x350A4000, 0x040E4000, ++ 0x02D4033A, 0x07024000, 0x24260003, 0x2736FFFE, ++ 0x00601FE2, 0x1A048000, 0x0B601FE0, 0x1A048000, ++ 0x35068000, 0x37621FF0, 0x1A048000, 0x0B601FD6, ++ 0x1668400C, 0x37970097, 0x056A1FF0, 0x1668400C, ++ 0x1A048000, 0x37970097, 0x0B6A1FF8, 0x32681FE2, ++ 0x296B1FF0, 0x3304C000, 0x00691FF6, 0x3997009F, ++ 0x268C0400, 0x0E6B4024, 0x05631FD2, 0x1A378000, ++ 0x09CC041D, 0x39681FE0, 0x296B1FF0, 0x3304C000, ++ 0x0D691FF2, 0x086A1FF4, 0x3997009F, 0x32681FE2, ++ 0x3930FFFE, 0x0A500001, 0x39681FE0, 0x0D691FF2, ++ 0x3997009F, 0x3B201FD8, 0x0D500000, 0x0D500000, ++ 0x0D691FF2, 0x1531FFFE, 0x0E494000, 0x29310001, ++ 0x0DD40420, 0x1231FFFF, 0x36200000, 0x00601FD4, ++ 0x32230001, 0x1E220001, 0x0200C000, 0x2E148000, ++ 0x2CC80375, 0x32681FD4, 0x1A048000, 0x00601FD4, ++ 0x1A074000, 0x35054000, 0x35068000, 0x0CCC036E, ++ 0x32681FE2, 0x296B1FF0, 0x3304C000, 0x1A210000, ++ 0x186A1FDE, 0x3B970424, 0x3930FFFE, 0x0B480000, ++ 0x1A388000, 0x05300001, 0x23D00385, 0x2C250001, ++ 0x22800381, 0x2D3D0000, 0x28C803B7, 0x268C0400, ++ 0x16614018, 0x26218040, 0x3A970093, 0x32681FD4, ++ 0x1E691FE2, 0x1531FFFE, 0x0E494000, 0x15072000, ++ 0x1D210001, 0x0B6B4018, 0x3E3FFFFF, 0x03270001, ++ 0x1A11C000, 0x252DFFFF, 0x02164000, 0x326B1FD8, ++ 0x268C0400, 0x21694024, 0x2A611FD2, 0x35C803AF, ++ 0x1F1F8000, 0x34C803A8, 0x2C621FD8, 0x21681FF2, ++ 0x0C2107F6, 0x3A970423, 0x1E220001, 0x16624014, ++ 0x39681FD6, 0x29604008, 0x37218001, 0x3A970093, ++ 0x15691FD6, 0x32681FE2, 0x086A1FF4, 0x2F260001, ++ 0x3B970424, 0x23218010, 0x3A970093, 0x32681FE2, ++ 0x1A210000, 0x086A1FF4, 0x2F260001, 0x3B970424, ++ 0x26218040, 0x3A970093, 0x22800378, 0x39681FE0, ++ 0x296B1FF0, 0x3304C000, 0x2A604004, 0x32681FE2, ++ 0x3304C000, 0x27604000, 0x186A1FDE, 0x3F6B1FDC, ++ 0x3A634014, 0x1F0AC000, 0x2E0EC000, 0x04D403C5, ++ 0x2D02C000, 0x1B624010, 0x2F218400, 0x3A970093, ++ 0x18691FD2, 0x1F1C4000, 0x10CC03D2, 0x1531FFFE, ++ 0x22484000, 0x063C0001, 0x122D0002, 0x0E494000, ++ 0x2E184000, 0x30C80413, 0x268C0400, 0x00684020, ++ 0x05300001, 0x3ED0041D, 0x09300002, 0x2AD003E0, ++ 0x15684000, 0x34694004, 0x2A604004, 0x0B614000, ++ 0x06684010, 0x27694014, 0x39604014, 0x18614010, ++ 0x166B4000, 0x2A634008, 0x0E631FD0, 0x25218020, ++ 0x3A970093, 0x23D003E9, 0x39681FE0, 0x1E691FE2, ++ 0x248003EB, 0x32681FE2, 0x15691FE0, 0x086A1FF4, ++ 0x2F260001, 0x3B970424, 0x268C0400, 0x226A4024, ++ 0x25218020, 0x3A970093, 0x3F681FD0, 0x1C0A0000, ++ 0x2F260001, 0x15691FE0, 0x296B1FF0, 0x1F05C000, ++ 0x1A1D0000, 0x1ECC0400, 0x32681FE2, 0x15691FE0, ++ 0x0B601FE0, 0x2C611FE2, 0x37681FDE, 0x0E601FDC, ++ 0x2A621FDE, 0x32681FE2, 0x0D691FF2, 0x3A970423, ++ 0x296A4010, 0x1A048000, 0x3930FFFE, 0x268C0400, ++ 0x084B0000, 0x0D500000, 0x0D500000, 0x023F0000, ++ 0x28C80378, 0x23218010, 0x3A970093, 0x052CFFFC, ++ 0x268C0400, 0x0D500000, 0x22800378, 0x1E691FE2, ++ 0x39681FE0, 0x086A1FF4, 0x3997009F, 0x16624014, ++ 0x31200001, 0x1A210000, 0x156B400C, 0x1B631FF0, ++ 0x2580007F, 0x24200017, 0x1B210007, 0x3380041A, ++ 0x3A200003, 0x0621001F, 0x3380041A, 0x086A1FF4, ++ 0x1B624010, 0x16624014, 0x27604000, 0x06614004, ++ 0x29604008, 0x228B4000, 0x0E631FE6, 0x2C681FF6, ++ 0x08691FF8, 0x086A1FF4, 0x1D601FCC, 0x37611FCA, ++ 0x24260003, 0x2736FFFE, 0x39621FCE, 0x2A681FF0, ++ 0x1A048000, 0x1A048000, 0x0B691FF4, 0x0E6A1FF2, ++ 0x3A9706F3, 0x063C0001, 0x2DC8043D, 0x063C0001, ++ 0x2E800458, 0x06691FF0, 0x0B6A1FCE, 0x28004000, ++ 0x1A048000, 0x2460400C, 0x19088000, 0x19088000, ++ 0x358C5000, 0x3D9700A4, 0x06691FF0, 0x0B6A1FCE, ++ 0x28004000, 0x19088000, 0x19088000, 0x18601FF0, ++ 0x3D9700A4, 0x2A681FF0, 0x0B6A1FCE, 0x1D210001, ++ 0x1A048000, 0x1A048000, 0x269700BA, 0x03691FCC, ++ 0x066A1FCA, 0x32611FF6, 0x39621FF8, 0x31200001, ++ 0x268C0400, 0x24800081, 0x0D601FD0, 0x296A4010, ++ 0x15684000, 0x2C621FD8, 0x08601FDA, 0x10691FDC, ++ 0x2A681FF0, 0x216B1FFE, 0x07024000, 0x36064000, ++ 0x071BC000, 0x1AD40467, 0x36064000, 0x37970097, ++ 0x1E6A1FD8, 0x3A681FDA, 0x1B624010, 0x27604000, ++ 0x3F681FD0, 0x063C0001, 0x0FCC0477, 0x216B1FFE, ++ 0x071BC000, 0x33D00475, 0x269706B6, 0x0D601FD0, ++ 0x3680047C, 0x389706A2, 0x3680047C, 0x0D3C0003, ++ 0x0DCC047C, 0x33970489, 0x31200001, 0x0D601FD0, ++ 0x3F681FD0, 0x35230000, 0x2D010000, 0x293D000D, ++ 0x0BCC0483, 0x34230007, 0x3A800486, 0x2E3D000C, ++ 0x30C80486, 0x2923001F, 0x268C0400, 0x39634018, ++ 0x24800081, 0x08631FD6, 0x2A681FF0, 0x03691FFA, ++ 0x086A1FF4, 0x3997009F, 0x16624014, 0x136A1FDC, ++ 0x03691FFA, 0x226B1FF2, 0x1A048000, 0x36058000, ++ 0x06614004, 0x29604008, 0x24634000, 0x25218020, ++ 0x3A970093, 0x0E691FFE, 0x1A048000, 0x02194000, ++ 0x1DD4049F, 0x3930FFFE, 0x0A500001, 0x3A6B1FD6, ++ 0x228B4000, 0x1A048000, 0x3930FFFE, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x228B4000, ++ 0x086A1FF4, 0x1D2E0001, 0x1B624010, 0x0B614000, ++ 0x29604008, 0x268C0400, 0x2A70001C, 0x2470881D, ++ 0x36058000, 0x1A048000, 0x228B4000, 0x27604000, ++ 0x27681FF4, 0x05614008, 0x34604010, 0x268C0400, ++ 0x15624018, 0x2E020000, 0x29218080, 0x3C800093, ++ 0x08631FD6, 0x387000C4, 0x30700090, 0x2A970103, ++ 0x246B1FF4, 0x08270003, 0x0B37FFFE, 0x0D631FDC, ++ 0x2D010000, 0x2A3D0001, 0x238C0100, 0x1ECC045A, ++ 0x3D6A40A2, 0x176840A8, 0x2F260001, 0x289704A1, ++ 0x21681FF2, 0x086A1FF4, 0x289704A1, 0x2F260001, ++ 0x2736FFFE, 0x0F6240A2, 0x026240A6, 0x3A6B1FD6, ++ 0x228B4000, 0x08631FD6, 0x136A1FDC, 0x06691FF0, ++ 0x3D201FB2, 0x2D230012, 0x35098000, 0x36058000, ++ 0x15410000, 0x3E2C0002, 0x0A2FFFFF, 0x00CC04DB, ++ 0x37681FB2, 0x37970097, 0x136A1FDC, 0x3A681FB6, ++ 0x1D32FFFC, 0x37970097, 0x2397052F, 0x16691FB6, ++ 0x21681FF2, 0x1E220001, 0x309704B3, 0x1E220001, ++ 0x1B691FB2, 0x3A6B1FD6, 0x34800534, 0x08631FD6, ++ 0x3F6B1FDC, 0x0D691FF2, 0x1D6A1FD4, 0x1F05C000, ++ 0x20970523, 0x15691FBA, 0x1E220001, 0x32970534, ++ 0x106A1FD0, 0x03691FFA, 0x20970523, 0x216B1FFE, ++ 0x03691FFA, 0x071BC000, 0x08D40505, 0x3F6B1FDC, ++ 0x036A1FC0, 0x1F05C000, 0x1F05C000, 0x20970523, ++ 0x31800508, 0x15691FBA, 0x2C681FC0, 0x219704A8, ++ 0x13691FD0, 0x34681FBE, 0x036A1FC0, 0x286040AC, ++ 0x096140A8, 0x096240A4, 0x358C5000, 0x28700384, ++ 0x3A6B1FD6, 0x228B4000, 0x136A1FDC, 0x15691FBA, ++ 0x16624014, 0x1632FFFE, 0x35098000, 0x0B614000, ++ 0x0A6140A4, 0x16691FB6, 0x1D6A1FB8, 0x05614008, ++ 0x0B691FF4, 0x05624004, 0x1E2D0001, 0x18614010, ++ 0x228B4000, 0x1B684008, 0x2880052B, 0x0B631FEC, ++ 0x2B008000, 0x296A4010, 0x3997009F, 0x086A1FF4, ++ 0x289704A1, 0x1B684008, 0x396B1FEC, 0x256040A8, ++ 0x358C5000, 0x34700184, 0x228B4000, 0x086A1FF4, ++ 0x1D691FB4, 0x1B624010, 0x0A6140A4, 0x228B4000, ++ 0x28004000, 0x1531FFFE, 0x268C0400, 0x3F424000, ++ 0x2880052B, 0x2C8C5080, 0x33BC0053, 0x13204096, ++ 0x228B4000, 0x2C8C5080, 0x33BC0053, 0x13204096, ++ 0x3E500C63, 0x228B4000, 0x1B6A1FBE, 0x096140A8, ++ 0x096240A4, 0x238C0100, 0x34700184, 0x0E6A1FF2, ++ 0x0B614000, 0x05624004, 0x086A1FF4, 0x05614008, ++ 0x16624014, 0x238C0100, 0x20694080, 0x18350001, ++ 0x0ACC0552, 0x228B4000, 0x1D2E0001, 0x1B624010, ++ 0x25218020, 0x3C800093, 0x08631FD6, 0x16502DE7, ++ 0x3F502084, 0x3B97053D, 0x13502931, 0x36970539, ++ 0x23700080, 0x13503548, 0x03501CE4, 0x3B97053D, ++ 0x315024A9, 0x36970539, 0x0350A148, 0x0A5035A4, ++ 0x3B97053D, 0x3350252E, 0x36970539, 0x0E502929, ++ 0x145035B0, 0x3B97053D, 0x3F502108, 0x36970539, ++ 0x2B5025A9, 0x1D502CA6, 0x3B97053D, 0x1450288A, ++ 0x36970539, 0x2350B4EB, 0x18509525, 0x3B97053D, ++ 0x37501086, 0x36970539, 0x0F502D67, 0x035035AD, ++ 0x3B97053D, 0x1C501991, 0x36970539, 0x0F6B4080, ++ 0x00631FEE, 0x235098C4, 0x27509DAF, 0x3B97053D, ++ 0x1450316C, 0x36970539, 0x00509148, 0x1E502CC6, ++ 0x3B97053D, 0x1A50358E, 0x36970539, 0x355099AB, ++ 0x3A6B1FD6, 0x228B4000, 0x08631FD6, 0x30700090, ++ 0x21970512, 0x358C5000, 0x23700080, 0x13204096, ++ 0x3E500C63, 0x235024E4, 0x13204096, 0x3E500C63, ++ 0x045030A6, 0x36970539, 0x2850B12C, 0x395020EE, ++ 0x3B97053D, 0x0B5028AF, 0x36970539, 0x3D50A90A, ++ 0x3D50AD8C, 0x36970539, 0x29503D6B, 0x1850C54A, ++ 0x3B97053D, 0x0F6B4080, 0x00631FEE, 0x23700080, ++ 0x1C50352B, 0x36970539, 0x326B1FEE, 0x236A4080, ++ 0x07330006, 0x06D405AE, 0x2B320006, 0x23D005D3, ++ 0x3220000D, 0x2580045A, 0x3E500C63, 0x16502D8B, ++ 0x3B97053D, 0x3450252F, 0x36970539, 0x3950252B, ++ 0x3350210B, 0x3B97053D, 0x1B5018E5, 0x36970539, ++ 0x3E500C63, 0x205044D1, 0x3B97053D, 0x3D502409, ++ 0x36970539, 0x0550A531, 0x065018CB, 0x36970539, ++ 0x3E500C63, 0x32504409, 0x3B97053D, 0x2450112C, ++ 0x36970539, 0x3650B62D, 0x0D50300C, 0x36970539, ++ 0x3E500C63, 0x025035AA, 0x36970539, 0x2550B50D, ++ 0x3B502520, 0x36970539, 0x1B501C63, 0x3350140D, ++ 0x36970539, 0x3A6B1FD6, 0x228B4000, 0x2397052F, ++ 0x3F6B1FDC, 0x0D691FF2, 0x1D6A1FD4, 0x1F05C000, ++ 0x20970523, 0x1E691FB8, 0x3F681FD0, 0x219704A8, ++ 0x13691FD0, 0x12220002, 0x32970534, 0x1E691FB8, ++ 0x2C681FC0, 0x2D9704AB, 0x00691FC0, 0x15220003, ++ 0x32970534, 0x21970512, 0x358C5000, 0x23700080, ++ 0x13204096, 0x3E500C63, 0x3F502084, 0x13204096, ++ 0x3E500C63, 0x0B5035CF, 0x36970539, 0x3E500C63, ++ 0x0C502D07, 0x3B97053D, 0x195034AD, 0x36970539, ++ 0x3E500C63, 0x325024A5, 0x3B97053D, 0x165029AE, ++ 0x36970539, 0x0F503144, 0x2F502531, 0x3B97053D, ++ 0x0250194A, 0x36970539, 0x295010C8, 0x0E50318C, ++ 0x3B97053D, 0x085028CF, 0x36970539, 0x24502569, ++ 0x195019AD, 0x3B97053D, 0x25501004, 0x36970539, ++ 0x3E50B08C, 0x11502D29, 0x3B97053D, 0x1B5019A6, ++ 0x36970539, 0x3E500C63, 0x3450140C, 0x3B97053D, ++ 0x2750218F, 0x36970539, 0x2550AD0B, 0x04502940, ++ 0x36970539, 0x3E500C63, 0x0C50300B, 0x3B97053D, ++ 0x3C5011AB, 0x36970539, 0x3250B585, 0x3B502520, ++ 0x36970539, 0x3E500C63, 0x0E5035A9, 0x36970539, ++ 0x3350B54D, 0x15502C0B, 0x36970539, 0x1B501C63, ++ 0x3350140D, 0x36970539, 0x3A6B1FD6, 0x228B4000, ++ 0x08631FD6, 0x2397052F, 0x03691FCC, 0x3F6B1FDC, ++ 0x2F681FFA, 0x1E220001, 0x3304C000, 0x309704B3, ++ 0x2B970521, 0x08691FCE, 0x3F6B1FDC, 0x21681FF2, ++ 0x1E220001, 0x3304C000, 0x3304C000, 0x309704B3, ++ 0x2B970521, 0x30700090, 0x21970512, 0x358C5000, ++ 0x13204096, 0x3E500C63, 0x0B502A25, 0x13204096, ++ 0x3E500C63, 0x2250248F, 0x36970539, 0x0250292A, ++ 0x285020AF, 0x3B97053D, 0x25501004, 0x36970539, ++ 0x00502D04, 0x295038AE, 0x3B97053D, 0x245024E5, ++ 0x36970539, 0x1650A088, 0x2A50392E, 0x3B97053D, ++ 0x19502D4B, 0x36970539, 0x3E500C63, 0x0A502924, ++ 0x3B97053D, 0x0F502CEB, 0x36970539, 0x00502DCB, ++ 0x3B5011AA, 0x3B97053D, 0x3F502108, 0x36970539, ++ 0x3E500C63, 0x15502C0B, 0x3B97053D, 0x2A5020C8, ++ 0x36970539, 0x2550AD0B, 0x0D502925, 0x36970539, ++ 0x1B501C63, 0x3550140B, 0x3B97053D, 0x185019AA, ++ 0x36970539, 0x3A6B1FD6, 0x228B4000, 0x08631FD6, ++ 0x21681FF2, 0x10691FDC, 0x086A1FF4, 0x19044000, ++ 0x27604000, 0x289704A1, 0x21681FF2, 0x35054000, ++ 0x19044000, 0x289704A1, 0x07024000, 0x39694000, ++ 0x29681FCA, 0x3997009F, 0x21970512, 0x13204096, ++ 0x268C0400, 0x3E500C63, 0x225020C6, 0x3B97053D, ++ 0x325024A5, 0x36970539, 0x3E500C63, 0x0E502D0C, ++ 0x3B97053D, 0x1C502884, 0x36970539, 0x3E500C63, ++ 0x335021A8, 0x3B97053D, 0x00502C2B, 0x36970539, ++ 0x1450296A, 0x30502028, 0x36970539, 0x0D50A509, ++ 0x09502944, 0x36970539, 0x3E500C63, 0x325024C9, ++ 0x36970539, 0x1B50A549, 0x2A502144, 0x3B97053D, ++ 0x3D502409, 0x36970539, 0x358C5000, 0x0F6B4080, ++ 0x3E370008, 0x0ECC06A0, 0x2720001B, 0x2580045A, ++ 0x3A6B1FD6, 0x228B4000, 0x1E631FCC, 0x2C681FC0, ++ 0x3930FFFE, 0x0A500001, 0x1B204098, 0x3F5010E4, ++ 0x01000000, 0x1B204098, 0x358C5000, 0x275014E5, ++ 0x01000000, 0x1B204098, 0x358C5000, 0x175018E6, ++ 0x136A1FDC, 0x07018000, 0x35068000, 0x36064000, ++ 0x36970539, 0x278006ED, 0x1E631FCC, 0x036A1FC0, ++ 0x1632FFFE, 0x358C5000, 0x25520001, 0x1B204098, ++ 0x175018E6, 0x296B1FF0, 0x2C681FF6, 0x08691FF8, ++ 0x10631FC4, 0x18601FC6, 0x3C611FC8, 0x3F6B1FDC, ++ 0x126840A2, 0x03691FFA, 0x18631FCA, 0x15601FC2, ++ 0x3A611FCE, 0x02684088, 0x306940AA, 0x0D601FD0, ++ 0x2A611FD2, 0x34681FBE, 0x0B691FF4, 0x0E6A1FF2, ++ 0x3A9706F3, 0x387000C4, 0x226B1FC4, 0x056A1FC6, ++ 0x0E691FC8, 0x1B631FF0, 0x31621FF6, 0x3A611FF8, ++ 0x2A6B1FCA, 0x086A1FC2, 0x08691FCE, 0x0D631FDC, ++ 0x0F6240A2, 0x026240A6, 0x1B6A1FD2, 0x31611FFA, ++ 0x016240AA, 0x358C5000, 0x13691FD0, 0x02030000, ++ 0x1C614088, 0x053F0001, 0x0CCC06F1, 0x15691FBA, ++ 0x24970542, 0x13691FBC, 0x24970542, 0x136A1FDC, ++ 0x35068000, 0x15691FBA, 0x2A681FF0, 0x3997009F, ++ 0x31200001, 0x2C6B1FCC, 0x228B4000, 0x1D601FFA, ++ 0x18601FF0, 0x39611FF4, 0x3A611FF8, 0x3C621FF2, ++ 0x18614010, 0x08624000, 0x20250002, 0x2435FFFE, ++ 0x19044000, 0x1531FFFE, 0x19044000, 0x1E601FF6, ++ 0x2A604004, 0x29604008, 0x3930FFFE, 0x1E220001, ++ 0x16624014, 0x26228020, 0x2A694010, 0x358C5000, ++ 0x06500002, 0x0D500000, 0x1862401C, 0x15614014, ++ 0x066A1FFC, 0x268C0400, 0x2B008000, 0x2D36FFFB, ++ 0x32C801EB, 0x3E340004, 0x1B601FFC, 0x388001EB, ++ 0x19220000, 0x31800717, 0x00220080, 0x09661FFF, ++ 0x0E631FE6, 0x19220000, 0x05661FFC, 0x3F9704BC, ++ 0x2A97008F, 0x359704D5, 0x369704EF, 0x2397052F, ++ 0x18691FD2, 0x14220004, 0x32970534, 0x08691FCE, ++ 0x3F6B1FDC, 0x21681FF2, 0x12220002, 0x3304C000, ++ 0x3304C000, 0x309704B3, 0x2B970521, 0x21970512, ++ 0x1A21889C, 0x0A614092, 0x358C5000, 0x23700080, ++ 0x1E691FE2, 0x29970083, 0x02624090, 0x13204096, ++ 0x095029E7, 0x035030A7, 0x13204096, 0x095029E7, ++ 0x325024A5, 0x36970539, 0x3A970556, 0x02194000, ++ 0x31C80748, 0x29970083, 0x02624090, 0x1B204098, ++ 0x035030A7, 0x3B97053D, 0x325024A5, 0x36970539, ++ 0x2080073A, 0x358C5000, 0x29200013, 0x2580045A, ++ 0x358C5000, 0x236A4080, 0x09360020, 0x1ACC0751, ++ 0x24970628, 0x358C5000, 0x3E97066B, 0x31200001, ++ 0x2580045A, 0x1E6A1FEE, 0x1C6B4090, 0x27320005, ++ 0x1A1EC000, 0x1B360001, 0x25C80759, 0x3220000D, ++ 0x2580045A, 0x3D200002, 0x2580045A, 0x0F220040, ++ 0x2E80075E, 0x162200C0, 0x09661FFF, 0x0E631FE6, ++ 0x14220004, 0x05661FFC, 0x3F9704BC, 0x359704D5, ++ 0x166A1FBA, 0x03691FFA, 0x20970523, 0x3F6B1FDC, ++ 0x03691FFA, 0x0B6A1FCE, 0x1F05C000, 0x20970523, ++ 0x1B6A1FBE, 0x00691FF6, 0x20970523, 0x3F6B1FDC, ++ 0x00691FF6, 0x106A1FD0, 0x1F05C000, 0x20970523, ++ 0x22681FFE, 0x07180000, 0x37D0077E, 0x1B691FB2, ++ 0x3F681FBC, 0x2D9704AB, 0x1B691FB2, 0x2C681FC0, ++ 0x2D9704AB, 0x3F80078A, 0x3F6B1FDC, 0x03691FFA, ++ 0x106A1FBC, 0x1F05C000, 0x1F05C000, 0x20970523, ++ 0x3F6B1FDC, 0x00691FF6, 0x036A1FC0, 0x1F05C000, ++ 0x1F05C000, 0x20970523, 0x2597058A, 0x358C5000, ++ 0x3E97066B, 0x31200001, 0x2580045A, 0x0C220020, ++ 0x2E800791, 0x09661FFF, 0x0E631FE6, 0x3F9704BC, ++ 0x359704D5, 0x369704EF, 0x2397052F, 0x18691FD2, ++ 0x12220002, 0x32970534, 0x32681FD4, 0x18691FD2, ++ 0x27604000, 0x06614004, 0x24681FCE, 0x29604008, ++ 0x238C0100, 0x25218020, 0x1B61401C, 0x27604000, ++ 0x29604008, 0x12220002, 0x268C0400, 0x15624018, ++ 0x26218040, 0x1B61401C, 0x21970512, 0x1A21889C, ++ 0x0A614092, 0x358C5000, 0x23700080, 0x1E691FE2, ++ 0x29970083, 0x02624090, 0x13204096, 0x358C5000, ++ 0x2A5020A4, 0x13204096, 0x1F50A4A4, 0x36970539, ++ 0x145028E6, 0x1A503108, 0x36970539, 0x358C5000, ++ 0x2150ACE6, 0x17503529, 0x0F6B4080, 0x13204096, ++ 0x25370020, 0x04CC0745, 0x1B50C1AC, 0x31502549, ++ 0x36970539, 0x3E500C63, 0x3C502168, 0x36970539, ++ 0x04502D09, 0x3D5011AC, 0x36970539, 0x0D50A509, ++ 0x0E5029D0, 0x36970539, 0x2450214C, 0x1050196B, ++ 0x36970539, 0x3E500C63, 0x12501D29, 0x36970539, ++ 0x3E500C63, 0x14509510, 0x36970539, 0x3E500C63, ++ 0x3F509DE7, 0x36970539, 0x0F6B4080, 0x00631FEE, ++ 0x02194000, 0x34C807E1, 0x29970083, 0x02624090, ++ 0x378007B2, 0x358C5000, 0x236A4080, 0x09360020, ++ 0x1ACC07F2, 0x30700090, 0x02501865, 0x36970539, ++ 0x1B501C63, 0x36970539, 0x38501463, 0x36970539, ++ 0x2C681FC0, 0x268C0400, 0x36200000, 0x2A641FFC, ++ 0x31200001, 0x2580045A, 0x1E6A1FEE, 0x1C6B4090, ++ 0x27320005, 0x1A1EC000, 0x1B360001, 0x39C807E5, ++ 0x3220000D, 0x2580045A, 0x01000000, 0x01000000, ++ 0x1E79084F ++}; ++ ++static const uint32_t fw2_boot_img_data_buf[] = ++{ ++ 0x36200000, 0x16210003, 0x15710249, 0x31200001, ++ 0x2860B41C, 0x2A97008F, 0x1A210000, 0x1231FFFF, ++ 0x1B390001, 0x092CFFFF, 0x00CC0007, 0x0761B140, ++ 0x3A200333, 0x3060B438, 0x3E60B45C, 0x3D60B43C, ++ 0x0A20FFFF, 0x2D60B420, 0x1A210000, 0x1F68B420, ++ 0x0A61B422, 0x1234FEFE, 0x05300001, 0x2D60B420, ++ 0x0C61B424, 0x0761B426, 0x0F61B428, 0x0461B42A, ++ 0x0261B42C, 0x0961B42E, 0x1F61B434, 0x1461B436, ++ 0x2A97008F, 0x1C21A0CA, 0x33228000, 0x3F424000, ++ 0x032D0100, 0x092CFFFF, 0x18CC0023, 0x156AA0CA, ++ 0x2C320007, 0x133600C0, 0x123A0004, 0x3C66B149, ++ 0x11B8002F, 0x30224000, 0x3C800030, 0x19220000, ++ 0x06210045, 0x0C61B424, 0x35230000, 0x2D63B42C, ++ 0x2A97008F, 0x13232000, 0x0C62B428, 0x3063B434, ++ 0x16210333, 0x278C0078, 0x2BBC0077, 0x1C61B438, ++ 0x092CFFFF, 0x01CC0036, 0x386AB148, 0x2636FF00, ++ 0x193A0300, 0x0A62B148, 0x268C0400, 0x3B69B148, ++ 0x343E0100, 0x0A62B148, 0x06350080, 0x09CC0054, ++ 0x1C21A0CA, 0x0D4A4000, 0x2A97008F, 0x0E262000, ++ 0x1ED40079, 0x3F424000, 0x032D0100, 0x092CFFFF, ++ 0x13CC004D, 0x2E60B42C, 0x2560B42E, 0x2E800027, ++ 0x2A97008F, 0x1721A0C8, 0x19220000, 0x3F424000, ++ 0x122D0002, 0x3F424000, 0x182D00FE, 0x092CFFFF, ++ 0x05CC0057, 0x1A223000, 0x2F712049, 0x05B80064, ++ 0x33214000, 0x35230000, 0x3F222000, 0x3F800066, ++ 0x1A210000, 0x35230000, 0x1820B424, 0x19500011, ++ 0x0A500001, 0x1150C400, 0x0A500001, 0x0261B42C, ++ 0x2663B42E, 0x1C62B434, 0x39230333, 0x278C0078, ++ 0x2BBC0077, 0x3363B438, 0x36200000, 0x2B60B140, ++ 0x13710149, 0x398C0000, 0x20800075, 0x3371FF49, ++ 0x20800075, 0x2F71FD49, 0x20800075, 0x2A320001, ++ 0x0A367FFF, 0x21C8008E, 0x252A0008, 0x1EC0008A, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x21C8008E, 0x2280007E, 0x26260008, 0x0D500000, ++ 0x262EFFFF, 0x1ACC008B, 0x228B4000, 0x0868B1F8, ++ 0x3C34000F, 0x0128000A, 0x33C40095, 0x0224000A, ++ 0x228B4000, 0x3320000A, 0x228B4000, 0x01000000, ++ 0x01000000, 0x01000000 ++}; ++ ++static const uint32_t fw2_master_img_data_buf[] = ++{ ++ 0x36200000, 0x16210003, 0x3C605FF4, 0x1B615FF6, ++ 0x36200000, 0x2560B148, 0x1A205FE0, 0x38215FE8, ++ 0x3B230008, 0x1F090000, 0x10C0010E, 0x31200001, ++ 0x2860B41C, 0x2A9700B9, 0x329700C7, 0x1C208000, ++ 0x2B60B140, 0x01000000, 0x19220000, 0x0B685FFE, ++ 0x2469B1F8, 0x2B3C4600, 0x1ECC0013, 0x1D2E0001, ++ 0x28038000, 0x01000000, 0x0A2FFFFF, 0x1BCC0019, ++ 0x0B685FFE, 0x2469B1F8, 0x2B3C4600, 0x22C80021, ++ 0x25800013, 0x056B5FFA, 0x333B0000, 0x14D40026, ++ 0x363700FF, 0x2E63B47A, 0x3A200333, 0x3060B438, ++ 0x3E60B45C, 0x3D60B43C, 0x39230003, 0x2F22B400, ++ 0x0A20FFFF, 0x13408000, 0x1A210000, 0x21488000, ++ 0x23260002, 0x3F418000, 0x1234FEFE, 0x05300001, ++ 0x202A0002, 0x13408000, 0x3D260020, 0x0A2FFFFF, ++ 0x17CC002C, 0x36200000, 0x3E60B406, 0x2D60B416, ++ 0x2B60B426, 0x3860B436, 0x2860B446, 0x3B60B456, ++ 0x036B5FFC, 0x00210100, 0x05222F00, 0x29370080, ++ 0x27C80047, 0x1A210000, 0x1A223000, 0x1820B424, ++ 0x19500011, 0x0A500001, 0x1150C400, 0x0A500001, ++ 0x15410000, 0x3E2C0002, 0x0D500000, 0x1C62B434, ++ 0x10205E90, 0x0D220164, 0x0F970FF0, 0x2469B1F8, ++ 0x15220333, 0x36200000, 0x278C0078, 0x26BC0106, ++ 0x1F62B438, 0x2060B424, 0x2B60B426, 0x33610102, ++ 0x1035000F, 0x38610100, 0x0A68B400, 0x3369B420, ++ 0x32605FCA, 0x13615FCE, 0x353400FF, 0x2C380200, ++ 0x34605FCC, 0x2535FF00, 0x17390002, 0x08615FD0, ++ 0x12970F7D, 0x31200001, 0x2E605EA0, 0x202001A0, ++ 0x1760010C, 0x35203000, 0x1C60010E, 0x31200001, ++ 0x2560B148, 0x30695EA0, 0x33228000, 0x28004000, ++ 0x063C0001, 0x1FCC0078, 0x0462B140, 0x2280007E, ++ 0x28004000, 0x0C3C0004, 0x19CC007E, 0x1968B140, ++ 0x283C4000, 0x2B60B140, 0x1035000F, 0x1231FFFF, ++ 0x0B2D0082, 0x0D894000, 0x248C1D78, 0x318000A1, ++ 0x2F8C1D7A, 0x318000A1, 0x3D8C1DF8, 0x318000A1, ++ 0x368C1DFA, 0x318000A1, 0x298C1D7C, 0x318000A1, ++ 0x228C1D7E, 0x318000A1, 0x308C1DFC, 0x318000A1, ++ 0x3B8C1DFE, 0x318000A1, 0x238C1D79, 0x318000A1, ++ 0x288C1D7B, 0x318000A1, 0x3A8C1DF9, 0x318000A1, ++ 0x318C1DFB, 0x318000A1, 0x2E8C1D7D, 0x318000A1, ++ 0x258C1D7F, 0x318000A1, 0x378C1DFD, 0x318000A1, ++ 0x3C8C1DFF, 0x2EB00104, 0x05BC0C60, 0x33D80D2D, ++ 0x35A00C61, 0x18A40C87, 0x04A80CA2, 0x08F80F6B, ++ 0x35E80D4B, 0x31E00122, 0x336A5EA0, 0x362300AF, ++ 0x17360002, 0x33C800AF, 0x21AC0EF6, 0x31215EA2, ++ 0x07220014, 0x1D97100D, 0x27C80071, 0x21884000, ++ 0x30380000, 0x3AC8011C, 0x31215EA2, 0x07220014, ++ 0x19801030, 0x36200000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x36200000, 0x2760B000, ++ 0x2960B008, 0x1E220001, 0x1B62B010, 0x3760B01C, ++ 0x10228800, 0x1862B01C, 0x228B4000, 0x0868B1F8, ++ 0x2D635E96, 0x3C34000F, 0x02030000, 0x022B000A, ++ 0x05C000CE, 0x3320000A, 0x02030000, 0x1A210000, ++ 0x1231FFFF, 0x1B390001, 0x092CFFFF, 0x1DCC00D0, ++ 0x0761B140, 0x33228000, 0x2D010000, 0x20310008, ++ 0x1A39A0CA, 0x3F424000, 0x19220000, 0x3F424000, ++ 0x0C220020, 0x392DFFBA, 0x3F424000, 0x3860B150, ++ 0x022D0044, 0x28200014, 0x0D4A4000, 0x092CFFFF, ++ 0x2BC800E7, 0x06360100, 0x21C800E2, 0x28004000, ++ 0x0C300008, 0x3C34000F, 0x1A22C000, 0x22520000, ++ 0x22520000, 0x19220000, 0x2B2DFF38, 0x3F424000, ++ 0x172D0008, 0x3F424000, 0x1E220001, 0x172D0008, ++ 0x3F424000, 0x19220000, 0x1A2D000C, 0x3F424000, ++ 0x10228800, 0x3F424000, 0x06220400, 0x0962B144, ++ 0x2E020000, 0x033A0200, 0x0962B144, 0x322C0001, ++ 0x0A2FFFFF, 0x17CC00D5, 0x1F6B5E96, 0x228B4000, ++ 0x0422008D, 0x32800117, 0x09220089, 0x32800117, ++ 0x0C220083, 0x32800117, 0x0A220085, 0x32800117, ++ 0x13220005, 0x32800117, 0x01220087, 0x32800117, ++ 0x18220007, 0x32800117, 0x0D220011, 0x32800117, ++ 0x0222008B, 0x32800117, 0x1B22000B, 0x15625FF2, ++ 0x32635FF0, 0x23320008, 0x0A62B148, 0x3BD0011D, ++ 0x228B4000, 0x31200001, 0x2A9700B9, 0x329700C7, ++ 0x398C0000, 0x35800120, 0x33695F20, 0x2C200136, ++ 0x1C35C000, 0x36C80129, 0x12685F24, 0x043D4000, ++ 0x08CC00AA, 0x3C2300AA, 0x336A5EA0, 0x03210080, ++ 0x2736FFFE, 0x01625EA0, 0x37655F21, 0x288000B4, ++ 0x33695F20, 0x12685F24, 0x1C35C000, 0x2E3DC000, ++ 0x3AC8012A, 0x228B4000, 0x0C970F90, 0x30C801D6, ++ 0x20605F24, 0x00685FFC, 0x1A210000, 0x09615F2E, ++ 0x3F340003, 0x372C0148, 0x21884000, 0x36200000, ++ 0x2360B122, 0x3580014C, 0x146BB124, 0x38695F22, ++ 0x36200000, 0x37370001, 0x15CC0152, 0x3965B123, ++ 0x3580014C, 0x2980013F, 0x3D800142, 0x33970116, ++ 0x1168B122, 0x3B69B124, 0x2F34001F, 0x29310001, ++ 0x19110000, 0x11D401CC, 0x036B5FFC, 0x1C645F20, ++ 0x0A37FF00, 0x0F330008, 0x300B0000, 0x1EC001C9, ++ 0x3D6A5F24, 0x3F215F26, 0x0C2E0040, 0x13408000, ++ 0x3330FFFB, 0x1C2C4000, 0x0B97104D, 0x35695F26, ++ 0x362C000C, 0x13350003, 0x1ECC01C5, 0x3F215F26, ++ 0x2222FFFE, 0x16971063, 0x3E695F24, 0x382C0004, ++ 0x244A0000, 0x042D0042, 0x3F424000, 0x1D2E0001, ++ 0x16420000, 0x12971097, 0x1B970CBD, 0x19685F26, ++ 0x3D695F28, 0x3660B408, 0x1161B40A, 0x12685F24, ++ 0x2421B40E, 0x3B60B40C, 0x21510000, 0x24200021, ++ 0x3560B404, 0x20200040, 0x2660B414, 0x3320017F, ++ 0x0721016D, 0x362300AF, 0x11800CE4, 0x1F685F20, ++ 0x316A5FE8, 0x353400FF, 0x26605F22, 0x1D2E0001, ++ 0x03625FE8, 0x02030000, 0x3330FFFB, 0x0F2C4010, ++ 0x244A0000, 0x382C0004, 0x27490000, 0x2C3B0400, ++ 0x1E2D0001, 0x350A4000, 0x23C40190, 0x1A210000, ++ 0x15410000, 0x12685F24, 0x2B63B120, 0x3D2C0038, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x002CFFF6, 0x244A0000, 0x052CFFCA, 0x146B5F2E, ++ 0x36368000, 0x1DCC01A5, 0x333B0000, 0x22C801C1, ++ 0x332F003C, 0x3A40C000, 0x0C685F30, 0x20605F24, ++ 0x288001C1, 0x25605F2E, 0x333B0000, 0x12CC01AA, ++ 0x3E605F30, 0x2F8001AC, 0x332F003C, 0x3A40C000, ++ 0x33695F20, 0x1768B124, 0x1E220001, 0x35230000, ++ 0x193500FF, 0x190B4000, 0x1912C000, 0x2E148000, ++ 0x01CC01BA, 0x3E970112, 0x202301AC, 0x23635F24, ++ 0x20200040, 0x208001CF, 0x0C970F90, 0x3BC801D4, ++ 0x20605F24, 0x1F685F20, 0x3D6A5F24, 0x353400FF, ++ 0x2C800159, 0x35215FDA, 0x03970FA9, 0x282301CE, ++ 0x3E8001DB, 0x1F685F20, 0x35970110, 0x353400FF, ++ 0x2A8001CA, 0x33970116, 0x2F380400, 0x2860B120, ++ 0x12685F24, 0x06970FA3, 0x36200000, 0x336A5EA0, ++ 0x1B645F21, 0x183A0001, 0x01625EA0, 0x398000AF, ++ 0x352301BA, 0x3D8001D7, 0x2F230136, 0x23635F24, ++ 0x392000C0, 0x1B645F21, 0x398000AF, 0x2B695F32, ++ 0x1C208000, 0x28150000, 0x30C801E0, 0x228B4000, ++ 0x35605F32, 0x3A2001E3, 0x288000B4, 0x18685FD8, ++ 0x3E215FD8, 0x30380000, 0x22C80208, 0x0B970FCB, ++ 0x33605F34, 0x2D010000, 0x3E2C0034, 0x0B480000, ++ 0x3C6A5FEC, 0x02030000, 0x3C34000F, 0x1D2E0001, ++ 0x0E625FEC, 0x19220000, 0x14625F3A, 0x3562013E, ++ 0x0C330004, 0x3F37000F, 0x2B2F01F8, 0x228B4000, ++ 0x2C8003D3, 0x3E80055D, 0x2A80073F, 0x3A80074F, ++ 0x3780021B, 0x3780021B, 0x3780021B, 0x3780021B, ++ 0x3780021B, 0x3780021B, 0x3780021B, 0x3780021B, ++ 0x3780021B, 0x3780021B, 0x00800C30, 0x3780021B, ++ 0x33605F34, 0x35605F32, 0x398000AF, 0x112200C1, ++ 0x3D80021E, 0x192200A3, 0x3D80021E, 0x0F22008F, ++ 0x3D80021E, 0x0A220085, 0x3D80021E, 0x162200C0, ++ 0x3D80021E, 0x152200A0, 0x3D80021E, 0x122200A1, ++ 0x3D80021E, 0x07220081, 0x3D80021E, 0x01220087, ++ 0x3D80021E, 0x19220000, 0x07685F32, 0x1F625F38, ++ 0x30230223, 0x16341000, 0x00CC02BB, 0x2997037C, ++ 0x01685F34, 0x2D6A5F38, 0x23230233, 0x392C0035, ++ 0x27460000, 0x2D695F34, 0x3780028E, 0x1160013C, ++ 0x2B635F46, 0x2997037C, 0x2C200230, 0x38605F36, ++ 0x229703B1, 0x05CC027E, 0x22970251, 0x0A6A010C, ++ 0x35680110, 0x3D2A01A0, 0x3CC801E3, 0x30380000, ++ 0x0DCC01E3, 0x28620110, 0x0B970CCD, 0x1A6A0110, ++ 0x1820B424, 0x19500011, 0x0A500001, 0x1150C400, ++ 0x0A500001, 0x1B5001A0, 0x0D500000, 0x1C62B434, ++ 0x11210247, 0x392301E3, 0x18940CE7, 0x3D6B0112, ++ 0x0F2201A0, 0x3862010C, 0x36200000, 0x1A6A0110, ++ 0x0C600112, 0x07600110, 0x333B0000, 0x07CC03A3, ++ 0x398000AF, 0x33635F38, 0x011A4000, 0x0462B140, ++ 0x1F6B5EA0, 0x2E020000, 0x3E3B0004, 0x2D635EA0, ++ 0x1A388000, 0x35605F32, 0x2B008000, 0x0E300003, ++ 0x2B605F4A, 0x2B008000, 0x3F30FFF8, 0x1E384001, ++ 0x2D605F4C, 0x1132FFFF, 0x2C2E0D70, 0x20230265, ++ 0x0E8A4000, 0x26605F4E, 0x0A6A010C, 0x202001A0, ++ 0x1A210000, 0x1C0A0000, 0x14970E54, 0x07970E72, ++ 0x046B5F32, 0x14685F4E, 0x3F37000F, 0x293B0100, ++ 0x2E6A5F34, 0x2563B144, 0x16420000, 0x36695F46, ++ 0x3E2C0002, 0x15410000, 0x266A5F3A, 0x3E2C0002, ++ 0x16420000, 0x23695F3C, 0x016B5F38, 0x3E2C0002, ++ 0x15410000, 0x228B4000, 0x3520C000, 0x35605F32, ++ 0x14970CDE, 0x0F220040, 0x1820B424, 0x19500011, ++ 0x01500003, 0x1150C400, 0x0A500001, 0x0E500180, ++ 0x0D500000, 0x1C62B434, 0x352000AF, 0x192100AF, ++ 0x362300AF, 0x1D800CE7, 0x28635E9C, 0x1B6B5FEE, ++ 0x0A615E98, 0x192D0036, 0x22484000, 0x312F0001, ++ 0x29635FEE, 0x00349FFF, 0x10404000, 0x19348000, ++ 0x27C802A1, 0x222DFFFE, 0x0D4A4000, 0x172D0008, ++ 0x22484000, 0x02625E9A, 0x21510000, 0x30380000, ++ 0x32C802B7, 0x20605E9E, 0x14685E98, 0x33215FDC, ++ 0x1C970FBA, 0x13970EF6, 0x12685E9E, 0x1A6B5E9C, ++ 0x30380000, 0x13CC02AB, 0x228B4000, 0x306A5E9A, ++ 0x3E215FD8, 0x2636FF00, 0x3ED002B2, 0x1C970FBA, ++ 0x1A6B5E9C, 0x3E8001DB, 0x23320008, 0x392C0035, ++ 0x27460000, 0x3E695E9E, 0x3080028F, 0x2E97010E, ++ 0x39209000, 0x35605F32, 0x0280108D, 0x1C208000, ++ 0x35605F32, 0x1680109C, 0x19685F4A, 0x33695F4C, ++ 0x1632FFFE, 0x1A048000, 0x19220000, 0x29058400, ++ 0x2B605F4A, 0x01615F4C, 0x228B4000, 0x3B635F36, ++ 0x0A625E94, 0x379702BE, 0x386A5E94, 0x09685F3A, ++ 0x3B8002D7, 0x3B635F36, 0x30380000, 0x31D002D1, ++ 0x21970372, 0x09685F3A, 0x1C390000, 0x31C802D7, ++ 0x09300002, 0x10404000, 0x3930FFFE, 0x2D010000, ++ 0x0F2D01A0, 0x3E610106, 0x1632FFFE, 0x26C80370, ++ 0x28038000, 0x06330001, 0x01D402E0, 0x172E0004, ++ 0x280C8000, 0x3B605F3A, 0x28038000, 0x3F37000F, ++ 0x37C802E7, 0x2F36FFF0, 0x092E0010, 0x1F6B5F40, ++ 0x19625F3E, 0x1A0B8000, 0x36C402EC, 0x01625F40, ++ 0x386A5F42, 0x36200000, 0x133600C0, 0x2B320006, ++ 0x28C802F4, 0x232C0040, 0x262EFFFF, 0x2F8002F0, ++ 0x19600104, 0x09970D10, 0x352000AF, 0x00970D19, ++ 0x0F970D20, 0x0B970CCD, 0x07690104, 0x2B680104, ++ 0x1F2D0030, 0x0D4A4000, 0x122D0002, 0x214B4000, ++ 0x123EFFFF, 0x1A1EC000, 0x11CC0340, 0x3421B424, ++ 0x30510041, 0x2360B428, 0x142D0004, 0x21510000, ++ 0x3151C010, 0x26510001, 0x11220038, 0x1C62B434, ++ 0x062102F9, 0x362300AF, 0x18940CE7, 0x3320003C, ++ 0x3960B348, 0x1B970CBD, 0x0B970CCD, 0x20680106, ++ 0x3721B428, 0x2B6A5F3E, 0x156B5FD0, 0x0451E000, ++ 0x26510001, 0x2E60B42C, 0x122D0002, 0x21510000, ++ 0x24200311, 0x2E63B420, 0x2060B424, 0x1C62B434, ++ 0x19685F4A, 0x33695F4C, 0x3660B408, 0x1161B40A, ++ 0x056B5FCC, 0x2F21B40C, 0x0451E000, 0x26510001, ++ 0x17201061, 0x3B63B400, 0x3560B404, 0x0962B414, ++ 0x3A200003, 0x3D605F50, 0x3F200339, 0x06210343, ++ 0x1B970CE7, 0x362300AF, 0x14940CE4, 0x0F685F50, ++ 0x0834FFFE, 0x3D605F50, 0x30380000, 0x38C8033E, ++ 0x398000AF, 0x0F685F50, 0x0434FFFD, 0x3D605F50, ++ 0x30380000, 0x02CC00AF, 0x096B5F36, 0x08800D27, ++ 0x1E970CED, 0x2D23020D, 0x08800D27, 0x292302F9, ++ 0x18800CED, 0x3B635F36, 0x30380000, 0x2FD00349, ++ 0x21970372, 0x09685F3A, 0x1C390000, 0x2FC8034F, ++ 0x09300002, 0x10404000, 0x3930FFFE, 0x2D010000, ++ 0x0F2D01A0, 0x3E610106, 0x1632FFFE, 0x26C80370, ++ 0x1F6B5F40, 0x19625F3E, 0x1A0B8000, 0x39C40359, ++ 0x01625F40, 0x28038000, 0x0D330003, 0x00D4035D, ++ 0x172E0004, 0x280C8000, 0x3B605F3A, 0x1B970CBD, ++ 0x19685F4A, 0x33695F4C, 0x3660B408, 0x1161B40A, ++ 0x20680106, 0x2B6A5F3E, 0x2421B40E, 0x21510000, ++ 0x3B60B40C, 0x24200021, 0x3560B404, 0x0962B414, ++ 0x0A685F36, 0x1621035F, 0x362300AF, 0x11800CE4, ++ 0x096B5F36, 0x35800116, 0x2B635E90, 0x026B5F34, ++ 0x010CC000, 0x084B0000, 0x3E2C0002, 0x0B480000, ++ 0x28635F4A, 0x196B5E90, 0x2D605F4C, 0x228B4000, ++ 0x336A5F40, 0x36200000, 0x2E605F40, 0x1F3A0000, ++ 0x3BCC0CFF, 0x228B4000, 0x0A20FFFF, 0x192D0036, ++ 0x0D4A4000, 0x2F2DFFFA, 0x0A625F42, 0x3A34003F, ++ 0x2E148000, 0x19CC020D, 0x228B4000, 0x0D4A4000, ++ 0x122D0002, 0x0F3607FC, 0x23C8020F, 0x26320002, ++ 0x19088000, 0x11C0020F, 0x2B008000, 0x05300001, ++ 0x0DD40396, 0x1D2E0001, 0x3E30FFFF, 0x228B4000, ++ 0x2D635E96, 0x27200102, 0x2197038B, 0x12600130, ++ 0x0C625F44, 0x27200102, 0x2197038B, 0x1F6B5E96, ++ 0x1F600134, 0x07625F46, 0x228B4000, 0x0969010C, ++ 0x2E68010E, 0x3B3D01A0, 0x03CC03AE, 0x0C2E01A0, ++ 0x3862010C, 0x30380000, 0x3EC803AD, 0x19088000, ++ 0x1CC0020B, 0x228B4000, 0x28620110, 0x0F630112, ++ 0x398000AF, 0x26680100, 0x2D635E96, 0x366AB140, ++ 0x1D210001, 0x35230000, 0x03280001, 0x300B0000, ++ 0x1A11C000, 0x28038000, 0x2E174000, 0x26C803BF, ++ 0x29310001, 0x03280001, 0x23C403B9, 0x1F6B5E96, ++ 0x228B4000, 0x2D635E96, 0x19220000, 0x0A625E94, ++ 0x1A6BB140, 0x0A690100, 0x31200001, 0x2D02C000, ++ 0x2B160000, 0x386A5E94, 0x0CCC03CD, 0x1D2E0001, ++ 0x0A625E94, 0x3E30FFFF, 0x252DFFFF, 0x09CC03C7, ++ 0x1F6B5E96, 0x386A5E94, 0x228B4000, 0x09625F4E, ++ 0x292C03D6, 0x21884000, 0x3780021B, 0x208003E6, ++ 0x26800460, 0x2A800463, 0x30800483, 0x248004A4, ++ 0x36800509, 0x3C80050C, 0x2B800527, 0x2F80052A, ++ 0x27800548, 0x3780021B, 0x3780021B, 0x3780021B, ++ 0x3780021B, 0x3780021B, 0x28230018, 0x1263013C, ++ 0x28970382, 0x3E970398, 0x0F6A0130, 0x02030000, ++ 0x1A0B8000, 0x11C003EF, 0x2E020000, 0x206B013C, ++ 0x11685F44, 0x36695F46, 0x25370020, 0x04CC03F5, ++ 0x1D2E0001, 0x12625F3C, 0x2D0E0000, 0x040E4000, ++ 0x1632FFFE, 0x3A9703A3, 0x319702B8, 0x36200000, ++ 0x15210120, 0x3E6A5F44, 0x26970345, 0x38200008, ++ 0x18210124, 0x356A5F46, 0x26970345, 0x3D9702BB, ++ 0x09685F3A, 0x09210010, 0x09300002, 0x0F600128, ++ 0x35610104, 0x2997037C, 0x16970D35, 0x20680130, ++ 0x01690134, 0x1C6A0120, 0x3D6B0124, 0x3460B010, ++ 0x1561B014, 0x3D680128, 0x1C69012C, 0x172E0068, ++ 0x0862B000, 0x3B2F0068, 0x2963B004, 0x016A0138, ++ 0x382C0068, 0x2960B008, 0x142D0068, 0x0861B00C, ++ 0x1562B018, 0x2368013C, 0x362300AF, 0x1A388000, ++ 0x3760B01C, 0x1A940D3A, 0x14685F4E, 0x2E6A5F34, ++ 0x30380000, 0x38C8042B, 0x21884000, 0x1C208000, ++ 0x13408000, 0x36200000, 0x22800437, 0x09685F3A, ++ 0x2169B024, 0x012E0028, 0x1C390000, 0x3DD00427, ++ 0x09300002, 0x382C0068, 0x1F090000, 0x1531FFFE, ++ 0x0E68B028, 0x3F418000, 0x2F34001F, 0x112E0002, ++ 0x13408000, 0x2B008000, 0x3E2C0002, 0x0D500000, ++ 0x0D500000, 0x07970D42, 0x206A5F3C, 0x01685F34, ++ 0x1632FFFE, 0x3BC8021D, 0x286B0104, 0x25695F3A, ++ 0x12625F3C, 0x01625F40, 0x010CC000, 0x0F2D01A0, ++ 0x35610104, 0x27490000, 0x3E2C0002, 0x0B480000, ++ 0x07615F4A, 0x2D605F4C, 0x1B970CBD, 0x19685F4A, ++ 0x33695F4C, 0x3B60B40C, 0x1C61B40E, 0x2B680104, ++ 0x1A210000, 0x1161B40A, 0x3660B408, 0x206A5F3C, ++ 0x28200081, 0x3560B404, 0x0962B414, 0x1B21044E, ++ 0x362300AF, 0x14940CE4, 0x3E23021D, 0x2F80037C, ++ 0x2E230028, 0x1263013C, 0x288003E8, 0x28970382, ++ 0x27200102, 0x2197038B, 0x12600130, 0x0C625F44, ++ 0x322C0001, 0x3D605F3C, 0x1D32FFFC, 0x172E0004, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x26970345, 0x3E6A5F44, 0x38200008, ++ 0x18210124, 0x26970345, 0x3E6A5F44, 0x25200010, ++ 0x1B210128, 0x26970345, 0x3D9702BB, 0x09685F3A, ++ 0x07210018, 0x09300002, 0x0260012C, 0x35610104, ++ 0x3023000A, 0x1263013C, 0x2C800409, 0x28970382, ++ 0x3E970398, 0x11685F44, 0x2D0E0000, 0x1632FFFE, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x26970345, 0x356A5F46, 0x38200008, ++ 0x18210124, 0x26970345, 0x3D9702BB, 0x09685F3A, ++ 0x0F6A0130, 0x2E6B0134, 0x09300002, 0x0F600128, ++ 0x2E0EC000, 0x1632FFFE, 0x12625F3C, 0x15208009, ++ 0x3797022B, 0x0E970DE8, 0x3E680148, 0x0A970EB9, ++ 0x1A210000, 0x236A5F5C, 0x25200010, 0x00800ED6, ++ 0x06208100, 0x1160013C, 0x28970382, 0x3E970398, ++ 0x236B0130, 0x3D695F44, 0x300B0000, 0x11C0020F, ++ 0x0834FFFE, 0x23C8020F, 0x040E4000, 0x1632FFFE, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x26970345, 0x356A5F46, 0x38200008, ++ 0x18210124, 0x26970345, 0x3D9702BB, 0x026A0134, ++ 0x12690124, 0x262EFFFF, 0x040D8000, 0x1531FFFE, ++ 0x0F2D01A0, 0x0D4A4000, 0x122D0002, 0x0E494000, ++ 0x2368013C, 0x011A4000, 0x35C80215, 0x25695F3A, ++ 0x026A0134, 0x25310002, 0x23610128, 0x29340100, ++ 0x3DC804D8, 0x236B0130, 0x2B008000, 0x1A0B8000, ++ 0x312F0001, 0x1D2E0001, 0x05300001, 0x3FD004D5, ++ 0x1D2E0001, 0x040D8000, 0x2E61012C, 0x2E0EC000, ++ 0x1632FFFE, 0x12625F3C, 0x2368013C, 0x3797022B, ++ 0x0E970DE8, 0x0C69015C, 0x3368014C, 0x05350100, ++ 0x3EC80502, 0x0A970EB9, 0x22520000, 0x172E0004, ++ 0x07690168, 0x3E680148, 0x1C390000, 0x31D004EB, ++ 0x1F090000, 0x1531FFFE, 0x3C8004EC, 0x30218000, ++ 0x04685F52, 0x2A2EFFFC, 0x3F418000, 0x15381000, ++ 0x36605F52, 0x0497108D, 0x016A0154, 0x2068015C, ++ 0x1A210000, 0x1632FFFE, 0x29340100, 0x25200010, ++ 0x32C80501, 0x01970ED7, 0x3E680148, 0x1F69014C, ++ 0x236A5F5C, 0x1F090000, 0x1531FFFE, 0x350A4000, ++ 0x2B200018, 0x00800ED6, 0x2E6A5F58, 0x012E0028, ++ 0x22520000, 0x22520000, 0x22520000, 0x22520000, ++ 0x328004E4, 0x00208200, 0x1160013C, 0x2F8004A6, ++ 0x21200088, 0x1160013C, 0x28970382, 0x03361F00, ++ 0x23320008, 0x33620138, 0x27200102, 0x2197038B, ++ 0x12600130, 0x2D6B0138, 0x0C625F44, 0x333B0000, ++ 0x206B013C, 0x15CC051B, 0x2480051E, 0x26370040, ++ 0x1FCC051E, 0x322C0001, 0x3D605F3C, 0x2D0E0000, ++ 0x1632FFFE, 0x3A9703A3, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x27230404, 0x20800345, 0x2E200048, ++ 0x1160013C, 0x3780050E, 0x28970382, 0x27200102, ++ 0x2197038B, 0x12600130, 0x0C625F44, 0x1A32FFFD, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x26970345, 0x3E6A5F44, 0x38200008, ++ 0x18210124, 0x26970345, 0x3D9702BB, 0x25200540, ++ 0x26605F4E, 0x2A230400, 0x1263013C, 0x2C800409, ++ 0x2C69B020, 0x012E0028, 0x22520000, 0x22520000, ++ 0x22520000, 0x3F418000, 0x3E23021D, 0x01800D42, ++ 0x28970382, 0x2A2001FF, 0x2197038B, 0x12600130, ++ 0x3D605F3C, 0x2E020000, 0x0C625F44, 0x1632FFFE, ++ 0x3A9703A3, 0x36200000, 0x15210120, 0x3E6A5F44, ++ 0x26970345, 0x36200000, 0x3B605F3A, 0x0F600128, ++ 0x09210010, 0x35610104, 0x18230808, 0x1263013C, ++ 0x2C800409, 0x02030000, 0x0D37FFF8, 0x0CCC021B, ++ 0x382C0562, 0x21884000, 0x3980056A, 0x208005B0, ++ 0x2580061F, 0x31800638, 0x2680067F, 0x268006B0, ++ 0x3780021B, 0x3780021B, 0x0620FFFC, 0x2F970383, ++ 0x03361F00, 0x23320008, 0x33620138, 0x3F2A0011, ++ 0x3BC40211, 0x3E970398, 0x05300001, 0x29D00575, ++ 0x112E0002, 0x25347FFF, 0x23C8020F, 0x2E680138, ++ 0x07625F46, 0x322C0001, 0x08280003, 0x22C4057D, ++ 0x36200000, 0x0D240005, 0x07018000, 0x15072000, ++ 0x333B0000, 0x02CC0213, 0x3D695F44, 0x092E0010, ++ 0x040E4000, 0x082A0800, 0x356A5F46, 0x30C40213, ++ 0x1132FFFF, 0x040E4000, 0x1632FFFE, 0x3A9703A3, ++ 0x319702B8, 0x36200000, 0x15210120, 0x146B5F42, ++ 0x3E6A5F44, 0x06330001, 0x33D00595, 0x3C230596, ++ 0x20800345, 0x2B9702CD, 0x146B5F42, 0x38200008, ++ 0x18210124, 0x356A5F46, 0x0A330002, 0x31D0059E, ++ 0x3523059F, 0x20800345, 0x2B9702CD, 0x0A6B5F3A, ++ 0x356A5F46, 0x1B210128, 0x2B635F46, 0x25200010, ++ 0x26970345, 0x3D9702BB, 0x196B5F46, 0x3D680128, ++ 0x026A0134, 0x0260012C, 0x1632FFFE, 0x38635F3A, ++ 0x12625F3C, 0x1320E000, 0x2B230618, 0x3180022B, ++ 0x0B20FFF8, 0x2F970383, 0x03361F00, 0x23320008, ++ 0x33620138, 0x3F2A0011, 0x3BC40211, 0x24200082, ++ 0x2197038B, 0x12600130, 0x0C625F44, 0x24200082, ++ 0x2197038B, 0x1F600134, 0x05300001, 0x3BD005C1, ++ 0x112E0002, 0x25347FFF, 0x23C8020F, 0x2E680138, ++ 0x07625F46, 0x3E2C0002, 0x09280004, 0x30C405C9, ++ 0x36200000, 0x3C2C0009, 0x07018000, 0x15072000, ++ 0x333B0000, 0x02CC0213, 0x3D695F44, 0x2D680134, ++ 0x092E0010, 0x1231FFFF, 0x082A0800, 0x30C40213, ++ 0x2E020000, 0x1632FFFE, 0x2D0E0000, 0x040E4000, ++ 0x102E0005, 0x1632FFFE, 0x3A9703A3, 0x319702B8, ++ 0x36200000, 0x15210120, 0x146B5F42, 0x3E6A5F44, ++ 0x06330001, 0x23D005E5, 0x1132FFFF, 0x242305E8, ++ 0x20800345, 0x2B9702CD, 0x3E6A5F44, 0x2E9702C7, ++ 0x146B5F42, 0x38200008, 0x18210124, 0x356A5F46, ++ 0x0A330002, 0x3DD005F1, 0x1132FFFF, 0x342305F4, ++ 0x20800345, 0x2B9702CD, 0x356A5F46, 0x2E9702C7, ++ 0x12690124, 0x356A5F46, 0x1531FFFE, 0x0F2D01A0, ++ 0x22484000, 0x1632FFFE, 0x040D8000, 0x214B4000, ++ 0x34340001, 0x36C80219, 0x37370001, 0x36C80219, ++ 0x026A0134, 0x25200010, 0x146B5F42, 0x1B210128, ++ 0x0D330003, 0x3BD00608, 0x3F230609, 0x20800345, ++ 0x2B9702CD, 0x09685F3A, 0x026A0134, 0x26605F4E, ++ 0x2D200028, 0x1621012C, 0x1132FFFF, 0x26970345, ++ 0x3D9702BB, 0x14685F4E, 0x026A0134, 0x3B605F3A, ++ 0x39209000, 0x1A32FFFD, 0x12625F3C, 0x3797022B, ++ 0x0E970DE8, 0x3368014C, 0x0A970EB9, 0x1A210000, ++ 0x236A5F5C, 0x2B200018, 0x00800ED6, 0x28970382, ++ 0x3E970398, 0x126B5F44, 0x2E0EC000, 0x1632FFFE, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x3E6A5F44, 0x26970345, 0x38200008, 0x18210124, ++ 0x356A5F46, 0x26970345, 0x3D9702BB, 0x0A6B5F3A, ++ 0x026A0134, 0x0A330002, 0x0163012C, 0x1632FFFE, ++ 0x12625F3C, 0x3620F000, 0x2B230618, 0x3180022B, ++ 0x0B20FFF8, 0x2F970383, 0x0A625F42, 0x2B200018, ++ 0x2197038B, 0x12600130, 0x0C625F44, 0x2B200018, ++ 0x2197038B, 0x1F600134, 0x0834FFFE, 0x23C8020F, ++ 0x112E0002, 0x07625F46, 0x3A20A000, 0x1160013C, ++ 0x3D695F44, 0x28038000, 0x070E8000, 0x2E0EC000, ++ 0x040E4000, 0x1632FFFE, 0x3A9703A3, 0x319702B8, ++ 0x36200000, 0x15210120, 0x146B5F42, 0x3E6A5F44, ++ 0x06330001, 0x3ED00658, 0x3A230659, 0x20800345, ++ 0x2B9702CD, 0x146B5F42, 0x356A5F46, 0x38200008, ++ 0x0A330002, 0x3DD00662, 0x1132FFFF, 0x18210124, ++ 0x33230666, 0x20800345, 0x18210124, 0x2B9702CD, ++ 0x356A5F46, 0x2E9702C7, 0x25200010, 0x1B210128, ++ 0x146B5F42, 0x356A5F46, 0x0D330003, 0x3ED0066E, ++ 0x3A23066F, 0x20800345, 0x2B9702CD, 0x3D9702BB, ++ 0x09685F3A, 0x356A5F46, 0x1632FFFE, 0x12625F3C, ++ 0x09300002, 0x0260012C, 0x2368013C, 0x3797022B, ++ 0x0E970DE8, 0x3368014C, 0x0A970EB9, 0x1A210000, ++ 0x236A5F5C, 0x2B200018, 0x00800ED6, 0x0C20FFF9, ++ 0x2F970383, 0x0A625F42, 0x122D0002, 0x2B200018, ++ 0x2197038B, 0x1F600134, 0x0834FFFE, 0x23C8020F, ++ 0x112E0002, 0x07625F46, 0x2920013C, 0x27508000, ++ 0x0A500001, 0x23290002, 0x22484000, 0x28038000, ++ 0x1A32FFFD, 0x2E0EC000, 0x3F340003, 0x20605F48, ++ 0x1632FFFE, 0x3A9703A3, 0x319702B8, 0x356A5F46, ++ 0x116B5F48, 0x2B008000, 0x1132FFFF, 0x37370001, ++ 0x31C8069E, 0x2D0E0000, 0x15210120, 0x36200000, ++ 0x26970345, 0x116B5F48, 0x356A5F46, 0x37370001, ++ 0x1FCC06D7, 0x2B2306D7, 0x09685F3A, 0x2E01C000, ++ 0x232C01A0, 0x0A500001, 0x1632FFFE, 0x202A0002, ++ 0x0F970FF0, 0x122801A0, 0x3B605F3A, 0x0D894000, ++ 0x0B20FFF8, 0x2F970383, 0x0A625F42, 0x2B200018, ++ 0x2197038B, 0x12600130, 0x0C625F44, 0x2B200018, ++ 0x2197038B, 0x1F600134, 0x0834FFFE, 0x23C8020F, ++ 0x112E0002, 0x07625F46, 0x2920013C, 0x02509000, ++ 0x0A500001, 0x23290002, 0x22484000, 0x3D695F44, ++ 0x38340002, 0x20605F48, 0x1132FFFF, 0x28038000, ++ 0x2E0EC000, 0x2E0EC000, 0x040E4000, 0x1632FFFE, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x146B5F42, 0x3E6A5F44, 0x06330001, 0x2FD006D6, ++ 0x2B2306D7, 0x20800345, 0x2B9702CD, 0x146B5F42, ++ 0x356A5F46, 0x38200008, 0x0A330002, 0x24D006E2, ++ 0x07018000, 0x1132FFFF, 0x040E4000, 0x18210124, ++ 0x222306E8, 0x20800345, 0x18210124, 0x2B9702CD, ++ 0x356A5F46, 0x2E9702C7, 0x356A5F46, 0x2E9702C7, ++ 0x146B5F42, 0x356A5F46, 0x1B210128, 0x0D330003, ++ 0x20D0070F, 0x116B5F48, 0x2B008000, 0x1132FFFF, ++ 0x37370001, 0x36C806F3, 0x2D0E0000, 0x25200010, ++ 0x26970345, 0x116B5F48, 0x356A5F46, 0x37370001, ++ 0x05CC0718, 0x0F69013C, 0x01685F34, 0x356A5F46, ++ 0x223D9000, 0x1CCC070D, 0x2E2C0028, 0x084B0000, ++ 0x3E2C0002, 0x27490000, 0x3E2C0002, 0x2D1B4000, ++ 0x27490000, 0x3E2C0002, 0x2D1B4000, 0x27490000, ++ 0x2D200028, 0x2D1B4000, 0x2DC8070D, 0x31230718, ++ 0x20800345, 0x31230718, 0x338006A6, 0x25200010, ++ 0x2B9702CD, 0x356A5F46, 0x2E9702C7, 0x116B5F48, ++ 0x356A5F46, 0x37370001, 0x33C806F9, 0x2E9702C7, ++ 0x3D9702BB, 0x3D6A5F48, 0x09685F3A, 0x17360002, ++ 0x37C80722, 0x356A5F46, 0x01690134, 0x1132FFFF, ++ 0x040E4000, 0x1632FFFE, 0x12625F3C, 0x09300002, ++ 0x0260012C, 0x2368013C, 0x3797022B, 0x2D695F58, ++ 0x142D0032, 0x22484000, 0x38340002, 0x10CC0738, ++ 0x016A0154, 0x3A20A000, 0x28038000, 0x06330001, ++ 0x13D40732, 0x1D2E0001, 0x112E0002, 0x3D33FFFF, ++ 0x2E0EC000, 0x1632FFFE, 0x11625F5C, 0x0B970DD4, ++ 0x0E970DE8, 0x3368014C, 0x0A970EB9, 0x1A210000, ++ 0x236A5F5C, 0x2B200018, 0x00800ED6, 0x02030000, ++ 0x052B000B, 0x3EC4021B, 0x372C0744, 0x21884000, ++ 0x2B800754, 0x0D800811, 0x18800A18, 0x0B800AF1, ++ 0x3780021B, 0x0D800811, 0x3780021B, 0x0B800AF1, ++ 0x2D800752, 0x3780021B, 0x2A800753, 0x30380000, ++ 0x0CCC021B, 0x1C800C2F, 0x3780021B, 0x3780021B, ++ 0x0620FFFC, 0x2F970383, 0x122D0002, 0x2B200018, ++ 0x2197038B, 0x12600130, 0x1F600134, 0x0834FFFE, ++ 0x23C8020F, 0x112E0002, 0x23290002, 0x22484000, ++ 0x07625F46, 0x34340001, 0x20605F48, 0x2B008000, ++ 0x3530FFFD, 0x2D0E0000, 0x2D0E0000, 0x1632FFFE, ++ 0x3A9703A3, 0x319702B8, 0x36200000, 0x15210120, ++ 0x146B5F42, 0x356A5F46, 0x06330001, 0x34D00772, ++ 0x30230773, 0x20800345, 0x2B9702CD, 0x1E9709E7, ++ 0x356A5F46, 0x2D200028, 0x1A210000, 0x26970345, ++ 0x3D9702BB, 0x1A685F46, 0x36695F46, 0x3530FFFD, ++ 0x2B0C4000, 0x01600120, 0x1531FFFE, 0x20610124, ++ 0x026A0134, 0x3930FFFE, 0x232C01A0, 0x1132FFFF, ++ 0x1A210000, 0x084B0000, 0x3E2C0002, 0x2819C000, ++ 0x262EFFFF, 0x0BCC0785, 0x2435FFFE, 0x3EC80217, ++ 0x16970D35, 0x01690134, 0x1C6A0120, 0x3D6B0124, ++ 0x03208400, 0x172E0068, 0x3B2F0068, 0x1861B010, ++ 0x0862B000, 0x2963B004, 0x3760B01C, 0x362300AF, ++ 0x1A940D3A, 0x2C69B020, 0x25310002, 0x2DD0079E, ++ 0x07970D42, 0x34800217, 0x07970D42, 0x1A685F46, ++ 0x19220000, 0x0C600124, 0x2D010000, 0x1531FFFE, ++ 0x2E0D0000, 0x23610128, 0x070D4000, 0x2E0D0000, ++ 0x2E61012C, 0x12625F3C, 0x31200001, 0x1A60013E, ++ 0x39209000, 0x3797022B, 0x3A20A000, 0x0B970DD4, ++ 0x28680164, 0x126A0144, 0x28038000, 0x1632FFFE, ++ 0x2E0EC000, 0x30380000, 0x08D00EB7, 0x1F69014C, ++ 0x070E8000, 0x2E610140, 0x23620148, 0x35098000, ++ 0x2D61014C, 0x1531FFFE, 0x23610144, 0x00208200, ++ 0x00970DD6, 0x2B680168, 0x1C6A014C, 0x30380000, ++ 0x08D00EB7, 0x12690148, 0x23620148, 0x35098000, ++ 0x2E610140, 0x35098000, 0x1632FFFE, 0x040D8000, ++ 0x2D61014C, 0x3620F000, 0x00970DD6, 0x3E680148, ++ 0x1C690140, 0x19220000, 0x20620144, 0x0160014C, ++ 0x2E0D0000, 0x2E610140, 0x3230FFFC, 0x0C600148, ++ 0x1B208001, 0x00970DD6, 0x116A0148, 0x3368014C, ++ 0x2D6B0154, 0x2D620140, 0x2D010000, 0x3530FFFD, ++ 0x0F600144, 0x05300001, 0x1C0A0000, 0x040D8000, ++ 0x20610148, 0x020FC000, 0x12630150, 0x0F208010, ++ 0x00970DD6, 0x28680164, 0x1C690140, 0x30380000, ++ 0x08D00EB7, 0x116A0148, 0x3368014C, 0x206B0150, ++ 0x20610148, 0x2D620140, 0x312F0001, 0x12630150, ++ 0x1C0A0000, 0x20620144, 0x1B208001, 0x00970DD6, ++ 0x0C6A0150, 0x2D6B0154, 0x3368014C, 0x12690148, ++ 0x2E0EC000, 0x3E620150, 0x126A0144, 0x2E610140, ++ 0x1C0A0000, 0x23620148, 0x010F0000, 0x3A33FFFE, ++ 0x3D635F5C, 0x3930FFFE, 0x0F600144, 0x00208200, ++ 0x00970DD6, 0x0E970DE8, 0x07690168, 0x236A5F5C, ++ 0x1C390000, 0x08D00EB7, 0x1B970ECE, 0x2B200018, ++ 0x00800ED6, 0x0120FFFD, 0x2F970383, 0x122D0002, ++ 0x2B200018, 0x2197038B, 0x12600130, 0x1F600134, ++ 0x0834FFFE, 0x23C8020F, 0x112E0002, 0x23290002, ++ 0x22484000, 0x07625F46, 0x38340002, 0x20605F48, ++ 0x2B008000, 0x07018000, 0x3930FFFE, 0x1A32FFFD, ++ 0x2D0E0000, 0x040E4000, 0x1632FFFE, 0x3A9703A3, ++ 0x319702B8, 0x1E9709E7, 0x356A5F46, 0x2D200028, ++ 0x1A210000, 0x1132FFFF, 0x26970345, 0x36200000, ++ 0x356A5F46, 0x1A210000, 0x1132FFFF, 0x26970345, ++ 0x3D9702BB, 0x356A5F46, 0x359706A6, 0x36695F46, ++ 0x1A685F46, 0x1931FFFD, 0x2D610120, 0x29310001, ++ 0x1F090000, 0x20610124, 0x16970D35, 0x01690134, ++ 0x1C6A0120, 0x1861B010, 0x172E0068, 0x0862B000, ++ 0x0662B008, 0x31208808, 0x3760B01C, 0x362300AF, ++ 0x1A940D3A, 0x2169B024, 0x1C390000, 0x10D008F3, ++ 0x12690124, 0x03208400, 0x142D0068, 0x0661B004, ++ 0x3760B01C, 0x362300AF, 0x1A940D3A, 0x2C69B020, ++ 0x25310002, 0x21D408F3, 0x36695F46, 0x1C6A0120, ++ 0x31208808, 0x040E4000, 0x2E620120, 0x172E0068, ++ 0x0862B000, 0x0662B008, 0x3760B01C, 0x362300AF, ++ 0x1A940D3A, 0x2169B024, 0x1C390000, 0x10D008F3, ++ 0x03208400, 0x3760B01C, 0x362300AF, 0x1A940D3A, ++ 0x2C69B020, 0x25310002, 0x21D408F3, 0x07970D42, ++ 0x1A685F46, 0x1F690120, 0x0F600128, 0x3930FFFE, ++ 0x2E0D0000, 0x2E61012C, 0x329703C1, 0x11615F3C, ++ 0x3620F000, 0x202A0002, 0x13C408F5, 0x3E695F48, ++ 0x14350002, 0x21CC08F5, 0x3797022B, 0x0A9709C0, ++ 0x089709CB, 0x016A0154, 0x3368014C, 0x336B0140, ++ 0x3E620150, 0x12690148, 0x0F630148, 0x300B0000, ++ 0x0C630144, 0x3E30FFFF, 0x1F090000, 0x2E610140, ++ 0x1B208001, 0x00970DD6, 0x1C9709DA, 0x3368014C, ++ 0x1F6A0140, 0x12690148, 0x2D6B0154, 0x1C0A0000, ++ 0x2E62014C, 0x3E30FFFF, 0x2E0D0000, 0x2E610140, ++ 0x05300001, 0x2E0D0000, 0x20610148, 0x36200000, ++ 0x0F600144, 0x12630150, 0x39209000, 0x0B970DD4, ++ 0x3E680148, 0x1C690140, 0x1C6A014C, 0x1A084000, ++ 0x0160014C, 0x20610148, 0x2D620140, 0x2D010000, ++ 0x3E30FFFF, 0x2E0D0000, 0x3D610150, 0x3F208800, ++ 0x00970DD6, 0x3368014C, 0x1F6A0140, 0x12690148, ++ 0x2D6B0154, 0x1C0A0000, 0x2E62014C, 0x3E30FFFF, ++ 0x1F090000, 0x2E610140, 0x3930FFFE, 0x1C0A0000, ++ 0x23620148, 0x12630150, 0x39209000, 0x0B970DD4, ++ 0x3368014C, 0x12690148, 0x1F6A0140, 0x0C600148, ++ 0x1A084000, 0x28038000, 0x2D0E0000, 0x2E62014C, ++ 0x09300002, 0x010F0000, 0x01630140, 0x1C208000, ++ 0x0B970DD4, 0x3A20A000, 0x0B970DD4, 0x2E680154, ++ 0x1C6A014C, 0x2D010000, 0x29310001, 0x2FD408CD, ++ 0x322C0001, 0x3E2C0002, 0x0160014C, 0x2D620140, ++ 0x2D010000, 0x3E30FFFF, 0x2B0C4000, 0x0F600144, ++ 0x2D010000, 0x3E30FFFF, 0x2E0D0000, 0x20610148, ++ 0x00208200, 0x00970DD6, 0x3E680148, 0x306B014C, ++ 0x016A0154, 0x02600140, 0x2D010000, 0x3930FFFE, ++ 0x38605F5A, 0x1C09C000, 0x23610144, 0x1632FFFE, ++ 0x11625F5C, 0x03208400, 0x00970DD6, 0x0E970DE8, ++ 0x1B970ECE, 0x026B5F58, 0x0A6A0160, 0x3D2F0034, ++ 0x0B4BC000, 0x16420000, 0x3D370004, 0x25CC0DA8, ++ 0x236A5F5C, 0x2B200018, 0x00800ED6, 0x07970D42, ++ 0x3F800215, 0x1160013C, 0x2997037C, 0x0C2309A3, ++ 0x2B635F46, 0x1E2008FB, 0x38605F36, 0x229703B1, ++ 0x05CC027E, 0x22970251, 0x0B230901, 0x2B635F46, ++ 0x3B80022E, 0x3E680148, 0x1C6A014C, 0x1C690140, ++ 0x0160014C, 0x20620144, 0x2D0E0000, 0x3E30FFFF, ++ 0x1F090000, 0x2E610140, 0x23620148, 0x1B208001, ++ 0x00970DD6, 0x1C9709DA, 0x12690148, 0x3368014C, ++ 0x1F6A0140, 0x2D6B0154, 0x2E610140, 0x1C0A0000, ++ 0x1C0A0000, 0x2E62014C, 0x3930FFFE, 0x0C600148, ++ 0x36200000, 0x0F600144, 0x12630150, 0x39209000, ++ 0x0B970DD4, 0x3368014C, 0x12690148, 0x1F6A0140, ++ 0x0C600148, 0x1A084000, 0x09300002, 0x2D0E0000, ++ 0x2D620140, 0x05300001, 0x0160014C, 0x25200010, ++ 0x28695F52, 0x19220000, 0x2B190000, 0x1A615F52, ++ 0x26695F6C, 0x1F238000, 0x38635F56, 0x22484000, ++ 0x026B5F34, 0x122D0002, 0x3F424000, 0x351F0000, ++ 0x0EC80DB1, 0x16235F7A, 0x2449C000, 0x3D2F0002, ++ 0x1A1D0000, 0x29CC0941, 0x2449C000, 0x1C390000, ++ 0x3FCC0DB1, 0x25695F56, 0x1C390000, 0x25D40944, ++ 0x14625F56, 0x302F0006, 0x1D2E0001, 0x03800936, ++ 0x04685F52, 0x076B5F52, 0x3C34000F, 0x393700F0, ++ 0x2DCC094C, 0x1C1C8000, 0x26CC094E, 0x06800950, ++ 0x1C1C8000, 0x3DCC0950, 0x1D32FFFC, 0x01800951, ++ 0x1E31FFFC, 0x01198000, 0x17615F56, 0x076B5F52, ++ 0x23310004, 0x1035000F, 0x3F37000F, 0x1C1F4000, ++ 0x0CC80966, 0x28004000, 0x07645F52, 0x1331FFF8, ++ 0x32394001, 0x12615F6A, 0x2D010000, 0x22310003, ++ 0x19615F68, 0x3E30FFFF, 0x032C0D70, 0x05230965, ++ 0x21884000, 0x38605F6C, 0x116A0148, 0x1F69014C, ++ 0x30680140, 0x040D8000, 0x1531FFFE, 0x17615F60, ++ 0x3D6B0148, 0x1C0A0000, 0x2B0F8000, 0x0263014C, ++ 0x3930FFFE, 0x30605F62, 0x1632FFFE, 0x12625F66, ++ 0x10970CD3, 0x34200051, 0x2360B444, 0x09685F56, ++ 0x0A6B5F60, 0x3C34000F, 0x0E300003, 0x2D010000, ++ 0x0934FF00, 0x010CC000, 0x2060B448, 0x193500FF, ++ 0x0761B44A, 0x07685F68, 0x016B5F62, 0x206A5F66, ++ 0x2D010000, 0x0934FF00, 0x010CC000, 0x2D60B44C, ++ 0x193500FF, 0x0A61B44E, 0x1F62B454, 0x1920098F, ++ 0x3E210974, 0x362300AF, 0x19800CEA, 0x1D210001, ++ 0x3561015E, 0x1C208000, 0x1260015C, 0x02970E78, ++ 0x076B5F52, 0x0A685F6C, 0x3F37000F, 0x293B0100, ++ 0x2563B144, 0x3C2108C5, 0x3E2C0002, 0x15410000, ++ 0x09685F56, 0x0B230DB1, 0x3C34000F, 0x07645F52, ++ 0x0E300003, 0x35605F68, 0x08800DE8, 0x0A9709C0, ++ 0x089709CB, 0x3368014C, 0x1F6A0140, 0x12690148, ++ 0x2D6B0154, 0x1C0A0000, 0x2E62014C, 0x1F6A0140, ++ 0x12630150, 0x2E610140, 0x3930FFFE, 0x1C0A0000, ++ 0x23620148, 0x36200000, 0x0F600144, 0x39209000, ++ 0x0B970DD4, 0x1C690140, 0x3E680148, 0x116A0148, ++ 0x2E610140, 0x1A084000, 0x0160014C, 0x3E30FFFF, ++ 0x2D0E0000, 0x23620148, 0x36200000, 0x18800928, ++ 0x3E680148, 0x1C6A014C, 0x1C690140, 0x0160014C, ++ 0x20620144, 0x1F090000, 0x2D0E0000, 0x2E610140, ++ 0x23620148, 0x1B208001, 0x06800DD6, 0x3368014C, ++ 0x12690148, 0x1F6A0140, 0x2E610140, 0x2D0E0000, ++ 0x23620148, 0x2E020000, 0x1632FFFE, 0x1C0A0000, ++ 0x2E680154, 0x20620144, 0x020C0000, 0x11600150, ++ 0x00208200, 0x06800DD6, 0x1F6A0140, 0x12690148, ++ 0x3368014C, 0x23620148, 0x2E610140, 0x3930FFFE, ++ 0x1C0A0000, 0x2E680154, 0x20620144, 0x020C0000, ++ 0x11600150, 0x00208200, 0x06800DD6, 0x25635F4E, ++ 0x146B5F42, 0x356A5F46, 0x38200008, 0x1A210000, ++ 0x0A330002, 0x0BD009F4, 0x28038000, 0x1632FFFE, ++ 0x3D33FFFF, 0x2E0EC000, 0x0A2309FF, 0x20800345, ++ 0x2B9702CD, 0x356A5F46, 0x2E9702C7, 0x356A5F46, ++ 0x2E9702C7, 0x356A5F46, 0x2E9702C7, 0x356A5F46, ++ 0x2E9702C7, 0x356A5F46, 0x2E9702C7, 0x3E695F48, ++ 0x356A5F46, 0x18350001, 0x17C80A12, 0x2D200028, ++ 0x21970372, 0x19685F4A, 0x33695F4C, 0x1632FFFE, ++ 0x1A048000, 0x0FC40A0C, 0x1E2D0001, 0x01615F4C, ++ 0x2B605F4A, 0x0A20FFFF, 0x1A210000, 0x356A5F46, ++ 0x15230A13, 0x20800345, 0x359706A6, 0x356A5F46, ++ 0x25200010, 0x1A210000, 0x176B5F4E, 0x20800345, ++ 0x0620FFFC, 0x2F970383, 0x03361F00, 0x38C80211, ++ 0x23320008, 0x33620138, 0x3F2A0011, 0x3BC40211, ++ 0x3E970398, 0x236B0130, 0x2D010000, 0x2435FFFE, ++ 0x23C8020F, 0x3008C000, 0x26C00A28, 0x12CC020F, ++ 0x126B5F44, 0x112E0002, 0x07625F46, 0x3D2F0002, ++ 0x20635F44, 0x3D33FFFF, 0x1632FFFE, 0x2E0EC000, ++ 0x1632FFFE, 0x3A9703A3, 0x2E680138, 0x3D695F44, ++ 0x02030000, 0x0B2B0003, 0x04C40A38, 0x3A200003, ++ 0x392C0003, 0x15072000, 0x333B0000, 0x02CC0213, ++ 0x36695F46, 0x092E0010, 0x2B034000, 0x1931FFFD, ++ 0x1C09C000, 0x040E4000, 0x082A0800, 0x30C40213, ++ 0x319702B8, 0x36200000, 0x15210120, 0x146B5F42, ++ 0x356A5F46, 0x06330001, 0x1BD00A4D, 0x14230A4E, ++ 0x20800345, 0x2B9702CD, 0x08970C0E, 0x356A5F46, ++ 0x2D200028, 0x1A210000, 0x26970345, 0x3D9702BB, ++ 0x3D695F44, 0x1A685F46, 0x1231FFFF, 0x2E0D0000, ++ 0x20610124, 0x3E30FFFF, 0x2E0D0000, 0x2D610120, ++ 0x16970D35, 0x01690134, 0x1C6A0120, 0x1861B010, ++ 0x172E0068, 0x0862B000, 0x0662B008, 0x31208808, ++ 0x3760B01C, 0x362300AF, 0x1A940D3A, 0x2169B024, ++ 0x1C390000, 0x14D00A74, 0x12690124, 0x03208400, ++ 0x142D0068, 0x0661B004, 0x3760B01C, 0x362300AF, ++ 0x1A940D3A, 0x2C69B020, 0x25310002, 0x1FD00A76, ++ 0x07970D42, 0x34800217, 0x07970D42, 0x1A685F46, ++ 0x3D695F44, 0x1C6A0120, 0x0C600124, 0x2E0D0000, ++ 0x23610128, 0x0C690130, 0x2E6B0134, 0x3930FFFE, ++ 0x2D0E0000, 0x2D62012C, 0x11630130, 0x33610134, ++ 0x19220000, 0x12625F3C, 0x1320E000, 0x3797022B, ++ 0x28680164, 0x0F690150, 0x30380000, 0x08D00EB7, ++ 0x2D6B0154, 0x126A0144, 0x3368014C, 0x30610154, ++ 0x312F0001, 0x12630150, 0x1C690140, 0x2E62014C, ++ 0x02600140, 0x28004000, 0x040D8000, 0x20610148, ++ 0x1132FFFF, 0x19088000, 0x0F600144, 0x00208200, ++ 0x00970DD6, 0x2B680168, 0x2D6B0154, 0x30380000, ++ 0x08D00EB7, 0x1C6A014C, 0x12690148, 0x12630150, ++ 0x23620148, 0x35098000, 0x2E610140, 0x040D8000, ++ 0x1132FFFF, 0x040D8000, 0x2D61014C, 0x3620F000, ++ 0x00970DD6, 0x3E680148, 0x1F69014C, 0x1F6A0140, ++ 0x35230000, 0x0C630144, 0x0160014C, 0x2E0D0000, ++ 0x20610148, 0x2D0E0000, 0x2D620140, 0x1B208001, ++ 0x00970DD6, 0x116A0148, 0x3368014C, 0x1C690140, ++ 0x2D6B0154, 0x2D620140, 0x2D0E0000, 0x3E30FFFF, ++ 0x2D0E0000, 0x23620148, 0x1F090000, 0x23610144, ++ 0x3D33FFFF, 0x12630150, 0x0F208010, 0x00970DD6, ++ 0x04690164, 0x3368014C, 0x1C390000, 0x08D00EB7, ++ 0x1C690140, 0x116A0148, 0x206B0150, 0x20610148, ++ 0x2D620140, 0x312F0001, 0x12630150, 0x1F090000, ++ 0x23610144, 0x1B208001, 0x00970DD6, 0x0C6A0150, ++ 0x2D6B0154, 0x3368014C, 0x12690148, 0x2E0EC000, ++ 0x3E620150, 0x010F0000, 0x3A33FFFE, 0x3D635F5C, ++ 0x3E6B0144, 0x2E610140, 0x300B0000, 0x0F630148, ++ 0x3930FFFE, 0x300B0000, 0x0C630144, 0x00208200, ++ 0x00970DD6, 0x0E970DE8, 0x07690168, 0x236A5F5C, ++ 0x1C390000, 0x08D00EB7, 0x1B970ECE, 0x2B200018, ++ 0x00800ED6, 0x0120FFFD, 0x2F970383, 0x03361F00, ++ 0x38C80211, 0x23320008, 0x33620138, 0x3F2A0011, ++ 0x3BC40211, 0x3E970398, 0x236B0130, 0x2D010000, ++ 0x2435FFFE, 0x23C8020F, 0x3008C000, 0x20C00B01, ++ 0x12CC020F, 0x126B5F44, 0x112E0002, 0x07625F46, ++ 0x3D2F0002, 0x20635F44, 0x0200C000, 0x3D33FFFF, ++ 0x010F0000, 0x1632FFFE, 0x2E0EC000, 0x1632FFFE, ++ 0x3A9703A3, 0x2E680138, 0x3D695F44, 0x02030000, ++ 0x0B2B0003, 0x09C40B13, 0x3A200003, 0x3F2C0005, ++ 0x15072000, 0x333B0000, 0x02CC0213, 0x36695F46, ++ 0x092E0010, 0x1531FFFE, 0x040E4000, 0x082A0800, ++ 0x30C40213, 0x319702B8, 0x36200000, 0x1A210000, ++ 0x3E6A5F44, 0x26970345, 0x08970C0E, 0x356A5F46, ++ 0x2D200028, 0x1A210000, 0x1132FFFF, 0x26970345, ++ 0x3D9702BB, 0x11685F44, 0x36695F46, 0x2E020000, ++ 0x2B034000, 0x3E30FFFF, 0x1231FFFF, 0x280C8000, ++ 0x0C600124, 0x2B0C4000, 0x0F600128, 0x010CC000, ++ 0x01600120, 0x16970D35, 0x01690134, 0x126A0128, ++ 0x3E610130, 0x1861B010, 0x172E0068, 0x0862B000, ++ 0x0662B008, 0x31208808, 0x3760B01C, 0x362300AF, ++ 0x1A940D3A, 0x2169B024, 0x1C390000, 0x32D40B46, ++ 0x07970D42, 0x3F800215, 0x12690124, 0x03208400, ++ 0x142D0068, 0x0661B004, 0x3760B01C, 0x362300AF, ++ 0x1A940D3A, 0x2C69B020, 0x25310002, 0x39D40B44, ++ 0x1C6A0120, 0x31208808, 0x172E0068, 0x0862B000, ++ 0x0662B008, 0x3760B01C, 0x362300AF, 0x1A940D3A, ++ 0x2169B024, 0x1C390000, 0x08D00B44, 0x03208400, ++ 0x3760B01C, 0x362300AF, 0x1A940D3A, 0x2C69B020, ++ 0x25310002, 0x39D40B44, 0x07970D42, 0x1A685F46, ++ 0x1F690120, 0x0F600128, 0x2E0D0000, 0x2E61012C, ++ 0x19220000, 0x12625F3C, 0x3620F000, 0x3797022B, ++ 0x3E680148, 0x1C6A014C, 0x1C690140, 0x0160014C, ++ 0x20620144, 0x1F090000, 0x2E610140, 0x2D0E0000, ++ 0x23620148, 0x1B208001, 0x00970DD6, 0x3368014C, ++ 0x12690148, 0x1F6A0140, 0x2E610140, 0x07018000, ++ 0x2E0D0000, 0x20610148, 0x3E30FFFF, 0x1C0A0000, ++ 0x2E680154, 0x20620144, 0x020C0000, 0x11600150, ++ 0x00208200, 0x00970DD6, 0x016A0154, 0x3368014C, ++ 0x336B0140, 0x3E620150, 0x12690148, 0x0F630148, ++ 0x300B0000, 0x0C630144, 0x3E30FFFF, 0x1F090000, ++ 0x2E610140, 0x1B208001, 0x00970DD6, 0x3368014C, ++ 0x1F6A0140, 0x12690148, 0x23620148, 0x1C0A0000, ++ 0x2E680154, 0x20620144, 0x2E610140, 0x020C0000, ++ 0x11600150, 0x00208200, 0x00970DD6, 0x3368014C, ++ 0x2D6B0154, 0x12690148, 0x1F6A0140, 0x12630150, ++ 0x2E610140, 0x2D695F58, 0x1C0A0000, 0x2E62014C, ++ 0x1F2D0030, 0x0D4A4000, 0x1F2D0006, 0x0E494000, ++ 0x0F3607FC, 0x26320002, 0x33620154, 0x28038000, ++ 0x06330001, 0x31D40BB3, 0x1D2E0001, 0x112E0002, ++ 0x20620144, 0x1132FFFF, 0x23620148, 0x00351F00, ++ 0x20310008, 0x33610158, 0x1320E000, 0x00970DD6, ++ 0x3D680144, 0x1C6A014C, 0x1C690140, 0x206B0150, ++ 0x2D0E0000, 0x2E62014C, 0x0200C000, 0x06330001, ++ 0x2BD40BC6, 0x322C0001, 0x3E2C0002, 0x3E30FFFF, ++ 0x2E0D0000, 0x2E610140, 0x1A210000, 0x20610148, ++ 0x1320E000, 0x00970DD6, 0x206B0150, 0x2E680154, ++ 0x1C6A014C, 0x0263014C, 0x11600150, 0x1C600154, ++ 0x02030000, 0x06330001, 0x30D40BD8, 0x322C0001, ++ 0x3E2C0002, 0x20620144, 0x1C0A0000, 0x2D620140, ++ 0x3E30FFFF, 0x2D0E0000, 0x23620148, 0x1B208001, ++ 0x00970DD6, 0x12690148, 0x126A0144, 0x206B0150, ++ 0x2E610140, 0x23620148, 0x0200C000, 0x3D33FFFF, ++ 0x12630150, 0x1C600154, 0x02030000, 0x06330001, ++ 0x30D40BEE, 0x322C0001, 0x3E2C0002, 0x0F600144, ++ 0x00208200, 0x00970DD6, 0x11690144, 0x116A0148, ++ 0x3368014C, 0x2D6B0154, 0x2D620140, 0x12630150, ++ 0x1C600154, 0x02030000, 0x06330001, 0x2FD40BFD, ++ 0x322C0001, 0x3E2C0002, 0x0160014C, 0x350A4000, ++ 0x23620148, 0x3930FFFE, 0x1C0A0000, 0x20620144, ++ 0x00208200, 0x00970DD6, 0x12690148, 0x016A0154, ++ 0x306B014C, 0x2E610140, 0x3E620150, 0x3D33FFFF, ++ 0x1C09C000, 0x088008E2, 0x25635F4E, 0x146B5F42, ++ 0x38200008, 0x1A210000, 0x3E6A5F44, 0x0A330002, ++ 0x1CD00C1A, 0x196B5F46, 0x1132FFFF, 0x2E0EC000, ++ 0x19230C2A, 0x20800345, 0x2B9702CD, 0x3E6A5F44, ++ 0x2E9702C7, 0x3E6A5F44, 0x19685F4A, 0x33695F4C, ++ 0x1632FFFE, 0x1A048000, 0x10C40C25, 0x1E2D0001, ++ 0x01615F4C, 0x2B605F4A, 0x356A5F46, 0x0A20FFFF, ++ 0x1A210000, 0x2B9702CD, 0x356A5F46, 0x25200010, ++ 0x1A210000, 0x176B5F4E, 0x20800345, 0x3780021B, ++ 0x02030000, 0x0C37FFFF, 0x0CCC021B, 0x052C0C35, ++ 0x21884000, 0x06800C36, 0x28970382, 0x3E20000E, ++ 0x2197038B, 0x093C000E, 0x12CC020F, 0x2A2001FF, ++ 0x2197038B, 0x3D605F3C, 0x3F340003, 0x12CC020F, ++ 0x122E000E, 0x1632FFFE, 0x3A9703A3, 0x319702B8, ++ 0x1122000E, 0x36200000, 0x1A210000, 0x26970345, ++ 0x01685F34, 0x122101D8, 0x3E610106, 0x3B2C0008, ++ 0x27490000, 0x3E2C0002, 0x0B480000, 0x07615F4A, ++ 0x2D605F4C, 0x0F685F3C, 0x30695F40, 0x3930FFFE, ++ 0x36605F3E, 0x1F090000, 0x04C40C58, 0x2E605F40, ++ 0x202001A0, 0x08230C5D, 0x19600104, 0x3B635F36, ++ 0x258002F5, 0x25200010, 0x19600104, 0x2B80043E, ++ 0x20970106, 0x15220003, 0x1F62B438, 0x2C695FCA, ++ 0x04685EDE, 0x19220000, 0x1461B400, 0x1162B406, ++ 0x30380000, 0x36C800A5, 0x2A340080, 0x00C80C6F, ++ 0x13200C80, 0x19230C70, 0x288000B4, 0x36605EDE, ++ 0x09685EEC, 0x332300A5, 0x19220000, 0x14625EEC, ++ 0x28695EDE, 0x366A5EF0, 0x30380000, 0x22C8010E, ++ 0x01198000, 0x2E6A5F02, 0x01198000, 0x336A5EA0, ++ 0x24D000B4, 0x3C36FDFF, 0x01625EA0, 0x288000B4, ++ 0x22215EDE, 0x1F220006, 0x1D97100D, 0x2F215EEC, ++ 0x21510000, 0x21510000, 0x21884000, 0x1F220030, ++ 0x1F62B438, 0x21695FCE, 0x19685EF0, 0x19220000, ++ 0x0161B420, 0x0462B426, 0x30380000, 0x3AC800A6, ++ 0x2A340080, 0x0CC80C95, 0x02200C9B, 0x05230C96, ++ 0x288000B4, 0x2B605EF0, 0x11685EFE, 0x3F2300A6, ++ 0x19220000, 0x0C625EFE, 0x1B800C74, 0x3F215EF0, ++ 0x1F220006, 0x1D97100D, 0x37215EFE, 0x21510000, ++ 0x21510000, 0x21884000, 0x1F220300, 0x1F62B438, ++ 0x21695FCE, 0x01685F02, 0x19220000, 0x0261B440, ++ 0x0762B446, 0x30380000, 0x3DC800A7, 0x2A340080, ++ 0x13C80CB0, 0x13200CB6, 0x11230CB1, 0x288000B4, ++ 0x33605F02, 0x19685F10, 0x382300A7, 0x19220000, ++ 0x04625F10, 0x1B800C74, 0x27215F02, 0x1F220006, ++ 0x1D97100D, 0x3F215F10, 0x21510000, 0x21510000, ++ 0x21884000, 0x04685EDE, 0x22215EDE, 0x30380000, ++ 0x0CD00CC9, 0x03205EEC, 0x0B518000, 0x0D500000, ++ 0x30695EA0, 0x0D500000, 0x00390200, 0x02615EA0, ++ 0x228B4000, 0x0200C000, 0x1F220006, 0x362300AF, ++ 0x19801030, 0x19685EF0, 0x3F215EF0, 0x30380000, ++ 0x0CD00CC9, 0x1B205EFE, 0x02800CC2, 0x01685F02, ++ 0x27215F02, 0x30380000, 0x0CD00CC9, 0x13205F10, ++ 0x02800CC2, 0x04685EDE, 0x22215EDE, 0x30380000, ++ 0x33D40CC1, 0x398000AF, 0x19685EF0, 0x3F215EF0, ++ 0x30380000, 0x35D000AF, 0x1B205EFE, 0x02800CC2, ++ 0x3B605EEC, 0x1C615EEE, 0x228B4000, 0x23605EFE, ++ 0x14615F00, 0x228B4000, 0x2B605F10, 0x0C615F12, ++ 0x228B4000, 0x19685EF0, 0x1A210000, 0x30380000, ++ 0x0DC80CFE, 0x1F61B434, 0x226A5FCE, 0x0761B426, ++ 0x0262B420, 0x2A340080, 0x01C80CFD, 0x28635E9C, ++ 0x3F215EF0, 0x1F220006, 0x1D97100D, 0x1A6B5E9C, ++ 0x288000B4, 0x07615EF0, 0x228B4000, 0x2E620116, ++ 0x1B200D02, 0x288000B4, 0x15970CD9, 0x1C6A0116, ++ 0x0D20B404, 0x19500011, 0x01500003, 0x1150C400, ++ 0x0A500001, 0x0E500180, 0x0D500000, 0x0962B414, ++ 0x352000AF, 0x192100AF, 0x362300AF, 0x11800CE4, ++ 0x01690102, 0x36200000, 0x0A350020, 0x28C8020D, ++ 0x30218000, 0x1F615ED4, 0x3B605EDA, 0x3D605EDC, ++ 0x228B4000, 0x2D695ED4, 0x30380000, 0x22C8010E, ++ 0x1C390000, 0x18D4010A, 0x3B605EDA, 0x228B4000, ++ 0x2D695ED4, 0x30380000, 0x22C8010E, 0x1C390000, ++ 0x18D4010A, 0x3D605EDC, 0x228B4000, 0x01685ED4, ++ 0x27215ED4, 0x30380000, 0x1ED4010C, 0x21510000, ++ 0x228B4000, 0x30695ECC, 0x07685ED2, 0x1C390000, ++ 0x06D400A4, 0x30380000, 0x31C800A4, 0x342300A4, ++ 0x288000B4, 0x3A215ECC, 0x0B518000, 0x36200000, ++ 0x35605ED2, 0x228B4000, 0x30695ECC, 0x35605ED2, ++ 0x1C390000, 0x30695EA0, 0x18D4010A, 0x12390008, ++ 0x02615EA0, 0x228B4000, 0x336A5EA0, 0x1C685ECC, ++ 0x3A215ECC, 0x2E36FFF7, 0x01625EA0, 0x30380000, ++ 0x1ED4010C, 0x21510000, 0x228B4000, 0x04685F52, ++ 0x30218000, 0x2D144000, 0x04CC00A9, 0x1A615F52, ++ 0x302300A9, 0x19200D53, 0x288000B4, 0x29200400, ++ 0x2660B144, 0x06210200, 0x1468B144, 0x3C34000F, ++ 0x2B190000, 0x0A61B144, 0x07645F52, 0x2D010000, ++ 0x20310008, 0x1139A0C8, 0x214B4000, 0x0F2D002C, ++ 0x0E494000, 0x2E020000, 0x06330001, 0x20377F00, ++ 0x1263010A, 0x21320003, 0x1A625F68, 0x2E020000, ++ 0x1032FFF8, 0x313A4001, 0x11625F6A, 0x2E020000, ++ 0x1132FFFF, 0x2C2E0D70, 0x07230D84, 0x0E8A4000, ++ 0x15205F7A, 0x228B4000, 0x12205F82, 0x228B4000, ++ 0x1C205F8A, 0x228B4000, 0x01205F92, 0x228B4000, ++ 0x0F205F9A, 0x228B4000, 0x07205FA2, 0x228B4000, ++ 0x09205FAA, 0x228B4000, 0x14205FB2, 0x228B4000, ++ 0x1A205FBA, 0x228B4000, 0x04205FC2, 0x228B4000, ++ 0x38605F6C, 0x27490000, 0x3E2C0002, 0x084B0000, ++ 0x3E2C0002, 0x244A0000, 0x3E2C0002, 0x0B480000, ++ 0x1F615F58, 0x38635F56, 0x17625F5A, 0x3E605F5C, ++ 0x10970E96, 0x236A5F5C, 0x266B010C, 0x1F3A0000, ++ 0x1AC80DA0, 0x19213000, 0x35098000, 0x190B4000, ++ 0x3061010E, 0x2CC00D9B, 0x34CC0EB5, 0x0A685F5A, ++ 0x1F230DA0, 0x33635F54, 0x046B5F68, 0x12800E9B, ++ 0x0F69010A, 0x0A6B5F56, 0x20310008, 0x0DC80DD1, ++ 0x2E6A5F58, 0x05390080, 0x162E0035, 0x0E458000, ++ 0x0E970DE8, 0x04685F52, 0x1B230DAD, 0x16341000, ++ 0x2DCC109C, 0x3A2000A0, 0x00645F53, 0x2D695F58, ++ 0x3197028E, 0x0269010E, 0x1A223000, 0x350A4000, ++ 0x1DC80DCD, 0x28680108, 0x25620114, 0x30380000, ++ 0x0CC80DBA, 0x06970CFF, 0x10970CD3, 0x0269010E, ++ 0x1B20B444, 0x19500011, 0x0A500001, 0x1150C400, ++ 0x0A500001, 0x2335FFFF, 0x15410000, 0x176A0114, ++ 0x3E2C0002, 0x0D500000, 0x1F62B454, 0x1D200DCB, ++ 0x31210DCB, 0x362300AF, 0x19800CEA, 0x35203000, ++ 0x1C60010E, 0x1A210000, 0x36610108, 0x1A615F52, ++ 0x398000AF, 0x19220000, 0x3662015E, 0x228B4000, ++ 0x1D210001, 0x3561015E, 0x1260015C, 0x38635F56, ++ 0x02970E78, 0x076B5F52, 0x0A685F6C, 0x3F37000F, ++ 0x293B0100, 0x2563B144, 0x25695F56, 0x3E2C0002, ++ 0x15410000, 0x26695F5A, 0x3E2C0002, 0x15410000, ++ 0x20695F5C, 0x3E2C0002, 0x15410000, 0x04800DB1, ++ 0x04685F52, 0x3569B140, 0x3930FFFE, 0x38D003AD, ++ 0x33635F54, 0x09300002, 0x02030000, 0x3C34000F, ++ 0x3D3CFFFF, 0x33228000, 0x1A120000, 0x301D8000, ++ 0x0761B140, 0x336A5EA0, 0x27CC0DF9, 0x2D36FFFB, ++ 0x01625EA0, 0x3D3CFFFF, 0x3A225F7A, 0x3530FFFD, ++ 0x1F060000, 0x22520000, 0x22520000, 0x153B2000, ++ 0x07685F32, 0x35635F52, 0x1A344000, 0x19C80E09, ++ 0x0A685F36, 0x2E9700B4, 0x02685F54, 0x362300AF, ++ 0x288000B4, 0x04685F52, 0x3569B140, 0x1F238000, ++ 0x3C34000F, 0x2E020000, 0x123EFFFF, 0x1C138000, ++ 0x2819C000, 0x0761B140, 0x3F30FFF8, 0x2838A084, ++ 0x18500020, 0x3B680118, 0x2E695F54, 0x0418C000, ++ 0x09600118, 0x351CC000, 0x28CC0E53, 0x2361011E, ++ 0x07685F68, 0x0763011C, 0x0260011A, 0x10970CD3, ++ 0x336B011A, 0x1B20B444, 0x1C500041, 0x0A500001, ++ 0x0E500180, 0x0D500000, 0x2D02C000, 0x2636FF00, ++ 0x0262B44C, 0x363700FF, 0x2563B44E, 0x3F222000, ++ 0x1F62B454, 0x3E6B011E, 0x36200000, 0x0F60011E, ++ 0x333B0000, 0x2BCC0E33, 0x362300AF, 0x16200E36, ++ 0x3A210E36, 0x19800CEA, 0x3668011C, 0x3569B140, ++ 0x146A0118, 0x1A1D0000, 0x0761B140, 0x191E0000, ++ 0x26620118, 0x09C80E4F, 0x36200000, 0x1D210001, ++ 0x28038000, 0x2E174000, 0x31CC0E46, 0x322C0001, ++ 0x1231FFFF, 0x0C800E40, 0x2861011C, 0x0E300003, ++ 0x2B695F32, 0x0260011A, 0x36354000, 0x0CC80E1F, ++ 0x0A200E1F, 0x096B5F36, 0x288000B4, 0x07685F32, ++ 0x26695F36, 0x1A344000, 0x33C800AF, 0x0D894000, ++ 0x1F3A0000, 0x3EC803AD, 0x3B635F36, 0x1A6B5F4A, ++ 0x19600104, 0x3E610106, 0x19625F3E, 0x23635F48, ++ 0x0B970CCD, 0x2B680104, 0x0F6A0106, 0x116B5F48, ++ 0x2360B428, 0x3C21B42A, 0x21510000, 0x0200C000, ++ 0x0934FF00, 0x281A0000, 0x0162B42C, 0x363700FF, ++ 0x2663B42E, 0x2B6A5F3E, 0x27200041, 0x2060B424, ++ 0x1C62B434, 0x3C210E5C, 0x362300AF, 0x18940CE7, ++ 0x096B5F36, 0x228B4000, 0x3B635F36, 0x39200120, ++ 0x1A210000, 0x0C220020, 0x1C6B5F4C, 0x11800E58, ++ 0x33635F54, 0x0F6B5F6A, 0x3A200140, 0x1A210000, ++ 0x0C220020, 0x3B605F60, 0x1C615F62, 0x12625F66, ++ 0x36635F5E, 0x10970CD3, 0x09685F60, 0x2D6A5F62, ++ 0x046B5F5E, 0x2060B448, 0x3F21B44A, 0x21510000, ++ 0x0200C000, 0x0934FF00, 0x281A0000, 0x0262B44C, ++ 0x363700FF, 0x2563B44E, 0x206A5F66, 0x27200041, ++ 0x2360B444, 0x1F62B454, 0x05200EB3, 0x24210E81, ++ 0x362300AF, 0x19800CEA, 0x33635F54, 0x36200000, ++ 0x16210140, 0x0F22002C, 0x0F6B5F6A, 0x3B605F60, ++ 0x1C615F62, 0x12625F66, 0x36635F5E, 0x10970CD3, ++ 0x286A5F5E, 0x09685F60, 0x2E695F62, 0x28038000, ++ 0x0A37FF00, 0x0418C000, 0x2060B448, 0x1A3600FF, ++ 0x0462B44A, 0x0161B44C, 0x36200000, 0x2660B44E, ++ 0x206A5F66, 0x22200011, 0x2360B444, 0x1F62B454, ++ 0x3F210E9F, 0x362300AF, 0x1C940CEA, 0x016B5F54, ++ 0x228B4000, 0x0B210041, 0x1D800DA4, 0x08210021, ++ 0x1D800DA4, 0x2E6A5F58, 0x04690164, 0x012E0028, ++ 0x1C390000, 0x1CD00ECA, 0x1F090000, 0x1531FFFE, ++ 0x2B680168, 0x3F418000, 0x2F34001F, 0x112E0002, ++ 0x13408000, 0x2B008000, 0x3E2C0002, 0x0D500000, ++ 0x0D500000, 0x228B4000, 0x1C208000, 0x13408000, ++ 0x36200000, 0x19800EC3, 0x01685F58, 0x1A210000, ++ 0x2E2C0028, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x15410000, 0x228B4000, 0x11230DA8, 0x0F3607FC, ++ 0x3EC803AD, 0x33635F54, 0x026B5F58, 0x12625F66, ++ 0x010CC000, 0x084B0000, 0x3E2C0002, 0x0B480000, ++ 0x33635F62, 0x2D6B010E, 0x36605F64, 0x2D0DC000, ++ 0x36610108, 0x1B970CBD, 0x02685F62, 0x28695F64, ++ 0x3B60B40C, 0x1C61B40E, 0x28680108, 0x206A5F66, ++ 0x2921B40A, 0x3660B408, 0x21510000, 0x28200081, ++ 0x3560B404, 0x0962B414, 0x02685F54, 0x2A210EE5, ++ 0x362300AF, 0x11800CE4, 0x2D695F6E, 0x1C208000, ++ 0x28150000, 0x1BC80EFB, 0x228B4000, 0x336A5EA0, ++ 0x33605F6E, 0x0B200F01, 0x2B36FFFD, 0x01625EA0, ++ 0x288000B4, 0x15685FDC, 0x2D695F6E, 0x30380000, ++ 0x04C80F64, 0x28605F70, 0x232C0040, 0x27490000, ++ 0x2E655F6E, 0x3865B112, 0x1F31FFFB, 0x232D4010, ++ 0x0D4A4000, 0x1F6BB110, 0x122D0002, 0x1F0AC000, ++ 0x33C00F58, 0x214B4000, 0x2C2DFFF6, 0x333B0000, ++ 0x2AD40F1D, 0x1A685F70, 0x012D0012, 0x0D4A4000, ++ 0x282C0042, 0x084B0000, 0x312DFFEE, 0x1F1F8000, ++ 0x3BCC0F5A, 0x28004000, 0x37215F72, 0x0B97104D, ++ 0x3D695F72, 0x332C0006, 0x13350003, 0x31CC0F5F, ++ 0x37215F72, 0x2922FFFC, 0x16971063, 0x1A685F70, ++ 0x33215FDC, 0x0B970FCB, 0x12971097, 0x1B970CBD, ++ 0x196B5F70, 0x11685F72, 0x3B695F74, 0x2A22B40A, ++ 0x3563B408, 0x22520000, 0x3B60B40C, 0x1C61B40E, ++ 0x28200081, 0x3560B404, 0x20200040, 0x2660B414, ++ 0x30210F2A, 0x362300AF, 0x14940CE4, 0x01685F6E, ++ 0x39695FEA, 0x353400FF, 0x3330FFFB, 0x0A2C401A, ++ 0x084B0000, 0x1E2D0001, 0x312F0001, 0x3A430000, ++ 0x002CFFF6, 0x244A0000, 0x332C0006, 0x084B0000, ++ 0x0B615FEA, 0x312F0001, 0x1F0AC000, 0x1BC40F4D, ++ 0x35230000, 0x3A430000, 0x2E6A5F6E, 0x1A685F70, ++ 0x1A3600FF, 0x3A3A1000, 0x1462B130, 0x06970FA3, ++ 0x1C208000, 0x33605F6E, 0x08230F01, 0x26800130, ++ 0x0D210088, 0x29655F6F, 0x1A685F70, 0x2D695F6E, ++ 0x3D2C0038, 0x0B480000, 0x0C800F03, 0x35970110, ++ 0x1A685F70, 0x33215FDC, 0x06230F53, 0x0D800FCB, ++ 0x336A5EA0, 0x3C350800, 0x1F615F6E, 0x33C800AF, ++ 0x143A0002, 0x01625EA0, 0x398000AF, 0x1768B148, ++ 0x05300001, 0x11D00F74, 0x03300007, 0x15D00F79, ++ 0x0C300008, 0x3D3CFFFF, 0x1464B148, 0x388000A8, ++ 0x35230000, 0x2663B148, 0x39635FF2, 0x32635FF0, ++ 0x0B800F6E, 0x0E710048, 0x13710149, 0x2871804B, ++ 0x12800F7B, 0x00685FFC, 0x276AB1F8, 0x0934FF00, ++ 0x0C300008, 0x322C0001, 0x03361F00, 0x23320008, ++ 0x1C0A0000, 0x06C00114, 0x3F225E90, 0x3330FFFB, ++ 0x1C2C4000, 0x1C0A0000, 0x10C0010E, 0x2F605FD2, ++ 0x06625FD4, 0x242A000F, 0x16C00108, 0x228B4000, ++ 0x10685FD6, 0x37695FD4, 0x30380000, 0x01C80F97, ++ 0x27490000, 0x0E615FD6, 0x228B4000, 0x33290044, ++ 0x3DC00F9F, 0x1D685FD2, 0x05615FD4, 0x2D010000, ++ 0x022D0044, 0x03615FD2, 0x228B4000, 0x361C0000, ++ 0x2F605FD2, 0x29605FD4, 0x228B4000, 0x3C695FD6, ++ 0x30380000, 0x22C8010E, 0x15410000, 0x22605FD6, ++ 0x228B4000, 0x1C390000, 0x24C80108, 0x0D4A4000, ++ 0x30380000, 0x22C8010E, 0x10404000, 0x1F3A0000, ++ 0x14C80FB7, 0x362C003A, 0x16420000, 0x122E0038, ++ 0x062CFFC6, 0x13408000, 0x228B4000, 0x222DFFFE, ++ 0x10404000, 0x228B4000, 0x1C390000, 0x24C80108, ++ 0x0D4A4000, 0x30380000, 0x22C8010E, 0x10404000, ++ 0x1F3A0000, 0x0BC80FC8, 0x3D2C0038, 0x16420000, ++ 0x192E003A, 0x0E2CFFC8, 0x13408000, 0x228B4000, ++ 0x122D0002, 0x10404000, 0x228B4000, 0x1C390000, ++ 0x24C80108, 0x30380000, 0x22C8010E, 0x2D635E96, ++ 0x362C003A, 0x084B0000, 0x0E2CFFFE, 0x244A0000, ++ 0x333B0000, 0x1EC80FDE, 0x1F3A0000, 0x12C80FEB, ++ 0x3E2F0038, 0x1542C000, 0x192E003A, 0x0D2FFFC8, ++ 0x10438000, 0x1C800FE6, 0x3F424000, 0x1F3A0000, ++ 0x1DC80FE4, 0x192E003A, 0x10438000, 0x1C800FE6, ++ 0x122D0002, 0x3F424000, 0x0D500000, 0x0D500000, ++ 0x1F6B5E96, 0x0D2CFFC4, 0x228B4000, 0x122D0002, ++ 0x3F424000, 0x3E2F0038, 0x1542C000, 0x1C800FE6, ++ 0x2A320001, 0x0A367FFF, 0x19C81003, 0x252A0008, ++ 0x3EC00FFF, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x0D500000, 0x0D500000, 0x0D500000, ++ 0x0D500000, 0x19C81003, 0x05800FF3, 0x26260008, ++ 0x0D500000, 0x262EFFFF, 0x24CC1000, 0x228B4000, ++ 0x26635E94, 0x1D97100D, 0x146B5E94, 0x288000B4, ++ 0x26635E94, 0x1D97100D, 0x02030000, 0x17685E94, ++ 0x288000B4, 0x22484000, 0x0F615E92, 0x28605E90, ++ 0x0C300008, 0x3FD4102E, 0x2D635E96, 0x2C34007F, ++ 0x3E30FFFF, 0x122D0002, 0x2E0D0000, 0x214B4000, ++ 0x05300001, 0x322C0001, 0x36695E90, 0x191E0000, ++ 0x3FCC101E, 0x36200000, 0x07024000, 0x36368000, ++ 0x0035007F, 0x1A1D0000, 0x3D695E92, 0x03C8102C, ++ 0x23320008, 0x281A0000, 0x1E2D0001, 0x0E464000, ++ 0x0200C000, 0x1F6B5E96, 0x30380000, 0x228B4000, ++ 0x3F424000, 0x04801028, 0x361C0000, 0x228B4000, ++ 0x28605E90, 0x22484000, 0x0A625E94, 0x0C300008, ++ 0x36D4104B, 0x2E020000, 0x0C300008, 0x2C34007F, ++ 0x0336007F, 0x191E0000, 0x24C80108, 0x3E30FFFF, ++ 0x356A5E90, 0x0F615E92, 0x122D0002, 0x2E0D0000, ++ 0x3F424000, 0x386A5E94, 0x3D695E92, 0x05300001, ++ 0x322C0001, 0x191E0000, 0x3CCC1048, 0x36200000, ++ 0x29380080, 0x21444000, 0x228B4000, 0x36200000, ++ 0x1A80103C, 0x2D635E96, 0x084B0000, 0x3E2C0002, ++ 0x13434000, 0x244A0000, 0x122D0002, 0x3F424000, ++ 0x2E1B8000, 0x3E2C0002, 0x244A0000, 0x122D0002, ++ 0x3F424000, 0x2E1B8000, 0x3E2C0002, 0x244A0000, ++ 0x122D0002, 0x3F424000, 0x2B1AC000, 0x1F6B5E96, ++ 0x3E2C0002, 0x122D0002, 0x228B4000, 0x28605E90, ++ 0x0F615E92, 0x2D635E96, 0x27490000, 0x280C8000, ++ 0x0B480000, 0x1C390000, 0x09C8108A, 0x03340FFC, ++ 0x0EC81072, 0x15280041, 0x3CC01072, 0x16240041, ++ 0x15072000, 0x0E801077, 0x1831FFFA, 0x07024000, ++ 0x2936FFC0, 0x2B034000, 0x3937003F, 0x3D695E92, ++ 0x22484000, 0x1A048000, 0x10404000, 0x122D0002, ++ 0x22484000, 0x2C04C400, 0x10404000, 0x0AC4108A, ++ 0x122D0002, 0x22484000, 0x19220000, 0x05048400, ++ 0x10404000, 0x0AC4108A, 0x122D0002, 0x22484000, ++ 0x05048400, 0x10404000, 0x1F6B5E96, 0x1A685E90, ++ 0x228B4000, 0x14685F14, 0x32215F14, 0x30380000, ++ 0x15D01093, 0x0B518000, 0x228B4000, 0x0200C000, ++ 0x12220002, 0x362300AF, 0x19801030, 0x14685F14, ++ 0x3A215F1A, 0x30380000, 0x15D01093, 0x228B4000, ++ 0x14685F14, 0x32215F14, 0x30380000, 0x1ED4010C, ++ 0x2A340080, 0x14C810A4, 0x12220002, 0x11801008, ++ 0x21510000, 0x1C685F1A, 0x28635E9C, 0x30380000, ++ 0x2DCC10AA, 0x228B4000, 0x3A215F1A, 0x12220002, ++ 0x14971004, 0x1A6B5E9C, 0x198010A5, 0x3DFFFFFF, ++ 0x01000000, 0x01000000, 0x01000000 ++}; ++ ++// Encapsulates the PKA firmware images information. ++typedef struct { ++ const uint32_t *farm_img; ++ uint32_t farm_img_size; ++ const uint32_t *boot_img; ++ uint32_t boot_img_size; ++ const uint32_t *master_img; ++ uint32_t master_img_size; ++} pka_firmware_info_t; ++ ++static const pka_firmware_info_t pka_firmware_array[] = ++{ ++ { ++ fw0_farm_img_data_buf, 2048, // actual length is 1652 ++ fw0_boot_img_data_buf, 152, ++ fw0_master_img_data_buf, 4161 ++ }, ++ { ++ fw1_farm_img_data_buf, 2048, // actual length is 2000 ++ fw1_boot_img_data_buf, 127, ++ fw1_master_img_data_buf, 4186 ++ }, ++ { ++ fw2_farm_img_data_buf, 2048, // actual length is 2045 ++ fw2_boot_img_data_buf, 154, ++ fw2_master_img_data_buf, 4275 ++ } ++}; ++ ++#define PKA_FIRMWARE_IMAGE_0_ID 0 ++#define PKA_FIRMWARE_IMAGE_1_ID 1 ++#define PKA_FIRMWARE_IMAGE_2_ID 2 ++ ++// Global storage for the actual firmware identifier ++static uint8_t pka_firmware_id; ++ ++// Setter of pka_firmware_id ++static inline void pka_firmware_set_id(uint8_t id) ++{ ++ pka_firmware_id = id; ++} ++ ++// Getter of pka_firmware_id ++static inline uint8_t pka_firmware_get_id(void) ++{ ++ return pka_firmware_id; ++} ++ ++ ++#endif +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ioctl.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ioctl.h +new file mode 100644 +index 000000000..8081a01fd +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ioctl.h +@@ -0,0 +1,127 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_IOCTL_H__ ++#define __PKA_IOCTL_H__ ++ ++ ++#include ++#include ++ ++#define PKA_IOC_TYPE 0xB7 ++ ++/// PKA_RING_GET_REGION_INFO - _IORW(PKA_IOC_TYPE, 0x0, pka_dev_region_info_t) ++/// ++/// Retrieve information about a device region. This is intended to describe ++/// MMIO, I/O port, as well as bus specific regions (ex. PCI config space). ++/// Zero sized regions may be used to describe unimplemented regions. ++/// Return: 0 on success, -errno on failure. ++typedef struct ++{ ++ uint32_t reg_index; ///< Registers region index. ++ uint64_t reg_size; ///< Registers region size (bytes). ++ uint64_t reg_offset; ///< Registers region offset from start of device fd. ++ ++ uint32_t mem_index; ///< Memory region index. ++ uint64_t mem_size; ///< Memory region size (bytes). ++ uint64_t mem_offset; ///< Memeory region offset from start of device fd. ++} pka_dev_region_info_t; ++#define PKA_RING_GET_REGION_INFO _IOWR(PKA_IOC_TYPE, 0x0, pka_dev_region_info_t) ++ ++/// PKA_GET_RING_INFO - _IORW(PKA_IOC_TYPE, 0x1, pka_dev_ring_info_t) ++/// ++/// Retrieve information about a ring. This is intended to describe ring ++/// information words located in PKA_BUFFER_RAM. Ring information includes ++/// base addresses, size and statistics. ++/// Return: 0 on success, -errno on failure. ++typedef struct // Bluefield specific ring information ++{ ++ /// Base address of the command descriptor ring. ++ uint64_t cmmd_base; ++ ++ /// Base address of the result descriptor ring. ++ uint64_t rslt_base; ++ ++ /// Size of a command ring in number of descriptors, minus 1. ++ /// Minimum value is 0 (for 1 descriptor); maximum value is ++ /// 65535 (for 64K descriptors). ++ uint16_t size; ++ ++ /// This field specifies the size (in 32-bit words) of the ++ /// space that PKI command and result descriptor occupies on ++ /// the Host. ++ uint16_t host_desc_size : 10; ++ ++ /// Indicates whether the result ring delivers results strictly ++ /// in-order ('1') or that result descriptors are written to the ++ /// result ring as soon as they become available, so out-of-order ++ /// ('0'). ++ uint8_t in_order : 1; ++ ++ /// Read pointer of the command descriptor ring. ++ uint16_t cmmd_rd_ptr; ++ ++ /// Write pointer of the result descriptor ring. ++ uint16_t rslt_wr_ptr; ++ ++ /// Read statistics of the command descriptor ring. ++ uint16_t cmmd_rd_stats; ++ ++ /// Write statistics of the result descriptor ring. ++ uint16_t rslt_wr_stats; ++ ++} pka_dev_hw_ring_info_t; ++#define PKA_GET_RING_INFO _IOWR(PKA_IOC_TYPE, 0x1, pka_dev_hw_ring_info_t) ++ ++/// PKA_CLEAR_RING_COUNTERS - _IO(PKA_IOC_TYPE, 0x2) ++/// ++/// Clear counters. This is intended to reset all command and result counters. ++/// Return: 0 on success, -errno on failure. ++#define PKA_CLEAR_RING_COUNTERS _IO(PKA_IOC_TYPE, 0x2) ++ ++/// PKA_GET_RANDOM_BYTES - _IOWR(PKA_IOC_TYPE, 0x3, pka_dev_trng_info_t) ++/// ++/// Get random bytes from True Random Number Generator(TRNG). ++/// Return: 0 on success, -errno on failure. ++typedef struct // True Random Number Generator information ++{ ++ /// Number of random bytes in the buffer; Length of the buffer. ++ uint32_t count; ++ ++ /// Data buffer to hold the random bytes. ++ uint8_t *data; ++ ++} pka_dev_trng_info_t; ++#define PKA_GET_RANDOM_BYTES _IOWR(PKA_IOC_TYPE, 0x3, pka_dev_trng_info_t) ++ ++#endif // __PKA_IOCTL_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_mmio.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_mmio.h +new file mode 100644 +index 000000000..c70823c2a +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_mmio.h +@@ -0,0 +1,49 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_MMIO_H__ ++#define __PKA_MMIO_H__ ++ ++ ++/// Macros for standard MMIO functions. ++ ++#include ++#include ++#include ++ ++#define pka_mmio_read64(addr) readq_relaxed(addr) ++#define pka_mmio_write64(addr, val) writeq_relaxed((val), (addr)) ++#define pka_mmio_read(addr) pka_mmio_read64(addr) ++#define pka_mmio_write(addr, val) pka_mmio_write64((addr), (val)) ++ ++#endif // __PKA_MMIO_H__ +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ring.h b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ring.h +new file mode 100644 +index 000000000..be56b61ee +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_ring.h +@@ -0,0 +1,276 @@ ++// ++// BSD LICENSE ++// ++// Copyright(c) 2016 Mellanox Technologies, Ltd. All rights reserved. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions ++// are met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in ++// the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Mellanox Technologies nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++ ++#ifndef __PKA_RING_H__ ++#define __PKA_RING_H__ ++ ++/// ++/// @file ++/// ++/// This file forms an interface to the BlueField Public Key Accelerator based ++/// on EIP-154. ++/// ++/// Rings are used as a communication mechanism between ARM cores (controller) ++/// and the farm engines controlled by EIP-154 master firmware. ++/// ++/// Note that the API defines data stuctures and functions to manage rings ++/// within window RAM, and to enqueue/dequeue descriptors. Rings are considered ++/// as a memory of descriptors (command/result descriptors) using finite size ++/// circular queue and a couple of control status registers (count registers). ++/// ++ ++ ++#include ++ ++#ifdef PKA_LIB_RING_DEBUG ++// A structure that stores the ring statistics. ++typedef struct ++{ ++ uint64_t enq_success_cmd; ///< Cmd descriptors successfully enqueued. ++ uint64_t enq_fail_cmd; ///< Cmd descriptors that failed to be enqueued. ++ uint64_t deq_success_rslt; ///< Rslt descriptors successfully dequeued. ++ uint64_t deq_fail_rslt; ///< Rslt descriptors that failed to be dequeued. ++} pka_ring_debug_stats __pka_cache_aligned; ++#endif ++ ++#ifdef PKA_LIB_RING_DEBUG ++#define __RING_STAT_ADD(r, name, n) ({ ##r##->stats.##name += 1; }) ++#else ++#define __RING_STAT_ADD(r, name, n) do {} while(0) ++#endif ++ ++/// Bluefield PKA command descriptor. ++typedef struct // 64 bytes long. 64 bytes aligned ++{ ++ uint64_t pointer_a; ++ uint64_t pointer_b; ++ uint64_t pointer_c; ++ uint64_t pointer_d; ++ uint64_t tag; ++ uint64_t pointer_e; ++ ++#ifdef __AARCH64EB__ ++ uint64_t linked : 1; ++ uint64_t driver_status : 2; ++ uint64_t odd_powers : 5; ///< shiftCnt for shift ops ++ uint64_t kdk : 2; ///< Key Decryption Key number ++ uint64_t encrypted_mask : 6; ++ uint64_t rsvd_3 : 8; ++ uint64_t command : 8; ++ uint64_t rsvd_2 : 5; ++ uint64_t length_b : 9; ++ uint64_t output_attr : 1; ++ uint64_t input_attr : 1; ++ uint64_t rsvd_1 : 5; ++ uint64_t length_a : 9; ++ uint64_t rsvd_0 : 2; ++#else ++ uint64_t rsvd_0 : 2; ++ uint64_t length_a : 9; ++ uint64_t rsvd_1 : 5; ++ uint64_t input_attr : 1; ++ uint64_t output_attr : 1; ++ uint64_t length_b : 9; ++ uint64_t rsvd_2 : 5; ++ uint64_t command : 8; ++ uint64_t rsvd_3 : 8; ++ uint64_t encrypted_mask : 6; ++ uint64_t kdk : 2; ///< Key Decryption Key number ++ uint64_t odd_powers : 5; ///< shiftCnt for shift ops ++ uint64_t driver_status : 2; ++ uint64_t linked : 1; ++#endif ++ ++ uint64_t rsvd_4; ++} pka_ring_hw_cmd_desc_t; ++ ++#define CMD_DESC_SIZE sizeof(pka_ring_hw_cmd_desc_t) // Must be 64 ++ ++/// Bluefield PKA result descriptor. ++typedef struct // 64 bytes long. 64 bytes aligned ++{ ++ uint64_t pointer_a; ++ uint64_t pointer_b; ++ uint64_t pointer_c; ++ uint64_t pointer_d; ++ uint64_t tag; ++ ++#ifdef __AARCH64EB__ ++ uint64_t rsvd_5 : 13; ++ uint64_t cmp_result : 3; ++ uint64_t modulo_is_0 : 1; ++ uint64_t rsvd_4 : 2; ++ uint64_t modulo_msw_offset : 11; ++ uint64_t rsvd_3 : 2; ++ uint64_t rsvd_2 : 11; ++ uint64_t main_result_msb_offset : 5; ++ uint64_t result_is_0 : 1; ++ uint64_t rsvd_1 : 2; ++ uint64_t main_result_msw_offset : 11; ++ uint64_t rsvd_0 : 2; ++ ++ uint64_t linked : 1; ++ uint64_t driver_status : 2; ///< Always written to 0 ++ uint64_t odd_powers : 5; ///< shiftCnt for shift ops ++ uint64_t kdk : 2; ///< Key Decryption Key number ++ uint64_t encrypted_mask : 6; ++ uint64_t result_code : 8; ++ uint64_t command : 8; ++ uint64_t rsvd_8 : 5; ++ uint64_t length_b : 9; ++ uint64_t output_attr : 1; ++ uint64_t input_attr : 1; ++ uint64_t rsvd_7 : 5; ++ uint64_t length_a : 9; ++ uint64_t rsvd_6 : 2; ++#else ++ uint64_t rsvd_0 : 2; ++ uint64_t main_result_msw_offset : 11; ++ uint64_t rsvd_1 : 2; ++ uint64_t result_is_0 : 1; ++ uint64_t main_result_msb_offset : 5; ++ uint64_t rsvd_2 : 11; ++ uint64_t rsvd_3 : 2; ++ uint64_t modulo_msw_offset : 11; ++ uint64_t rsvd_4 : 2; ++ uint64_t modulo_is_0 : 1; ++ uint64_t cmp_result : 3; ++ uint64_t rsvd_5 : 13; ++ ++ uint64_t rsvd_6 : 2; ++ uint64_t length_a : 9; ++ uint64_t rsvd_7 : 5; ++ uint64_t input_attr : 1; ++ uint64_t output_attr : 1; ++ uint64_t length_b : 9; ++ uint64_t rsvd_8 : 5; ++ uint64_t command : 8; ++ uint64_t result_code : 8; ++ uint64_t encrypted_mask : 6; ++ uint64_t kdk : 2; ///< Key Decryption Key number ++ uint64_t odd_powers : 5; ///< shiftCnt for shift ops ++ uint64_t driver_status : 2; ///< Always written to 0 ++ uint64_t linked : 1; ++#endif ++ ++ uint64_t rsvd_9; ++} pka_ring_hw_rslt_desc_t; ++ ++#define RESULT_DESC_SIZE sizeof(pka_ring_hw_rslt_desc_t) // Must be 64 ++ ++/// Describes a PKA command/result ring as used by the hardware. A pair of ++/// command and result rings in PKA window memory, and the data memory used ++/// by the commands. ++typedef struct ++{ ++ uint32_t num_descs; ///< total number of descriptors in the ring. ++ ++ uint32_t cmd_ring_base; ///< base address of the command ring. ++ uint32_t cmd_idx; ///< index of the command in a ring. ++ ++ uint32_t rslt_ring_base; ///< base address of the result ring. ++ uint32_t rslt_idx; ///< index of the result in a ring. ++ ++ uint32_t operands_base; ///< operands memory base address. ++ uint32_t operands_end; ///< end address of operands memory. ++ ++ uint32_t desc_size; ///< size of each element in the ring. ++ ++ uint64_t cmd_desc_mask; ///< bitmask of free(0)/in_use(1) cmd descriptors. ++ uint32_t cmd_desc_cnt; ///< number of command descriptors currently in use. ++ uint32_t rslt_desc_cnt; ///< number of result descriptors currently ready. ++} pka_ring_desc_t; ++ ++/// This structure declares ring parameters which can be used by user interface. ++typedef struct ++{ ++ int fd; ///< file descriptor. ++ int group; ///< iommu group. ++ int container; ///< vfio cointainer ++ ++ uint32_t idx; ///< ring index. ++ uint32_t ring_id; ///< hardware ring identifier. ++ ++ uint64_t mem_off; ///< offset specific to window RAM region. ++ uint64_t mem_addr; ///< window RAM region address. ++ uint64_t mem_size; ///< window RAM region size. ++ ++ uint64_t reg_off; ///< offset specific to count registers region. ++ uint64_t reg_addr; ///< count registers region address. ++ uint64_t reg_size; ///< count registers region size. ++ ++ void *mem_ptr; ///< pointer to map-ped memory region. ++ void *reg_ptr; ///< pointer to map-ped counters region. ++ ++ pka_ring_desc_t ring_desc; ///< ring descriptor. ++ ++#ifdef PKA_LIB_RING_DEBUG ++ struct pka_ring_debug_stats stats; ++#endif ++ ++ uint8_t big_endian; ///< big endian byte order when enabled. ++} pka_ring_info_t; ++ ++typedef struct ++{ ++ uint32_t dst_offset; ///< operands desctination offset. ++ uint32_t max_dst_offset; ///< operands end offset. ++ ++ pka_ring_info_t *ring; ++} pka_ring_alloc_t; ++ ++// This sturcture encapsulates 'user data' information, it also includes ++// additional information useful for command processing and statistics. ++typedef struct ++{ ++ uint64_t valid; ///< if set to 'PKA_UDATA_INFO_VALID' then info is valid ++ uint64_t user_data; ///< opaque user address. ++ uint64_t cmd_num; ///< command request number. ++ uint8_t cmd_desc_idx; ///< index of the cmd descriptor in HW rings ++ uint8_t ring_num; ///< command request number. ++ uint8_t queue_num; ///< queue number. ++} pka_udata_info_t; ++ ++#define PKA_UDATA_INFO_VALID 0xDEADBEEF ++ ++// This structure consists of a data base to store user data information. ++// Note that a data base should be associated with a hardware ring. ++typedef struct ++{ ++ pka_udata_info_t entries[32]; // user data information entries. ++ uint8_t index : 5; // entry index. Wrapping is permitted. ++} pka_udata_db_t; ++ ++#endif /// __PKA_RING_H__ ++ ++ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0221-UBUNTU-SAUCE-platform-mellanox-Add-mlxbf-livefish-dr.patch b/platform/mellanox/non-upstream-patches/patches/0221-UBUNTU-SAUCE-platform-mellanox-Add-mlxbf-livefish-dr.patch new file mode 100644 index 0000000000..8f9c4430e5 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0221-UBUNTU-SAUCE-platform-mellanox-Add-mlxbf-livefish-dr.patch @@ -0,0 +1,340 @@ +From 9b0e85d738a43f737ed233e649fcda22b573d372 Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Tue, 5 Jul 2022 12:43:45 -0400 +Subject: [PATCH backport 5.10 22/63] UBUNTU: SAUCE: platform/mellanox: Add + mlxbf-livefish driver + +BugLink: https://launchpad.net/bugs/1980761 + +This patch adds the mlxbf-livefish driver which supports update +of the HCA firmware when in livefish mode. + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/platform/mellanox/Kconfig | 9 + + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/mellanox/mlxbf-livefish.c | 279 +++++++++++++++++++++ + 3 files changed, 289 insertions(+) + create mode 100644 drivers/platform/mellanox/mlxbf-livefish.c + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index 946bc2375..a5231c23a 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -80,6 +80,15 @@ config MLXBF_BOOTCTL + to the userspace tools, to be used in conjunction with the eMMC + device driver to do necessary initial swap of the boot partition. + ++config MLXBF_LIVEFISH ++ tristate "Mellanox BlueField livefish firmware update driver" ++ depends on ARM64 ++ help ++ If you say yes to this option, support will added for the ++ mlxbf-livefish driver. This driver allows MFT tools to ++ update ConnectX HCA firmware on a Mellanox BlueField SoC ++ when it is in livefish mode. ++ + config MLXBF_PMC + tristate "Mellanox BlueField Performance Monitoring Counters driver" + depends on ARM64 +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index 046347d3a..7c6393ebe 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o + obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o + obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o + obj-$(CONFIG_MLXBF_TRIO) += mlx-trio.o ++obj-$(CONFIG_MLXBF_LIVEFISH) += mlxbf-livefish.o + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o + obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o +diff --git a/drivers/platform/mellanox/mlxbf-livefish.c b/drivers/platform/mellanox/mlxbf-livefish.c +new file mode 100644 +index 000000000..c6150117d +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf-livefish.c +@@ -0,0 +1,279 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB ++ ++/* ++ * Mellanox BlueField HCA firmware burning driver. ++ * ++ * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. ++ * ++ * This driver supports burning firmware for the embedded HCA in the ++ * BlueField SoC. Typically firmware is burned through the PCI mlx5 ++ * driver directly, but when the existing firmware is not yet installed ++ * or invalid, the PCI mlx5 driver has no endpoint to bind to, and we ++ * use this driver instead. It provides a character device that gives ++ * access to the same hardware registers at the same offsets as the ++ * mlx5 PCI configuration space does. ++ * ++ * The first 1 MB of the space is available through the TRIO HCA ++ * mapping. However, the efuse area (128 bytes at offset 0x1c1600) is ++ * not available through the HCA mapping, but is available by mapping ++ * the TYU via the RSHIM, so we make it virtually appear at the ++ * correct offset in this driver. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_VERSION 2.0 ++#define STRINGIFY(s) #s ++ ++static size_t hca_size; ++static phys_addr_t hca_pa; ++static __iomem void *hca_va; ++ ++#define TYU_SIZE 0x80UL ++#define TYU_OFFSET 0x1c1600 ++static phys_addr_t tyu_pa; ++static __iomem void *tyu_va; ++ ++#define MLXBF_LF_BF1 1 ++#define MLXBF_LF_BF2 2 ++static int chip_version; ++ ++#define CRSPACE_SIZE (2 * 1024 * 1024) ++ ++/* ++ * A valid I/O must be entirely within CR space and not extend into ++ * any unmapped areas of CR space. We don't truncate I/O that extends ++ * past the end of the CR space region (unlike the behavior of, for ++ * example, simple_read_from_buffer) but instead just call the whole ++ * I/O invalid. We also enforce 4-byte alignment for all I/O. ++ */ ++static bool valid_range(loff_t offset, size_t len) ++{ ++ if (offset % 4 != 0 || len % 4 != 0) ++ return false; /* unaligned */ ++ if (offset >= 0 && offset + len <= hca_size) ++ return true; /* inside the HCA space */ ++ if (offset >= TYU_OFFSET && offset + len <= TYU_OFFSET + TYU_SIZE) ++ return true; /* inside the TYU space */ ++ return false; ++} ++ ++/* ++ * Read and write to CR space offsets; we assume valid_range(). ++ * Data crossing the TRIO CR Space bridge gets byte-swapped, so we swap ++ * it back. ++ */ ++ ++static u32 crspace_readl(int offset) ++{ ++ u32 data; ++ if (chip_version == MLXBF_LF_BF1) { ++ if (offset < TYU_OFFSET) ++ return swab32(readl_relaxed(hca_va + offset)); ++ else ++ return readl_relaxed(tyu_va + offset - TYU_OFFSET); ++ } else { ++ data = readl_relaxed(hca_va + offset); ++ } ++ return data; ++} ++ ++static void crspace_writel(u32 data, int offset) ++{ ++ if (chip_version == MLXBF_LF_BF1) { ++ if (offset < TYU_OFFSET) ++ writel_relaxed(swab32(data), hca_va + offset); ++ else ++ writel_relaxed(data, tyu_va + offset - TYU_OFFSET); ++ } else { ++ writel_relaxed(data, hca_va + offset); ++ } ++} ++ ++/* ++ * Note that you can seek to illegal areas within the livefish device, ++ * but you won't be able to read or write there. ++ */ ++static loff_t livefish_llseek(struct file *filp, loff_t offset, int whence) ++{ ++ if (offset % 4 != 0) ++ return -EINVAL; ++ return fixed_size_llseek(filp, offset, whence, CRSPACE_SIZE); ++} ++ ++static ssize_t livefish_read(struct file *filp, char __user *to, size_t len, ++ loff_t *ppos) ++{ ++ loff_t pos = *ppos; ++ size_t i; ++ int word; ++ ++ if (!valid_range(pos, len)) ++ return -EINVAL; ++ if (len == 0) ++ return 0; ++ for (i = 0; i < len; i += 4, pos += 4) { ++ word = crspace_readl(pos); ++ if (put_user(word, (int __user *)(to + i)) != 0) ++ break; ++ } ++ *ppos = pos; ++ return i ?: -EFAULT; ++} ++ ++static ssize_t livefish_write(struct file *filp, const char __user *from, ++ size_t len, loff_t *ppos) ++{ ++ loff_t pos = *ppos; ++ size_t i; ++ int word; ++ ++ if (!valid_range(pos, len)) ++ return -EINVAL; ++ if (len == 0) ++ return 0; ++ for (i = 0; i < len; i += 4, pos += 4) { ++ if (get_user(word, (int __user *)(from + i)) != 0) ++ break; ++ crspace_writel(word, pos); ++ } ++ *ppos = pos; ++ return i ?: -EFAULT; ++} ++ ++static const struct file_operations livefish_fops = { ++ .owner = THIS_MODULE, ++ .llseek = livefish_llseek, ++ .read = livefish_read, ++ .write = livefish_write, ++}; ++ ++/* This name causes the correct semantics for the Mellanox MST tools. */ ++static struct miscdevice livefish_dev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "bf-livefish", ++ .mode = 0600, ++ .fops = &livefish_fops ++}; ++ ++/* Release any VA or PA mappings that have been set up. */ ++static void livefish_cleanup_mappings(void) ++{ ++ if (hca_va) ++ iounmap(hca_va); ++ if (hca_pa) ++ release_mem_region(hca_pa, hca_size); ++ if (tyu_va) ++ iounmap(tyu_va); ++ if (tyu_pa) ++ release_mem_region(tyu_pa, TYU_SIZE); ++} ++ ++static int livefish_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int ret = -EINVAL; ++ struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev); ++ const char *hid = acpi_device_hid(acpi_dev); ++ ++ if (strcmp(hid, "MLNXBF05") == 0) ++ chip_version = MLXBF_LF_BF1; ++ else if (strcmp(hid, "MLNXBF25") == 0) ++ chip_version = MLXBF_LF_BF2; ++ else { ++ dev_err(&pdev->dev, "Invalid device ID %s\n", hid); ++ return -ENODEV; ++ } ++ ++ /* Find and map the HCA region */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) ++ return -ENODEV; ++ ++ if (request_mem_region(res->start, resource_size(res), ++ "LiveFish (HCA)") == NULL) ++ return -EINVAL; ++ hca_pa = res->start; ++ hca_va = ioremap(res->start, resource_size(res)); ++ hca_size = resource_size(res); ++ dev_info(&pdev->dev, "HCA Region PA: 0x%llx Size: 0x%llx\n", ++ res->start, resource_size(res)); ++ if (hca_va == NULL) ++ goto err; ++ ++ if (chip_version == MLXBF_LF_BF1) { ++ /* Find and map the TYU efuse region */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (res == NULL) ++ goto err; ++ if (resource_size(res) < TYU_SIZE) { ++ dev_warn(&pdev->dev, "TYU space too small: %#lx, not %#lx\n", ++ (long)resource_size(res), TYU_SIZE); ++ goto err; ++ } ++ if (request_mem_region(res->start, TYU_SIZE, ++ "LiveFish (TYU)") == NULL) ++ goto err; ++ tyu_pa = res->start; ++ tyu_va = ioremap(res->start, TYU_SIZE); ++ if (tyu_va == NULL) ++ goto err; ++ } ++ ++ ret = misc_register(&livefish_dev); ++ if (ret) ++ goto err; ++ ++ dev_info(&pdev->dev, "probed\n"); ++ ++ return 0; ++ ++err: ++ livefish_cleanup_mappings(); ++ return ret; ++} ++ ++static int livefish_remove(struct platform_device *pdev) ++{ ++ misc_deregister(&livefish_dev); ++ livefish_cleanup_mappings(); ++ return 0; ++} ++ ++static const struct of_device_id livefish_of_match[] = { ++ { .compatible = "mellanox,mlxbf-livefish" }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, livefish_of_match); ++ ++static const struct acpi_device_id livefish_acpi_match[] = { ++ { "MLNXBF05", 0 }, ++ { "MLNXBF25", 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(acpi, livefish_acpi_match); ++ ++static struct platform_driver livefish_driver = { ++ .driver = { ++ .name = "mlxbf-livefish", ++ .of_match_table = livefish_of_match, ++ .acpi_match_table = ACPI_PTR(livefish_acpi_match), ++ }, ++ .probe = livefish_probe, ++ .remove = livefish_remove, ++}; ++ ++module_platform_driver(livefish_driver); ++ ++MODULE_DESCRIPTION("Mellanox BlueField LiveFish driver"); ++MODULE_AUTHOR("Shravan Kumar Ramani "); ++MODULE_VERSION(STRINGIFY(DRIVER_VERSION)); ++MODULE_LICENSE("Dual BSD/GPL"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0222-workqueue-Add-resource-managed-version-of-delayed-wo.patch b/platform/mellanox/non-upstream-patches/patches/0222-workqueue-Add-resource-managed-version-of-delayed-wo.patch new file mode 100644 index 0000000000..bc42afa803 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0222-workqueue-Add-resource-managed-version-of-delayed-wo.patch @@ -0,0 +1,84 @@ +From 48998b5918e9320b47c26c78d3b14cc3e1faac8a Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Tue, 23 Mar 2021 15:56:17 +0200 +Subject: [PATCH backport 5.10 23/63] workqueue: Add resource managed version + of delayed work init + +A few drivers which need a delayed work-queue must cancel work at driver +detach. Some of those implement remove() solely for this purpose. Help +drivers to avoid unnecessary remove and error-branch implementation by +adding managed verision of delayed work initialization. This will also +help drivers to avoid mixing manual and devm based unwinding when other +resources are handled by devm. + +Reviewed-by: Hans de Goede +Signed-off-by: Matti Vaittinen +Link: https://lore.kernel.org/r/51769ea4668198deb798fe47fcfb5f5288d61586.1616506559.git.matti.vaittinen@fi.rohmeurope.com +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/devm-helpers.h | 53 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + create mode 100644 include/linux/devm-helpers.h + +diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h +new file mode 100644 +index 000000000..f64e0c9f3 +--- /dev/null ++++ b/include/linux/devm-helpers.h +@@ -0,0 +1,53 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++#ifndef __LINUX_DEVM_HELPERS_H ++#define __LINUX_DEVM_HELPERS_H ++ ++/* ++ * Functions which do automatically cancel operations or release resources upon ++ * driver detach. ++ * ++ * These should be helpful to avoid mixing the manual and devm-based resource ++ * management which can be source of annoying, rarely occurring, ++ * hard-to-reproduce bugs. ++ * ++ * Please take into account that devm based cancellation may be performed some ++ * time after the remove() is ran. ++ * ++ * Thus mixing devm and manual resource management can easily cause problems ++ * when unwinding operations with dependencies. IRQ scheduling a work in a queue ++ * is typical example where IRQs are often devm-managed and WQs are manually ++ * cleaned at remove(). If IRQs are not manually freed at remove() (and this is ++ * often the case when we use devm for IRQs) we have a period of time after ++ * remove() - and before devm managed IRQs are freed - where new IRQ may fire ++ * and schedule a work item which won't be cancelled because remove() was ++ * already ran. ++ */ ++ ++#include ++#include ++ ++static inline void devm_delayed_work_drop(void *res) ++{ ++ cancel_delayed_work_sync(res); ++} ++ ++/** ++ * devm_delayed_work_autocancel - Resource-managed work allocation ++ * @dev: Device which lifetime work is bound to ++ * @pdata: work to be cancelled when driver is detached ++ * ++ * Initialize work which is automatically cancelled when driver is detached. ++ * A few drivers need delayed work which must be cancelled before driver ++ * is detached to avoid accessing removed resources. ++ * devm_delayed_work_autocancel() can be used to omit the explicit ++ * cancelleation when driver is detached. ++ */ ++static inline int devm_delayed_work_autocancel(struct device *dev, ++ struct delayed_work *w, ++ work_func_t worker) ++{ ++ INIT_DELAYED_WORK(w, worker); ++ return devm_add_action(dev, devm_delayed_work_drop, w); ++} ++ ++#endif +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0223-devm-helpers-Fix-devm_delayed_work_autocancel-kernel.patch b/platform/mellanox/non-upstream-patches/patches/0223-devm-helpers-Fix-devm_delayed_work_autocancel-kernel.patch new file mode 100644 index 0000000000..fde92e0392 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0223-devm-helpers-Fix-devm_delayed_work_autocancel-kernel.patch @@ -0,0 +1,50 @@ +From 64006a4de979012d8a55e67690b9ce743d5be433 Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Wed, 21 Apr 2021 21:11:32 +0300 +Subject: [PATCH backport 5.10 24/63] devm-helpers: Fix + devm_delayed_work_autocancel() kerneldoc + +The kerneldoc for devm_delayed_work_autocancel() contains invalid +parameter description. + +Fix the parameter description. And while at it - make it more obvous that +this function operates on delayed_work. That helps differentiating with +resource-managed INIT_WORK description (which should follow in near future) + +Fixes: 0341ce544394 ("workqueue: Add resource managed version of delayed work init") +Reviewed-by: Hans de Goede +Signed-off-by: Matti Vaittinen +Link: https://lore.kernel.org/r/db3a8b4b8899fdf109a0cc760807de12d3b4f09b.1619028482.git.matti.vaittinen@fi.rohmeurope.com +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/devm-helpers.h | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h +index f64e0c9f3..f40f77717 100644 +--- a/include/linux/devm-helpers.h ++++ b/include/linux/devm-helpers.h +@@ -32,13 +32,14 @@ static inline void devm_delayed_work_drop(void *res) + } + + /** +- * devm_delayed_work_autocancel - Resource-managed work allocation +- * @dev: Device which lifetime work is bound to +- * @pdata: work to be cancelled when driver is detached ++ * devm_delayed_work_autocancel - Resource-managed delayed work allocation ++ * @dev: Device which lifetime work is bound to ++ * @w: Work item to be queued ++ * @worker: Worker function + * +- * Initialize work which is automatically cancelled when driver is detached. +- * A few drivers need delayed work which must be cancelled before driver +- * is detached to avoid accessing removed resources. ++ * Initialize delayed work which is automatically cancelled when driver is ++ * detached. A few drivers need delayed work which must be cancelled before ++ * driver is detached to avoid accessing removed resources. + * devm_delayed_work_autocancel() can be used to omit the explicit + * cancelleation when driver is detached. + */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0224-devm-helpers-Add-resource-managed-version-of-work-in.patch b/platform/mellanox/non-upstream-patches/patches/0224-devm-helpers-Add-resource-managed-version-of-work-in.patch new file mode 100644 index 0000000000..b37400e15d --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0224-devm-helpers-Add-resource-managed-version-of-work-in.patch @@ -0,0 +1,59 @@ +From b73a2da62dcb4d975c1b226280868f951533142b Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Tue, 8 Jun 2021 13:09:34 +0300 +Subject: [PATCH backport 5.10 25/63] devm-helpers: Add resource managed + version of work init + +A few drivers which need a work-queue must cancel work at driver detach. +Some of those implement remove() solely for this purpose. Help drivers to +avoid unnecessary remove and error-branch implementation by adding managed +verision of work initialization. This will also help drivers to avoid +mixing manual and devm based unwinding when other resources are handled by +devm. + +Signed-off-by: Matti Vaittinen +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/94ff4175e7f2ff134ed2fa7d6e7641005cc9784b.1623146580.git.matti.vaittinen@fi.rohmeurope.com +Signed-off-by: Hans de Goede +--- + include/linux/devm-helpers.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h +index f40f77717..748918022 100644 +--- a/include/linux/devm-helpers.h ++++ b/include/linux/devm-helpers.h +@@ -51,4 +51,29 @@ static inline int devm_delayed_work_autocancel(struct device *dev, + return devm_add_action(dev, devm_delayed_work_drop, w); + } + ++static inline void devm_work_drop(void *res) ++{ ++ cancel_work_sync(res); ++} ++ ++/** ++ * devm_work_autocancel - Resource-managed work allocation ++ * @dev: Device which lifetime work is bound to ++ * @w: Work to be added (and automatically cancelled) ++ * @worker: Worker function ++ * ++ * Initialize work which is automatically cancelled when driver is detached. ++ * A few drivers need to queue work which must be cancelled before driver ++ * is detached to avoid accessing removed resources. ++ * devm_work_autocancel() can be used to omit the explicit ++ * cancelleation when driver is detached. ++ */ ++static inline int devm_work_autocancel(struct device *dev, ++ struct work_struct *w, ++ work_func_t worker) ++{ ++ INIT_WORK(w, worker); ++ return devm_add_action(dev, devm_work_drop, w); ++} ++ + #endif +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0225-UBUNTU-SAUCE-Add-support-to-pwr-mlxbf.c-driver.patch b/platform/mellanox/non-upstream-patches/patches/0225-UBUNTU-SAUCE-Add-support-to-pwr-mlxbf.c-driver.patch new file mode 100644 index 0000000000..a293cc8fa7 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0225-UBUNTU-SAUCE-Add-support-to-pwr-mlxbf.c-driver.patch @@ -0,0 +1,158 @@ +From 66c331a304f41a5f1806a827b42bc97ba090c745 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Tue, 5 Jul 2022 14:49:03 -0400 +Subject: [PATCH backport 5.10 26/63] UBUNTU: SAUCE: Add support to pwr-mlxbf.c + driver + +BugLink: https://launchpad.net/bugs/1980768 + +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Ike Panhc + +1 + +Signed-off-by: Ike Panhc +--- + drivers/power/reset/Kconfig | 6 ++ + drivers/power/reset/Makefile | 1 + + drivers/power/reset/pwr-mlxbf.c | 103 ++++++++++++++++++++++++++++++++ + 3 files changed, 110 insertions(+) + create mode 100644 drivers/power/reset/pwr-mlxbf.c + +diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig +index d55b3727e..41ee02f87 100644 +--- a/drivers/power/reset/Kconfig ++++ b/drivers/power/reset/Kconfig +@@ -284,5 +284,11 @@ config NVMEM_REBOOT_MODE + then the bootloader can read it and take different + action according to the mode. + ++config POWER_MLXBF ++ tristate "Mellanox BlueField power handling driver" ++ depends on (GPIO_MLXBF2 && ACPI) ++ help ++ This driver supports reset or low power mode handling for Mellanox BlueField. ++ + endif + +diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile +index c51eceba9..51801a5b5 100644 +--- a/drivers/power/reset/Makefile ++++ b/drivers/power/reset/Makefile +@@ -33,3 +33,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o + obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o + obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o + obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o ++obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o +diff --git a/drivers/power/reset/pwr-mlxbf.c b/drivers/power/reset/pwr-mlxbf.c +new file mode 100644 +index 000000000..3f587a372 +--- /dev/null ++++ b/drivers/power/reset/pwr-mlxbf.c +@@ -0,0 +1,103 @@ ++// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause ++ ++/* ++ * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_VERSION "1.1" ++ ++struct pwr_mlxbf { ++ struct work_struct send_work; ++ const char *hid; ++}; ++ ++static void pwr_mlxbf_send_work(struct work_struct *work) ++{ ++ acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1); ++} ++ ++static irqreturn_t pwr_mlxbf_irq(int irq, void *ptr) ++{ ++ const char *rst_pwr_hid = "MLNXBF24"; ++ const char *low_pwr_hid = "MLNXBF29"; ++ struct pwr_mlxbf *priv = ptr; ++ ++ if (!strncmp(priv->hid, rst_pwr_hid, 8)) ++ emergency_restart(); ++ ++ if (!strncmp(priv->hid, low_pwr_hid, 8)) ++ schedule_work(&priv->send_work); ++ ++ return IRQ_HANDLED; ++} ++ ++static int pwr_mlxbf_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct acpi_device *adev; ++ struct pwr_mlxbf *priv; ++ const char *hid; ++ int irq, err; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ adev = ACPI_COMPANION(dev); ++ if (!adev) ++ return -ENXIO; ++ ++ hid = acpi_device_hid(adev); ++ priv->hid = hid; ++ ++ irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0); ++ if (irq < 0) ++ return dev_err_probe(dev, irq, "Error getting %s irq.\n", priv->hid); ++ ++ err = devm_work_autocancel(dev, &priv->send_work, pwr_mlxbf_send_work); ++ if (err) ++ return err; ++ ++ err = devm_request_irq(dev, irq, pwr_mlxbf_irq, 0, hid, priv); ++ if (err) ++ dev_err(dev, "Failed request of %s irq\n", priv->hid); ++ ++ return err; ++} ++ ++static const struct acpi_device_id __maybe_unused pwr_mlxbf_acpi_match[] = { ++ { "MLNXBF24", 0 }, ++ { "MLNXBF29", 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(acpi, pwr_mlxbf_acpi_match); ++ ++static struct platform_driver pwr_mlxbf_driver = { ++ .driver = { ++ .name = "pwr_mlxbf", ++ .acpi_match_table = pwr_mlxbf_acpi_match, ++ }, ++ .probe = pwr_mlxbf_probe, ++}; ++ ++module_platform_driver(pwr_mlxbf_driver); ++ ++MODULE_DESCRIPTION("Mellanox BlueField power driver"); ++MODULE_AUTHOR("Asmaa Mnebhi "); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(DRV_VERSION); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0226-Add-Mellanox-BlueField-Gigabit-Ethernet-driver.patch b/platform/mellanox/non-upstream-patches/patches/0226-Add-Mellanox-BlueField-Gigabit-Ethernet-driver.patch new file mode 100644 index 0000000000..eff1c335a0 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0226-Add-Mellanox-BlueField-Gigabit-Ethernet-driver.patch @@ -0,0 +1,2206 @@ +From 0e3f14e4ef0018a4cd75c0620a58484dae635e5d Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Thu, 24 Jun 2021 21:11:46 -0400 +Subject: [PATCH backport 5.10 27/63] Add Mellanox BlueField Gigabit Ethernet + driver + +This patch adds build and driver logic for the "mlxbf_gige" +Ethernet driver from Mellanox Technologies. The second +generation BlueField SoC from Mellanox supports an +out-of-band GigaBit Ethernet management port to the Arm +subsystem. This driver supports TCP/IP network connectivity +for that port, and provides back-end routines to handle +basic ethtool requests. + +The driver interfaces to the Gigabit Ethernet block of +BlueField SoC via MMIO accesses to registers, which contain +control information or pointers describing transmit and +receive resources. There is a single transmit queue, and +the port supports transmit ring sizes of 4 to 256 entries. +There is a single receive queue, and the port supports +receive ring sizes of 32 to 32K entries. The transmit and +receive rings are allocated from DMA coherent memory. There +is a 16-bit producer and consumer index per ring to denote +software ownership and hardware ownership, respectively. + +The main driver logic such as probe(), remove(), and netdev +ops are in "mlxbf_gige_main.c". Logic in "mlxbf_gige_rx.c" +and "mlxbf_gige_tx.c" handles the packet processing for +receive and transmit respectively. + +The logic in "mlxbf_gige_ethtool.c" supports the handling +of some basic ethtool requests: get driver info, get ring +parameters, get registers, and get statistics. + +The logic in "mlxbf_gige_mdio.c" is the driver controlling +the Mellanox BlueField hardware that interacts with a PHY +device via MDIO/MDC pins. This driver does the following: + - At driver probe time, it configures several BlueField MDIO + parameters such as sample rate, full drive, voltage and MDC + - It defines functions to read and write MDIO registers and + registers the MDIO bus. + - It defines the phy interrupt handler reporting a + link up/down status change + - This driver's probe is invoked from the main driver logic + while the phy interrupt handler is registered in ndo_open. + +Driver limitations + - Only supports 1Gbps speed + - Only supports GMII protocol + - Supports maximum packet size of 2KB + - Does not support scatter-gather buffering + +Testing + - Successful build of kernel for ARM64, ARM32, X86_64 + - Tested ARM64 build on FastModels & Palladium + - Tested ARM64 build on several Mellanox boards that are built with + the BlueField-2 SoC. The testing includes coverage in the areas + of networking (e.g. ping, iperf, ifconfig, route), file transfers + (e.g. SCP), and various ethtool options relevant to this driver. + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +Reviewed-by: Liming Sun +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/Kconfig | 1 + + drivers/net/ethernet/mellanox/Makefile | 1 + + .../net/ethernet/mellanox/mlxbf_gige/Kconfig | 13 + + .../net/ethernet/mellanox/mlxbf_gige/Makefile | 11 + + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 190 ++++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | 137 ++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_gpio.c | 212 ++++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_intr.c | 142 ++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 452 ++++++++++++++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 187 ++++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_regs.h | 78 +++ + .../mellanox/mlxbf_gige/mlxbf_gige_rx.c | 320 +++++++++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_tx.c | 284 +++++++++++ + 13 files changed, 2028 insertions(+) + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/Makefile + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_tx.c + +diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig +index ff6613a5c..b4f66eb9d 100644 +--- a/drivers/net/ethernet/mellanox/Kconfig ++++ b/drivers/net/ethernet/mellanox/Kconfig +@@ -22,5 +22,6 @@ source "drivers/net/ethernet/mellanox/mlx4/Kconfig" + source "drivers/net/ethernet/mellanox/mlx5/core/Kconfig" + source "drivers/net/ethernet/mellanox/mlxsw/Kconfig" + source "drivers/net/ethernet/mellanox/mlxfw/Kconfig" ++source "drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig" + + endif # NET_VENDOR_MELLANOX +diff --git a/drivers/net/ethernet/mellanox/Makefile b/drivers/net/ethernet/mellanox/Makefile +index 79773ac33..d4b5f547a 100644 +--- a/drivers/net/ethernet/mellanox/Makefile ++++ b/drivers/net/ethernet/mellanox/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_MLX4_CORE) += mlx4/ + obj-$(CONFIG_MLX5_CORE) += mlx5/core/ + obj-$(CONFIG_MLXSW_CORE) += mlxsw/ + obj-$(CONFIG_MLXFW) += mlxfw/ ++obj-$(CONFIG_MLXBF_GIGE) += mlxbf_gige/ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig b/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig +new file mode 100644 +index 000000000..4cdebafaf +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig +@@ -0,0 +1,13 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++# ++# Mellanox GigE driver configuration ++# ++ ++config MLXBF_GIGE ++ tristate "Mellanox Technologies BlueField Gigabit Ethernet support" ++ depends on (ARM64 && ACPI) || COMPILE_TEST ++ select PHYLIB ++ help ++ The second generation BlueField SoC from Mellanox Technologies ++ supports an out-of-band Gigabit Ethernet management port to the ++ Arm subsystem. +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +new file mode 100644 +index 000000000..e57c1375f +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++obj-$(CONFIG_MLXBF_GIGE) += mlxbf_gige.o ++ ++mlxbf_gige-y := mlxbf_gige_ethtool.o \ ++ mlxbf_gige_gpio.o \ ++ mlxbf_gige_intr.o \ ++ mlxbf_gige_main.o \ ++ mlxbf_gige_mdio.o \ ++ mlxbf_gige_rx.o \ ++ mlxbf_gige_tx.o +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +new file mode 100644 +index 000000000..e3509e69e +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -0,0 +1,190 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ ++ ++/* Header file for Gigabit Ethernet driver for Mellanox BlueField SoC ++ * - this file contains software data structures and any chip-specific ++ * data structures (e.g. TX WQE format) that are memory resident. ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#ifndef __MLXBF_GIGE_H__ ++#define __MLXBF_GIGE_H__ ++ ++#include ++#include ++#include ++#include ++ ++/* The silicon design supports a maximum RX ring size of ++ * 32K entries. Based on current testing this maximum size ++ * is not required to be supported. Instead the RX ring ++ * will be capped at a realistic value of 1024 entries. ++ */ ++#define MLXBF_GIGE_MIN_RXQ_SZ 32 ++#define MLXBF_GIGE_MAX_RXQ_SZ 1024 ++#define MLXBF_GIGE_DEFAULT_RXQ_SZ 128 ++ ++#define MLXBF_GIGE_MIN_TXQ_SZ 4 ++#define MLXBF_GIGE_MAX_TXQ_SZ 256 ++#define MLXBF_GIGE_DEFAULT_TXQ_SZ 128 ++ ++#define MLXBF_GIGE_DEFAULT_BUF_SZ 2048 ++ ++#define MLXBF_GIGE_DMA_PAGE_SZ 4096 ++#define MLXBF_GIGE_DMA_PAGE_SHIFT 12 ++ ++/* There are four individual MAC RX filters. Currently ++ * two of them are being used: one for the broadcast MAC ++ * (index 0) and one for local MAC (index 1) ++ */ ++#define MLXBF_GIGE_BCAST_MAC_FILTER_IDX 0 ++#define MLXBF_GIGE_LOCAL_MAC_FILTER_IDX 1 ++ ++/* Define for broadcast MAC literal */ ++#define BCAST_MAC_ADDR 0xFFFFFFFFFFFF ++ ++/* There are three individual interrupts: ++ * 1) Errors, "OOB" interrupt line ++ * 2) Receive Packet, "OOB_LLU" interrupt line ++ * 3) LLU and PLU Events, "OOB_PLU" interrupt line ++ */ ++#define MLXBF_GIGE_ERROR_INTR_IDX 0 ++#define MLXBF_GIGE_RECEIVE_PKT_INTR_IDX 1 ++#define MLXBF_GIGE_LLU_PLU_INTR_IDX 2 ++#define MLXBF_GIGE_PHY_INT_N 3 ++ ++#define MLXBF_GIGE_MDIO_DEFAULT_PHY_ADDR 0x3 ++ ++#define MLXBF_GIGE_DEFAULT_PHY_INT_GPIO 12 ++ ++struct mlxbf_gige_stats { ++ u64 hw_access_errors; ++ u64 tx_invalid_checksums; ++ u64 tx_small_frames; ++ u64 tx_index_errors; ++ u64 sw_config_errors; ++ u64 sw_access_errors; ++ u64 rx_truncate_errors; ++ u64 rx_mac_errors; ++ u64 rx_din_dropped_pkts; ++ u64 tx_fifo_full; ++ u64 rx_filter_passed_pkts; ++ u64 rx_filter_discard_pkts; ++}; ++ ++struct mlxbf_gige { ++ void __iomem *base; ++ void __iomem *llu_base; ++ void __iomem *plu_base; ++ struct device *dev; ++ struct net_device *netdev; ++ struct platform_device *pdev; ++ void __iomem *mdio_io; ++ struct mii_bus *mdiobus; ++ void __iomem *gpio_io; ++ struct irq_domain *irqdomain; ++ u32 phy_int_gpio_mask; ++ spinlock_t lock; /* for packet processing indices */ ++ spinlock_t gpio_lock; /* for GPIO bus access */ ++ u16 rx_q_entries; ++ u16 tx_q_entries; ++ u64 *tx_wqe_base; ++ dma_addr_t tx_wqe_base_dma; ++ u64 *tx_wqe_next; ++ u64 *tx_cc; ++ dma_addr_t tx_cc_dma; ++ dma_addr_t *rx_wqe_base; ++ dma_addr_t rx_wqe_base_dma; ++ u64 *rx_cqe_base; ++ dma_addr_t rx_cqe_base_dma; ++ u16 tx_pi; ++ u16 prev_tx_ci; ++ u64 error_intr_count; ++ u64 rx_intr_count; ++ u64 llu_plu_intr_count; ++ struct sk_buff *rx_skb[MLXBF_GIGE_MAX_RXQ_SZ]; ++ struct sk_buff *tx_skb[MLXBF_GIGE_MAX_TXQ_SZ]; ++ int error_irq; ++ int rx_irq; ++ int llu_plu_irq; ++ int phy_irq; ++ int hw_phy_irq; ++ bool promisc_enabled; ++ u8 valid_polarity; ++ struct napi_struct napi; ++ struct mlxbf_gige_stats stats; ++}; ++ ++/* Rx Work Queue Element definitions */ ++#define MLXBF_GIGE_RX_WQE_SZ 8 ++ ++/* Rx Completion Queue Element definitions */ ++#define MLXBF_GIGE_RX_CQE_SZ 8 ++#define MLXBF_GIGE_RX_CQE_PKT_LEN_MASK GENMASK(10, 0) ++#define MLXBF_GIGE_RX_CQE_VALID_MASK GENMASK(11, 11) ++#define MLXBF_GIGE_RX_CQE_PKT_STATUS_MASK GENMASK(15, 12) ++#define MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR GENMASK(12, 12) ++#define MLXBF_GIGE_RX_CQE_PKT_STATUS_TRUNCATED GENMASK(13, 13) ++#define MLXBF_GIGE_RX_CQE_CHKSUM_MASK GENMASK(31, 16) ++ ++/* Tx Work Queue Element definitions */ ++#define MLXBF_GIGE_TX_WQE_SZ_QWORDS 2 ++#define MLXBF_GIGE_TX_WQE_SZ 16 ++#define MLXBF_GIGE_TX_WQE_PKT_LEN_MASK GENMASK(10, 0) ++#define MLXBF_GIGE_TX_WQE_UPDATE_MASK GENMASK(31, 31) ++#define MLXBF_GIGE_TX_WQE_CHKSUM_LEN_MASK GENMASK(42, 32) ++#define MLXBF_GIGE_TX_WQE_CHKSUM_START_MASK GENMASK(55, 48) ++#define MLXBF_GIGE_TX_WQE_CHKSUM_OFFSET_MASK GENMASK(63, 56) ++ ++/* Macro to return packet length of specified TX WQE */ ++#define MLXBF_GIGE_TX_WQE_PKT_LEN(tx_wqe_addr) \ ++ (*((tx_wqe_addr) + 1) & MLXBF_GIGE_TX_WQE_PKT_LEN_MASK) ++ ++/* Tx Completion Count */ ++#define MLXBF_GIGE_TX_CC_SZ 8 ++ ++/* List of resources in ACPI table */ ++enum mlxbf_gige_res { ++ MLXBF_GIGE_RES_MAC, ++ MLXBF_GIGE_RES_MDIO9, ++ MLXBF_GIGE_RES_GPIO0, ++ MLXBF_GIGE_RES_LLU, ++ MLXBF_GIGE_RES_PLU ++}; ++ ++/* Version of register data returned by mlxbf_gige_get_regs() */ ++#define MLXBF_GIGE_REGS_VERSION 1 ++ ++int mlxbf_gige_mdio_probe(struct platform_device *pdev, ++ struct mlxbf_gige *priv); ++void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv); ++irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(int irq, void *dev_id); ++void mlxbf_gige_mdio_enable_phy_int(struct mlxbf_gige *priv); ++ ++void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index, u64 dmac); ++void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index, u64 *dmac); ++void mlxbf_gige_enable_promisc(struct mlxbf_gige *priv); ++void mlxbf_gige_disable_promisc(struct mlxbf_gige *priv); ++int mlxbf_gige_rx_init(struct mlxbf_gige *priv); ++void mlxbf_gige_rx_deinit(struct mlxbf_gige *priv); ++int mlxbf_gige_tx_init(struct mlxbf_gige *priv); ++void mlxbf_gige_tx_deinit(struct mlxbf_gige *priv); ++bool mlxbf_gige_handle_tx_complete(struct mlxbf_gige *priv); ++netdev_tx_t mlxbf_gige_start_xmit(struct sk_buff *skb, ++ struct net_device *netdev); ++struct sk_buff *mlxbf_gige_alloc_skb(struct mlxbf_gige *priv, ++ unsigned int map_len, ++ dma_addr_t *buf_dma, ++ enum dma_data_direction dir); ++int mlxbf_gige_request_irqs(struct mlxbf_gige *priv); ++void mlxbf_gige_free_irqs(struct mlxbf_gige *priv); ++int mlxbf_gige_poll(struct napi_struct *napi, int budget); ++extern const struct ethtool_ops mlxbf_gige_ethtool_ops; ++void mlxbf_gige_update_tx_wqe_next(struct mlxbf_gige *priv); ++ ++int mlxbf_gige_gpio_init(struct platform_device *pdev, struct mlxbf_gige *priv); ++void mlxbf_gige_gpio_free(struct mlxbf_gige *priv); ++ ++#endif /* !defined(__MLXBF_GIGE_H__) */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +new file mode 100644 +index 000000000..92b798f8e +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +@@ -0,0 +1,137 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* Ethtool support for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" ++ ++/* Start of struct ethtool_ops functions */ ++static int mlxbf_gige_get_regs_len(struct net_device *netdev) ++{ ++ return MLXBF_GIGE_MMIO_REG_SZ; ++} ++ ++static void mlxbf_gige_get_regs(struct net_device *netdev, ++ struct ethtool_regs *regs, void *p) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ ++ regs->version = MLXBF_GIGE_REGS_VERSION; ++ ++ /* Read entire MMIO register space and store results ++ * into the provided buffer. Each 64-bit word is converted ++ * to big-endian to make the output more readable. ++ * ++ * NOTE: by design, a read to an offset without an existing ++ * register will be acknowledged and return zero. ++ */ ++ memcpy_fromio(p, priv->base, MLXBF_GIGE_MMIO_REG_SZ); ++} ++ ++static void mlxbf_gige_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ering) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ ++ ering->rx_max_pending = MLXBF_GIGE_MAX_RXQ_SZ; ++ ering->tx_max_pending = MLXBF_GIGE_MAX_TXQ_SZ; ++ ering->rx_pending = priv->rx_q_entries; ++ ering->tx_pending = priv->tx_q_entries; ++} ++ ++static const struct { ++ const char string[ETH_GSTRING_LEN]; ++} mlxbf_gige_ethtool_stats_keys[] = { ++ { "hw_access_errors" }, ++ { "tx_invalid_checksums" }, ++ { "tx_small_frames" }, ++ { "tx_index_errors" }, ++ { "sw_config_errors" }, ++ { "sw_access_errors" }, ++ { "rx_truncate_errors" }, ++ { "rx_mac_errors" }, ++ { "rx_din_dropped_pkts" }, ++ { "tx_fifo_full" }, ++ { "rx_filter_passed_pkts" }, ++ { "rx_filter_discard_pkts" }, ++}; ++ ++static int mlxbf_gige_get_sset_count(struct net_device *netdev, int stringset) ++{ ++ if (stringset != ETH_SS_STATS) ++ return -EOPNOTSUPP; ++ return ARRAY_SIZE(mlxbf_gige_ethtool_stats_keys); ++} ++ ++static void mlxbf_gige_get_strings(struct net_device *netdev, u32 stringset, ++ u8 *buf) ++{ ++ if (stringset != ETH_SS_STATS) ++ return; ++ memcpy(buf, &mlxbf_gige_ethtool_stats_keys, ++ sizeof(mlxbf_gige_ethtool_stats_keys)); ++} ++ ++static void mlxbf_gige_get_ethtool_stats(struct net_device *netdev, ++ struct ethtool_stats *estats, ++ u64 *data) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ ++ /* Fill data array with interface statistics ++ * ++ * NOTE: the data writes must be in ++ * sync with the strings shown in ++ * the mlxbf_gige_ethtool_stats_keys[] array ++ * ++ * NOTE2: certain statistics below are zeroed upon ++ * port disable, so the calculation below ++ * must include the "cached" value of the stat ++ * plus the value read directly from hardware. ++ * Cached statistics are currently: ++ * rx_din_dropped_pkts ++ * rx_filter_passed_pkts ++ * rx_filter_discard_pkts ++ */ ++ *data++ = priv->stats.hw_access_errors; ++ *data++ = priv->stats.tx_invalid_checksums; ++ *data++ = priv->stats.tx_small_frames; ++ *data++ = priv->stats.tx_index_errors; ++ *data++ = priv->stats.sw_config_errors; ++ *data++ = priv->stats.sw_access_errors; ++ *data++ = priv->stats.rx_truncate_errors; ++ *data++ = priv->stats.rx_mac_errors; ++ *data++ = (priv->stats.rx_din_dropped_pkts + ++ readq(priv->base + MLXBF_GIGE_RX_DIN_DROP_COUNTER)); ++ *data++ = priv->stats.tx_fifo_full; ++ *data++ = (priv->stats.rx_filter_passed_pkts + ++ readq(priv->base + MLXBF_GIGE_RX_PASS_COUNTER_ALL)); ++ *data++ = (priv->stats.rx_filter_discard_pkts + ++ readq(priv->base + MLXBF_GIGE_RX_DISC_COUNTER_ALL)); ++} ++ ++static void mlxbf_gige_get_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) ++{ ++ pause->autoneg = AUTONEG_DISABLE; ++ pause->rx_pause = 1; ++ pause->tx_pause = 1; ++} ++ ++const struct ethtool_ops mlxbf_gige_ethtool_ops = { ++ .get_link = ethtool_op_get_link, ++ .get_ringparam = mlxbf_gige_get_ringparam, ++ .get_regs_len = mlxbf_gige_get_regs_len, ++ .get_regs = mlxbf_gige_get_regs, ++ .get_strings = mlxbf_gige_get_strings, ++ .get_sset_count = mlxbf_gige_get_sset_count, ++ .get_ethtool_stats = mlxbf_gige_get_ethtool_stats, ++ .nway_reset = phy_ethtool_nway_reset, ++ .get_pauseparam = mlxbf_gige_get_pauseparam, ++ .get_link_ksettings = phy_ethtool_get_link_ksettings, ++}; +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c +new file mode 100644 +index 000000000..a8d966db5 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c +@@ -0,0 +1,212 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* Initialize and handle GPIO interrupt triggered by INT_N PHY signal. ++ * This GPIO interrupt triggers the PHY state machine to bring the link ++ * up/down. ++ * ++ * Copyright (C) 2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" ++ ++#define MLXBF_GIGE_GPIO_CAUSE_FALL_EN 0x48 ++#define MLXBF_GIGE_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80 ++#define MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0 0x94 ++#define MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE 0x98 ++ ++static void mlxbf_gige_gpio_enable(struct mlxbf_gige *priv) ++{ ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&priv->gpio_lock, flags); ++ val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); ++ val |= priv->phy_int_gpio_mask; ++ writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); ++ ++ /* The INT_N interrupt level is active low. ++ * So enable cause fall bit to detect when GPIO ++ * state goes low. ++ */ ++ val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_FALL_EN); ++ val |= priv->phy_int_gpio_mask; ++ writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_FALL_EN); ++ ++ /* Enable PHY interrupt by setting the priority level */ ++ val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); ++ val |= priv->phy_int_gpio_mask; ++ writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); ++ spin_unlock_irqrestore(&priv->gpio_lock, flags); ++} ++ ++static void mlxbf_gige_gpio_disable(struct mlxbf_gige *priv) ++{ ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&priv->gpio_lock, flags); ++ val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); ++ val &= ~priv->phy_int_gpio_mask; ++ writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); ++ spin_unlock_irqrestore(&priv->gpio_lock, flags); ++} ++ ++static irqreturn_t mlxbf_gige_gpio_handler(int irq, void *ptr) ++{ ++ struct mlxbf_gige *priv; ++ u32 val; ++ ++ priv = ptr; ++ ++ /* Check if this interrupt is from PHY device. ++ * Return if it is not. ++ */ ++ val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CAUSE_EVTEN0); ++ if (!(val & priv->phy_int_gpio_mask)) ++ return IRQ_NONE; ++ ++ /* Clear interrupt when done, otherwise, no further interrupt ++ * will be triggered. ++ */ ++ val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); ++ val |= priv->phy_int_gpio_mask; ++ writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); ++ ++ generic_handle_irq(priv->phy_irq); ++ ++ return IRQ_HANDLED; ++} ++ ++static void mlxbf_gige_gpio_mask(struct irq_data *irqd) ++{ ++ struct mlxbf_gige *priv = irq_data_get_irq_chip_data(irqd); ++ ++ mlxbf_gige_gpio_disable(priv); ++} ++ ++static void mlxbf_gige_gpio_unmask(struct irq_data *irqd) ++{ ++ struct mlxbf_gige *priv = irq_data_get_irq_chip_data(irqd); ++ ++ mlxbf_gige_gpio_enable(priv); ++} ++ ++static struct irq_chip mlxbf_gige_gpio_chip = { ++ .name = "mlxbf_gige_phy", ++ .irq_mask = mlxbf_gige_gpio_mask, ++ .irq_unmask = mlxbf_gige_gpio_unmask, ++}; ++ ++static int mlxbf_gige_gpio_domain_map(struct irq_domain *d, ++ unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_data(irq, d->host_data); ++ irq_set_chip_and_handler(irq, &mlxbf_gige_gpio_chip, handle_simple_irq); ++ irq_set_noprobe(irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops mlxbf_gige_gpio_domain_ops = { ++ .map = mlxbf_gige_gpio_domain_map, ++ .xlate = irq_domain_xlate_twocell, ++}; ++ ++#ifdef CONFIG_ACPI ++static int mlxbf_gige_gpio_resources(struct acpi_resource *ares, ++ void *data) ++{ ++ struct acpi_resource_gpio *gpio; ++ u32 *phy_int_gpio = data; ++ ++ if (ares->type == ACPI_RESOURCE_TYPE_GPIO) { ++ gpio = &ares->data.gpio; ++ *phy_int_gpio = gpio->pin_table[0]; ++ } ++ ++ return 1; ++} ++#endif ++ ++void mlxbf_gige_gpio_free(struct mlxbf_gige *priv) ++{ ++ irq_dispose_mapping(priv->phy_irq); ++ irq_domain_remove(priv->irqdomain); ++} ++ ++int mlxbf_gige_gpio_init(struct platform_device *pdev, ++ struct mlxbf_gige *priv) ++{ ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ u32 phy_int_gpio = 0; ++ int ret; ++ ++ LIST_HEAD(resources); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_GPIO0); ++ if (!res) ++ return -ENODEV; ++ ++ priv->gpio_io = devm_ioremap(dev, res->start, resource_size(res)); ++ if (!priv->gpio_io) ++ return -ENOMEM; ++ ++#ifdef CONFIG_ACPI ++ ret = acpi_dev_get_resources(ACPI_COMPANION(dev), ++ &resources, mlxbf_gige_gpio_resources, ++ &phy_int_gpio); ++ acpi_dev_free_resource_list(&resources); ++ if (ret < 0 || !phy_int_gpio) { ++ dev_err(dev, "Error retrieving the gpio phy pin"); ++ return -EINVAL; ++ } ++#endif ++ ++ priv->phy_int_gpio_mask = BIT(phy_int_gpio); ++ ++ mlxbf_gige_gpio_disable(priv); ++ ++ priv->hw_phy_irq = platform_get_irq(pdev, MLXBF_GIGE_PHY_INT_N); ++ ++ priv->irqdomain = irq_domain_add_simple(NULL, 1, 0, ++ &mlxbf_gige_gpio_domain_ops, ++ priv); ++ if (!priv->irqdomain) { ++ dev_err(dev, "Failed to add IRQ domain\n"); ++ return -ENOMEM; ++ } ++ ++ priv->phy_irq = irq_create_mapping(priv->irqdomain, 0); ++ if (!priv->phy_irq) { ++ irq_domain_remove(priv->irqdomain); ++ priv->irqdomain = NULL; ++ dev_err(dev, "Error mapping PHY IRQ\n"); ++ return -EINVAL; ++ } ++ ++ ret = devm_request_irq(dev, priv->hw_phy_irq, mlxbf_gige_gpio_handler, ++ IRQF_ONESHOT | IRQF_SHARED, "mlxbf_gige_phy", priv); ++ if (ret) { ++ dev_err(dev, "Failed to request PHY IRQ"); ++ mlxbf_gige_gpio_free(priv); ++ return ret; ++ } ++ ++ return ret; ++} +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c +new file mode 100644 +index 000000000..c38795be0 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c +@@ -0,0 +1,142 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* Interrupt related logic for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" ++ ++static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id) ++{ ++ struct mlxbf_gige *priv; ++ u64 int_status; ++ ++ priv = dev_id; ++ ++ priv->error_intr_count++; ++ ++ int_status = readq(priv->base + MLXBF_GIGE_INT_STATUS); ++ ++ if (int_status & MLXBF_GIGE_INT_STATUS_HW_ACCESS_ERROR) ++ priv->stats.hw_access_errors++; ++ ++ if (int_status & MLXBF_GIGE_INT_STATUS_TX_CHECKSUM_INPUTS) { ++ priv->stats.tx_invalid_checksums++; ++ /* This error condition is latched into MLXBF_GIGE_INT_STATUS ++ * when the GigE silicon operates on the offending ++ * TX WQE. The write to MLXBF_GIGE_INT_STATUS at the bottom ++ * of this routine clears this error condition. ++ */ ++ } ++ ++ if (int_status & MLXBF_GIGE_INT_STATUS_TX_SMALL_FRAME_SIZE) { ++ priv->stats.tx_small_frames++; ++ /* This condition happens when the networking stack invokes ++ * this driver's "start_xmit()" method with a packet whose ++ * size < 60 bytes. The GigE silicon will automatically pad ++ * this small frame up to a minimum-sized frame before it is ++ * sent. The "tx_small_frame" condition is latched into the ++ * MLXBF_GIGE_INT_STATUS register when the GigE silicon ++ * operates on the offending TX WQE. The write to ++ * MLXBF_GIGE_INT_STATUS at the bottom of this routine ++ * clears this condition. ++ */ ++ } ++ ++ if (int_status & MLXBF_GIGE_INT_STATUS_TX_PI_CI_EXCEED_WQ_SIZE) ++ priv->stats.tx_index_errors++; ++ ++ if (int_status & MLXBF_GIGE_INT_STATUS_SW_CONFIG_ERROR) ++ priv->stats.sw_config_errors++; ++ ++ if (int_status & MLXBF_GIGE_INT_STATUS_SW_ACCESS_ERROR) ++ priv->stats.sw_access_errors++; ++ ++ /* Clear all error interrupts by writing '1' back to ++ * all the asserted bits in INT_STATUS. Do not write ++ * '1' back to 'receive packet' bit, since that is ++ * managed separately. ++ */ ++ ++ int_status &= ~MLXBF_GIGE_INT_STATUS_RX_RECEIVE_PACKET; ++ ++ writeq(int_status, priv->base + MLXBF_GIGE_INT_STATUS); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t mlxbf_gige_rx_intr(int irq, void *dev_id) ++{ ++ struct mlxbf_gige *priv; ++ ++ priv = dev_id; ++ ++ priv->rx_intr_count++; ++ ++ /* NOTE: GigE silicon automatically disables "packet rx" interrupt by ++ * setting MLXBF_GIGE_INT_MASK bit0 upon triggering the interrupt ++ * to the ARM cores. Software needs to re-enable "packet rx" ++ * interrupts by clearing MLXBF_GIGE_INT_MASK bit0. ++ */ ++ ++ napi_schedule(&priv->napi); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t mlxbf_gige_llu_plu_intr(int irq, void *dev_id) ++{ ++ struct mlxbf_gige *priv; ++ ++ priv = dev_id; ++ priv->llu_plu_intr_count++; ++ ++ return IRQ_HANDLED; ++} ++ ++int mlxbf_gige_request_irqs(struct mlxbf_gige *priv) ++{ ++ int err; ++ ++ err = request_irq(priv->error_irq, mlxbf_gige_error_intr, 0, ++ "mlxbf_gige_error", priv); ++ if (err) { ++ dev_err(priv->dev, "Request error_irq failure\n"); ++ return err; ++ } ++ ++ err = request_irq(priv->rx_irq, mlxbf_gige_rx_intr, 0, ++ "mlxbf_gige_rx", priv); ++ if (err) { ++ dev_err(priv->dev, "Request rx_irq failure\n"); ++ goto free_error_irq; ++ } ++ ++ err = request_irq(priv->llu_plu_irq, mlxbf_gige_llu_plu_intr, 0, ++ "mlxbf_gige_llu_plu", priv); ++ if (err) { ++ dev_err(priv->dev, "Request llu_plu_irq failure\n"); ++ goto free_rx_irq; ++ } ++ ++ return 0; ++ ++free_rx_irq: ++ free_irq(priv->rx_irq, priv); ++ ++free_error_irq: ++ free_irq(priv->error_irq, priv); ++ ++ return err; ++} ++ ++void mlxbf_gige_free_irqs(struct mlxbf_gige *priv) ++{ ++ free_irq(priv->error_irq, priv); ++ free_irq(priv->rx_irq, priv); ++ free_irq(priv->llu_plu_irq, priv); ++} +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +new file mode 100644 +index 000000000..a0a059e01 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -0,0 +1,452 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* Gigabit Ethernet driver for Mellanox BlueField SoC ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" ++ ++#define DRV_NAME "mlxbf_gige" ++ ++/* Allocate SKB whose payload pointer aligns with the Bluefield ++ * hardware DMA limitation, i.e. DMA operation can't cross ++ * a 4KB boundary. A maximum packet size of 2KB is assumed in the ++ * alignment formula. The alignment logic overallocates an SKB, ++ * and then adjusts the headroom so that the SKB data pointer is ++ * naturally aligned to a 2KB boundary. ++ */ ++struct sk_buff *mlxbf_gige_alloc_skb(struct mlxbf_gige *priv, ++ unsigned int map_len, ++ dma_addr_t *buf_dma, ++ enum dma_data_direction dir) ++{ ++ struct sk_buff *skb; ++ u64 addr, offset; ++ ++ /* Overallocate the SKB so that any headroom adjustment (to ++ * provide 2KB natural alignment) does not exceed payload area ++ */ ++ skb = netdev_alloc_skb(priv->netdev, MLXBF_GIGE_DEFAULT_BUF_SZ * 2); ++ if (!skb) ++ return NULL; ++ ++ /* Adjust the headroom so that skb->data is naturally aligned to ++ * a 2KB boundary, which is the maximum packet size supported. ++ */ ++ addr = (long)skb->data; ++ offset = (addr + MLXBF_GIGE_DEFAULT_BUF_SZ - 1) & ++ ~(MLXBF_GIGE_DEFAULT_BUF_SZ - 1); ++ offset -= addr; ++ if (offset) ++ skb_reserve(skb, offset); ++ ++ /* Return streaming DMA mapping to caller */ ++ *buf_dma = dma_map_single(priv->dev, skb->data, map_len, dir); ++ if (dma_mapping_error(priv->dev, *buf_dma)) { ++ dev_kfree_skb(skb); ++ *buf_dma = (dma_addr_t)0; ++ return NULL; ++ } ++ ++ return skb; ++} ++ ++static void mlxbf_gige_initial_mac(struct mlxbf_gige *priv) ++{ ++ u8 mac[ETH_ALEN]; ++ u64 local_mac; ++ ++ memset(mac, 0, ETH_ALEN); ++ mlxbf_gige_get_mac_rx_filter(priv, MLXBF_GIGE_LOCAL_MAC_FILTER_IDX, ++ &local_mac); ++ u64_to_ether_addr(local_mac, mac); ++ ++ if (is_valid_ether_addr(mac)) { ++ ether_addr_copy(priv->netdev->dev_addr, mac); ++ } else { ++ /* Provide a random MAC if for some reason the device has ++ * not been configured with a valid MAC address already. ++ */ ++ eth_hw_addr_random(priv->netdev); ++ } ++ ++ local_mac = ether_addr_to_u64(priv->netdev->dev_addr); ++ mlxbf_gige_set_mac_rx_filter(priv, MLXBF_GIGE_LOCAL_MAC_FILTER_IDX, ++ local_mac); ++} ++ ++static void mlxbf_gige_cache_stats(struct mlxbf_gige *priv) ++{ ++ struct mlxbf_gige_stats *p; ++ ++ /* Cache stats that will be cleared by clean port operation */ ++ p = &priv->stats; ++ p->rx_din_dropped_pkts += readq(priv->base + ++ MLXBF_GIGE_RX_DIN_DROP_COUNTER); ++ p->rx_filter_passed_pkts += readq(priv->base + ++ MLXBF_GIGE_RX_PASS_COUNTER_ALL); ++ p->rx_filter_discard_pkts += readq(priv->base + ++ MLXBF_GIGE_RX_DISC_COUNTER_ALL); ++} ++ ++static int mlxbf_gige_clean_port(struct mlxbf_gige *priv) ++{ ++ u64 control; ++ u64 temp; ++ int err; ++ ++ /* Set the CLEAN_PORT_EN bit to trigger SW reset */ ++ control = readq(priv->base + MLXBF_GIGE_CONTROL); ++ control |= MLXBF_GIGE_CONTROL_CLEAN_PORT_EN; ++ writeq(control, priv->base + MLXBF_GIGE_CONTROL); ++ ++ /* Ensure completion of "clean port" write before polling status */ ++ mb(); ++ ++ err = readq_poll_timeout_atomic(priv->base + MLXBF_GIGE_STATUS, temp, ++ (temp & MLXBF_GIGE_STATUS_READY), ++ 100, 100000); ++ ++ /* Clear the CLEAN_PORT_EN bit at end of this loop */ ++ control = readq(priv->base + MLXBF_GIGE_CONTROL); ++ control &= ~MLXBF_GIGE_CONTROL_CLEAN_PORT_EN; ++ writeq(control, priv->base + MLXBF_GIGE_CONTROL); ++ ++ return err; ++} ++ ++static int mlxbf_gige_open(struct net_device *netdev) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ struct phy_device *phydev = netdev->phydev; ++ u64 int_en; ++ int err; ++ ++ err = mlxbf_gige_request_irqs(priv); ++ if (err) ++ return err; ++ mlxbf_gige_cache_stats(priv); ++ err = mlxbf_gige_clean_port(priv); ++ if (err) ++ goto free_irqs; ++ err = mlxbf_gige_rx_init(priv); ++ if (err) ++ goto free_irqs; ++ err = mlxbf_gige_tx_init(priv); ++ if (err) ++ goto rx_deinit; ++ ++ phy_start(phydev); ++ ++ netif_napi_add(netdev, &priv->napi, mlxbf_gige_poll, NAPI_POLL_WEIGHT); ++ napi_enable(&priv->napi); ++ netif_start_queue(netdev); ++ ++ /* Set bits in INT_EN that we care about */ ++ int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR | ++ MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS | ++ MLXBF_GIGE_INT_EN_TX_SMALL_FRAME_SIZE | ++ MLXBF_GIGE_INT_EN_TX_PI_CI_EXCEED_WQ_SIZE | ++ MLXBF_GIGE_INT_EN_SW_CONFIG_ERROR | ++ MLXBF_GIGE_INT_EN_SW_ACCESS_ERROR | ++ MLXBF_GIGE_INT_EN_RX_RECEIVE_PACKET; ++ ++ /* Ensure completion of all initialization before enabling interrupts */ ++ mb(); ++ ++ writeq(int_en, priv->base + MLXBF_GIGE_INT_EN); ++ ++ return 0; ++ ++rx_deinit: ++ mlxbf_gige_rx_deinit(priv); ++ ++free_irqs: ++ mlxbf_gige_free_irqs(priv); ++ return err; ++} ++ ++static int mlxbf_gige_stop(struct net_device *netdev) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ ++ writeq(0, priv->base + MLXBF_GIGE_INT_EN); ++ netif_stop_queue(netdev); ++ napi_disable(&priv->napi); ++ netif_napi_del(&priv->napi); ++ mlxbf_gige_free_irqs(priv); ++ ++ phy_stop(netdev->phydev); ++ ++ mlxbf_gige_rx_deinit(priv); ++ mlxbf_gige_tx_deinit(priv); ++ mlxbf_gige_cache_stats(priv); ++ mlxbf_gige_clean_port(priv); ++ ++ return 0; ++} ++ ++static int mlxbf_gige_do_ioctl(struct net_device *netdev, ++ struct ifreq *ifr, int cmd) ++{ ++ if (!(netif_running(netdev))) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(netdev->phydev, ifr, cmd); ++} ++ ++static void mlxbf_gige_set_rx_mode(struct net_device *netdev) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ bool new_promisc_enabled; ++ ++ new_promisc_enabled = netdev->flags & IFF_PROMISC; ++ ++ /* Only write to the hardware registers if the new setting ++ * of promiscuous mode is different from the current one. ++ */ ++ if (new_promisc_enabled != priv->promisc_enabled) { ++ priv->promisc_enabled = new_promisc_enabled; ++ ++ if (new_promisc_enabled) ++ mlxbf_gige_enable_promisc(priv); ++ else ++ mlxbf_gige_disable_promisc(priv); ++ } ++} ++ ++static void mlxbf_gige_get_stats64(struct net_device *netdev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ ++ netdev_stats_to_stats64(stats, &netdev->stats); ++ ++ stats->rx_length_errors = priv->stats.rx_truncate_errors; ++ stats->rx_fifo_errors = priv->stats.rx_din_dropped_pkts + ++ readq(priv->base + MLXBF_GIGE_RX_DIN_DROP_COUNTER); ++ stats->rx_crc_errors = priv->stats.rx_mac_errors; ++ stats->rx_errors = stats->rx_length_errors + ++ stats->rx_fifo_errors + ++ stats->rx_crc_errors; ++ ++ stats->tx_fifo_errors = priv->stats.tx_fifo_full; ++ stats->tx_errors = stats->tx_fifo_errors; ++} ++ ++static const struct net_device_ops mlxbf_gige_netdev_ops = { ++ .ndo_open = mlxbf_gige_open, ++ .ndo_stop = mlxbf_gige_stop, ++ .ndo_start_xmit = mlxbf_gige_start_xmit, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_do_ioctl = mlxbf_gige_do_ioctl, ++ .ndo_set_rx_mode = mlxbf_gige_set_rx_mode, ++ .ndo_get_stats64 = mlxbf_gige_get_stats64, ++}; ++ ++static void mlxbf_gige_adjust_link(struct net_device *netdev) ++{ ++ struct phy_device *phydev = netdev->phydev; ++ ++ phy_print_status(phydev); ++} ++ ++static int mlxbf_gige_probe(struct platform_device *pdev) ++{ ++ struct phy_device *phydev; ++ struct net_device *netdev; ++ struct resource *mac_res; ++ struct resource *llu_res; ++ struct resource *plu_res; ++ struct mlxbf_gige *priv; ++ void __iomem *llu_base; ++ void __iomem *plu_base; ++ void __iomem *base; ++ u64 control; ++ int addr; ++ int err; ++ ++ mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC); ++ if (!mac_res) ++ return -ENXIO; ++ ++ base = devm_ioremap_resource(&pdev->dev, mac_res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ llu_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_LLU); ++ if (!llu_res) ++ return -ENXIO; ++ ++ llu_base = devm_ioremap_resource(&pdev->dev, llu_res); ++ if (IS_ERR(llu_base)) ++ return PTR_ERR(llu_base); ++ ++ plu_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_PLU); ++ if (!plu_res) ++ return -ENXIO; ++ ++ plu_base = devm_ioremap_resource(&pdev->dev, plu_res); ++ if (IS_ERR(plu_base)) ++ return PTR_ERR(plu_base); ++ ++ /* Perform general init of GigE block */ ++ control = readq(base + MLXBF_GIGE_CONTROL); ++ control |= MLXBF_GIGE_CONTROL_PORT_EN; ++ writeq(control, base + MLXBF_GIGE_CONTROL); ++ ++ netdev = devm_alloc_etherdev(&pdev->dev, sizeof(*priv)); ++ if (!netdev) ++ return -ENOMEM; ++ ++ SET_NETDEV_DEV(netdev, &pdev->dev); ++ netdev->netdev_ops = &mlxbf_gige_netdev_ops; ++ netdev->ethtool_ops = &mlxbf_gige_ethtool_ops; ++ priv = netdev_priv(netdev); ++ priv->netdev = netdev; ++ ++ platform_set_drvdata(pdev, priv); ++ priv->dev = &pdev->dev; ++ priv->pdev = pdev; ++ ++ spin_lock_init(&priv->lock); ++ spin_lock_init(&priv->gpio_lock); ++ ++ /* Attach MDIO device */ ++ err = mlxbf_gige_mdio_probe(pdev, priv); ++ if (err) ++ return err; ++ ++ err = mlxbf_gige_gpio_init(pdev, priv); ++ if (err) { ++ dev_err(&pdev->dev, "PHY IRQ initialization failed\n"); ++ mlxbf_gige_mdio_remove(priv); ++ return -ENODEV; ++ } ++ ++ priv->base = base; ++ priv->llu_base = llu_base; ++ priv->plu_base = plu_base; ++ ++ priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ; ++ priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ; ++ ++ /* Write initial MAC address to hardware */ ++ mlxbf_gige_initial_mac(priv); ++ ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); ++ if (err) { ++ dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err); ++ goto out; ++ } ++ ++ priv->error_irq = platform_get_irq(pdev, MLXBF_GIGE_ERROR_INTR_IDX); ++ priv->rx_irq = platform_get_irq(pdev, MLXBF_GIGE_RECEIVE_PKT_INTR_IDX); ++ priv->llu_plu_irq = platform_get_irq(pdev, MLXBF_GIGE_LLU_PLU_INTR_IDX); ++ ++ phydev = phy_find_first(priv->mdiobus); ++ if (!phydev) { ++ err = -ENODEV; ++ goto out; ++ } ++ ++ addr = phydev->mdio.addr; ++ priv->mdiobus->irq[addr] = priv->phy_irq; ++ phydev->irq = priv->phy_irq; ++ ++ err = phy_connect_direct(netdev, phydev, ++ mlxbf_gige_adjust_link, ++ PHY_INTERFACE_MODE_GMII); ++ if (err) { ++ dev_err(&pdev->dev, "Could not attach to PHY\n"); ++ goto out; ++ } ++ ++ /* MAC only supports 1000T full duplex mode */ ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); ++ ++ /* Only symmetric pause with flow control enabled is supported so no ++ * need to negotiate pause. ++ */ ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising); ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising); ++ ++ /* Display information about attached PHY device */ ++ phy_attached_info(phydev); ++ ++ err = register_netdev(netdev); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to register netdev\n"); ++ phy_disconnect(phydev); ++ goto out; ++ } ++ ++ return 0; ++ ++out: ++ mlxbf_gige_gpio_free(priv); ++ mlxbf_gige_mdio_remove(priv); ++ return err; ++} ++ ++static int mlxbf_gige_remove(struct platform_device *pdev) ++{ ++ struct mlxbf_gige *priv = platform_get_drvdata(pdev); ++ ++ unregister_netdev(priv->netdev); ++ phy_disconnect(priv->netdev->phydev); ++ mlxbf_gige_gpio_free(priv); ++ mlxbf_gige_mdio_remove(priv); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void mlxbf_gige_shutdown(struct platform_device *pdev) ++{ ++ struct mlxbf_gige *priv = platform_get_drvdata(pdev); ++ ++ writeq(0, priv->base + MLXBF_GIGE_INT_EN); ++ mlxbf_gige_clean_port(priv); ++} ++ ++static const struct acpi_device_id __maybe_unused mlxbf_gige_acpi_match[] = { ++ { "MLNXBF17", 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(acpi, mlxbf_gige_acpi_match); ++ ++static struct platform_driver mlxbf_gige_driver = { ++ .probe = mlxbf_gige_probe, ++ .remove = mlxbf_gige_remove, ++ .shutdown = mlxbf_gige_shutdown, ++ .driver = { ++ .name = DRV_NAME, ++ .acpi_match_table = ACPI_PTR(mlxbf_gige_acpi_match), ++ }, ++}; ++ ++module_platform_driver(mlxbf_gige_driver); ++ ++MODULE_DESCRIPTION("Mellanox BlueField SoC Gigabit Ethernet Driver"); ++MODULE_AUTHOR("David Thompson "); ++MODULE_AUTHOR("Asmaa Mnebhi "); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +new file mode 100644 +index 000000000..e32dd34fd +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -0,0 +1,187 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* MDIO support for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mlxbf_gige.h" ++ ++#define MLXBF_GIGE_MDIO_GW_OFFSET 0x0 ++#define MLXBF_GIGE_MDIO_CFG_OFFSET 0x4 ++ ++/* Support clause 22 */ ++#define MLXBF_GIGE_MDIO_CL22_ST1 0x1 ++#define MLXBF_GIGE_MDIO_CL22_WRITE 0x1 ++#define MLXBF_GIGE_MDIO_CL22_READ 0x2 ++ ++/* Busy bit is set by software and cleared by hardware */ ++#define MLXBF_GIGE_MDIO_SET_BUSY 0x1 ++ ++/* MDIO GW register bits */ ++#define MLXBF_GIGE_MDIO_GW_AD_MASK GENMASK(15, 0) ++#define MLXBF_GIGE_MDIO_GW_DEVAD_MASK GENMASK(20, 16) ++#define MLXBF_GIGE_MDIO_GW_PARTAD_MASK GENMASK(25, 21) ++#define MLXBF_GIGE_MDIO_GW_OPCODE_MASK GENMASK(27, 26) ++#define MLXBF_GIGE_MDIO_GW_ST1_MASK GENMASK(28, 28) ++#define MLXBF_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30) ++ ++/* MDIO config register bits */ ++#define MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0) ++#define MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK GENMASK(2, 2) ++#define MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(4, 4) ++#define MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(15, 8) ++#define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16) ++#define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24) ++ ++/* Formula for encoding the MDIO period. The encoded value is ++ * passed to the MDIO config register. ++ * ++ * mdc_clk = 2*(val + 1)*i1clk ++ * ++ * 400 ns = 2*(val + 1)*(((1/430)*1000) ns) ++ * ++ * val = (((400 * 430 / 1000) / 2) - 1) ++ */ ++#define MLXBF_GIGE_I1CLK_MHZ 430 ++#define MLXBF_GIGE_MDC_CLK_NS 400 ++ ++#define MLXBF_GIGE_MDIO_PERIOD (((MLXBF_GIGE_MDC_CLK_NS * MLXBF_GIGE_I1CLK_MHZ / 1000) / 2) - 1) ++ ++#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, \ ++ MLXBF_GIGE_MDIO_PERIOD) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13)) ++ ++static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add, ++ int phy_reg, u32 opcode) ++{ ++ u32 gw_reg = 0; ++ ++ gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_AD_MASK, data); ++ gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_DEVAD_MASK, phy_reg); ++ gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_PARTAD_MASK, phy_add); ++ gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_OPCODE_MASK, opcode); ++ gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_ST1_MASK, ++ MLXBF_GIGE_MDIO_CL22_ST1); ++ gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_BUSY_MASK, ++ MLXBF_GIGE_MDIO_SET_BUSY); ++ ++ return gw_reg; ++} ++ ++static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg) ++{ ++ struct mlxbf_gige *priv = bus->priv; ++ u32 cmd; ++ int ret; ++ u32 val; ++ ++ if (phy_reg & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ ++ /* Send mdio read request */ ++ cmd = mlxbf_gige_mdio_create_cmd(0, phy_add, phy_reg, MLXBF_GIGE_MDIO_CL22_READ); ++ ++ writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ ++ ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET, ++ val, !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK), 100, 1000000); ++ ++ if (ret) { ++ writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ return ret; ++ } ++ ++ ret = readl(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ /* Only return ad bits of the gw register */ ++ ret &= MLXBF_GIGE_MDIO_GW_AD_MASK; ++ ++ return ret; ++} ++ ++static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add, ++ int phy_reg, u16 val) ++{ ++ struct mlxbf_gige *priv = bus->priv; ++ u32 cmd; ++ int ret; ++ u32 temp; ++ ++ if (phy_reg & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ ++ /* Send mdio write request */ ++ cmd = mlxbf_gige_mdio_create_cmd(val, phy_add, phy_reg, ++ MLXBF_GIGE_MDIO_CL22_WRITE); ++ writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ ++ /* If the poll timed out, drop the request */ ++ ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET, ++ temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK), 100, 1000000); ++ ++ return ret; ++} ++ ++int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) ++{ ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MDIO9); ++ if (!res) ++ return -ENODEV; ++ ++ priv->mdio_io = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->mdio_io)) ++ return PTR_ERR(priv->mdio_io); ++ ++ /* Configure mdio parameters */ ++ writel(MLXBF_GIGE_MDIO_CFG_VAL, ++ priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET); ++ ++ priv->mdiobus = devm_mdiobus_alloc(dev); ++ if (!priv->mdiobus) { ++ dev_err(dev, "Failed to alloc MDIO bus\n"); ++ return -ENOMEM; ++ } ++ ++ priv->mdiobus->name = "mlxbf-mdio"; ++ priv->mdiobus->read = mlxbf_gige_mdio_read; ++ priv->mdiobus->write = mlxbf_gige_mdio_write; ++ priv->mdiobus->parent = dev; ++ priv->mdiobus->priv = priv; ++ snprintf(priv->mdiobus->id, MII_BUS_ID_SIZE, "%s", ++ dev_name(dev)); ++ ++ ret = mdiobus_register(priv->mdiobus); ++ if (ret) ++ dev_err(dev, "Failed to register MDIO bus\n"); ++ ++ return ret; ++} ++ ++void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv) ++{ ++ mdiobus_unregister(priv->mdiobus); ++} +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +new file mode 100644 +index 000000000..5fb33c929 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +@@ -0,0 +1,78 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ ++ ++/* Header file for Mellanox BlueField GigE register defines ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#ifndef __MLXBF_GIGE_REGS_H__ ++#define __MLXBF_GIGE_REGS_H__ ++ ++#define MLXBF_GIGE_STATUS 0x0010 ++#define MLXBF_GIGE_STATUS_READY BIT(0) ++#define MLXBF_GIGE_INT_STATUS 0x0028 ++#define MLXBF_GIGE_INT_STATUS_RX_RECEIVE_PACKET BIT(0) ++#define MLXBF_GIGE_INT_STATUS_RX_MAC_ERROR BIT(1) ++#define MLXBF_GIGE_INT_STATUS_RX_TRN_ERROR BIT(2) ++#define MLXBF_GIGE_INT_STATUS_SW_ACCESS_ERROR BIT(3) ++#define MLXBF_GIGE_INT_STATUS_SW_CONFIG_ERROR BIT(4) ++#define MLXBF_GIGE_INT_STATUS_TX_PI_CI_EXCEED_WQ_SIZE BIT(5) ++#define MLXBF_GIGE_INT_STATUS_TX_SMALL_FRAME_SIZE BIT(6) ++#define MLXBF_GIGE_INT_STATUS_TX_CHECKSUM_INPUTS BIT(7) ++#define MLXBF_GIGE_INT_STATUS_HW_ACCESS_ERROR BIT(8) ++#define MLXBF_GIGE_INT_EN 0x0030 ++#define MLXBF_GIGE_INT_EN_RX_RECEIVE_PACKET BIT(0) ++#define MLXBF_GIGE_INT_EN_RX_MAC_ERROR BIT(1) ++#define MLXBF_GIGE_INT_EN_RX_TRN_ERROR BIT(2) ++#define MLXBF_GIGE_INT_EN_SW_ACCESS_ERROR BIT(3) ++#define MLXBF_GIGE_INT_EN_SW_CONFIG_ERROR BIT(4) ++#define MLXBF_GIGE_INT_EN_TX_PI_CI_EXCEED_WQ_SIZE BIT(5) ++#define MLXBF_GIGE_INT_EN_TX_SMALL_FRAME_SIZE BIT(6) ++#define MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS BIT(7) ++#define MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR BIT(8) ++#define MLXBF_GIGE_INT_MASK 0x0038 ++#define MLXBF_GIGE_INT_MASK_RX_RECEIVE_PACKET BIT(0) ++#define MLXBF_GIGE_CONTROL 0x0040 ++#define MLXBF_GIGE_CONTROL_PORT_EN BIT(0) ++#define MLXBF_GIGE_CONTROL_MAC_ID_RANGE_EN BIT(1) ++#define MLXBF_GIGE_CONTROL_EN_SPECIFIC_MAC BIT(4) ++#define MLXBF_GIGE_CONTROL_CLEAN_PORT_EN BIT(31) ++#define MLXBF_GIGE_RX_WQ_BASE 0x0200 ++#define MLXBF_GIGE_RX_WQE_SIZE_LOG2 0x0208 ++#define MLXBF_GIGE_RX_WQE_SIZE_LOG2_RESET_VAL 7 ++#define MLXBF_GIGE_RX_CQ_BASE 0x0210 ++#define MLXBF_GIGE_TX_WQ_BASE 0x0218 ++#define MLXBF_GIGE_TX_WQ_SIZE_LOG2 0x0220 ++#define MLXBF_GIGE_TX_WQ_SIZE_LOG2_RESET_VAL 7 ++#define MLXBF_GIGE_TX_CI_UPDATE_ADDRESS 0x0228 ++#define MLXBF_GIGE_RX_WQE_PI 0x0230 ++#define MLXBF_GIGE_TX_PRODUCER_INDEX 0x0238 ++#define MLXBF_GIGE_RX_MAC_FILTER 0x0240 ++#define MLXBF_GIGE_RX_MAC_FILTER_STRIDE 0x0008 ++#define MLXBF_GIGE_RX_DIN_DROP_COUNTER 0x0260 ++#define MLXBF_GIGE_TX_CONSUMER_INDEX 0x0310 ++#define MLXBF_GIGE_TX_CONTROL 0x0318 ++#define MLXBF_GIGE_TX_CONTROL_GRACEFUL_STOP BIT(0) ++#define MLXBF_GIGE_TX_STATUS 0x0388 ++#define MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL BIT(1) ++#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START 0x0520 ++#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END 0x0528 ++#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC 0x0540 ++#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC_EN BIT(0) ++#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS 0x0548 ++#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS_EN BIT(0) ++#define MLXBF_GIGE_RX_PASS_COUNTER_ALL 0x0550 ++#define MLXBF_GIGE_RX_DISC_COUNTER_ALL 0x0560 ++#define MLXBF_GIGE_RX 0x0578 ++#define MLXBF_GIGE_RX_STRIP_CRC_EN BIT(1) ++#define MLXBF_GIGE_RX_DMA 0x0580 ++#define MLXBF_GIGE_RX_DMA_EN BIT(0) ++#define MLXBF_GIGE_RX_CQE_PACKET_CI 0x05b0 ++#define MLXBF_GIGE_MAC_CFG 0x05e8 ++ ++/* NOTE: MLXBF_GIGE_MAC_CFG is the last defined register offset, ++ * so use that plus size of single register to derive total size ++ */ ++#define MLXBF_GIGE_MMIO_REG_SZ (MLXBF_GIGE_MAC_CFG + 8) ++ ++#endif /* !defined(__MLXBF_GIGE_REGS_H__) */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +new file mode 100644 +index 000000000..afa3b92a6 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +@@ -0,0 +1,320 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* Packet receive logic for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" ++ ++void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index, u64 dmac) ++{ ++ void __iomem *base = priv->base; ++ u64 control; ++ ++ /* Write destination MAC to specified MAC RX filter */ ++ writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER + ++ (index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE)); ++ ++ /* Enable MAC receive filter mask for specified index */ ++ control = readq(base + MLXBF_GIGE_CONTROL); ++ control |= (MLXBF_GIGE_CONTROL_EN_SPECIFIC_MAC << index); ++ writeq(control, base + MLXBF_GIGE_CONTROL); ++} ++ ++void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index, u64 *dmac) ++{ ++ void __iomem *base = priv->base; ++ ++ /* Read destination MAC from specified MAC RX filter */ ++ *dmac = readq(base + MLXBF_GIGE_RX_MAC_FILTER + ++ (index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE)); ++} ++ ++void mlxbf_gige_enable_promisc(struct mlxbf_gige *priv) ++{ ++ void __iomem *base = priv->base; ++ u64 control; ++ u64 end_mac; ++ ++ /* Enable MAC_ID_RANGE match functionality */ ++ control = readq(base + MLXBF_GIGE_CONTROL); ++ control |= MLXBF_GIGE_CONTROL_MAC_ID_RANGE_EN; ++ writeq(control, base + MLXBF_GIGE_CONTROL); ++ ++ /* Set start of destination MAC range check to 0 */ ++ writeq(0, base + MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START); ++ ++ /* Set end of destination MAC range check to all FFs */ ++ end_mac = BCAST_MAC_ADDR; ++ writeq(end_mac, base + MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END); ++} ++ ++void mlxbf_gige_disable_promisc(struct mlxbf_gige *priv) ++{ ++ void __iomem *base = priv->base; ++ u64 control; ++ ++ /* Disable MAC_ID_RANGE match functionality */ ++ control = readq(base + MLXBF_GIGE_CONTROL); ++ control &= ~MLXBF_GIGE_CONTROL_MAC_ID_RANGE_EN; ++ writeq(control, base + MLXBF_GIGE_CONTROL); ++ ++ /* NOTE: no need to change DMAC_RANGE_START or END; ++ * those values are ignored since MAC_ID_RANGE_EN=0 ++ */ ++} ++ ++/* Receive Initialization ++ * 1) Configures RX MAC filters via MMIO registers ++ * 2) Allocates RX WQE array using coherent DMA mapping ++ * 3) Initializes each element of RX WQE array with a receive ++ * buffer pointer (also using coherent DMA mapping) ++ * 4) Allocates RX CQE array using coherent DMA mapping ++ * 5) Completes other misc receive initialization ++ */ ++int mlxbf_gige_rx_init(struct mlxbf_gige *priv) ++{ ++ size_t wq_size, cq_size; ++ dma_addr_t *rx_wqe_ptr; ++ dma_addr_t rx_buf_dma; ++ u64 data; ++ int i, j; ++ ++ /* Configure MAC RX filter #0 to allow RX of broadcast pkts */ ++ mlxbf_gige_set_mac_rx_filter(priv, MLXBF_GIGE_BCAST_MAC_FILTER_IDX, ++ BCAST_MAC_ADDR); ++ ++ wq_size = MLXBF_GIGE_RX_WQE_SZ * priv->rx_q_entries; ++ priv->rx_wqe_base = dma_alloc_coherent(priv->dev, wq_size, ++ &priv->rx_wqe_base_dma, ++ GFP_KERNEL); ++ if (!priv->rx_wqe_base) ++ return -ENOMEM; ++ ++ /* Initialize 'rx_wqe_ptr' to point to first RX WQE in array ++ * Each RX WQE is simply a receive buffer pointer, so walk ++ * the entire array, allocating a 2KB buffer for each element ++ */ ++ rx_wqe_ptr = priv->rx_wqe_base; ++ ++ for (i = 0; i < priv->rx_q_entries; i++) { ++ priv->rx_skb[i] = mlxbf_gige_alloc_skb(priv, MLXBF_GIGE_DEFAULT_BUF_SZ, ++ &rx_buf_dma, DMA_FROM_DEVICE); ++ if (!priv->rx_skb[i]) ++ goto free_wqe_and_skb; ++ *rx_wqe_ptr++ = rx_buf_dma; ++ } ++ ++ /* Write RX WQE base address into MMIO reg */ ++ writeq(priv->rx_wqe_base_dma, priv->base + MLXBF_GIGE_RX_WQ_BASE); ++ ++ cq_size = MLXBF_GIGE_RX_CQE_SZ * priv->rx_q_entries; ++ priv->rx_cqe_base = dma_alloc_coherent(priv->dev, cq_size, ++ &priv->rx_cqe_base_dma, ++ GFP_KERNEL); ++ if (!priv->rx_cqe_base) ++ goto free_wqe_and_skb; ++ ++ for (i = 0; i < priv->rx_q_entries; i++) ++ priv->rx_cqe_base[i] |= MLXBF_GIGE_RX_CQE_VALID_MASK; ++ ++ /* Write RX CQE base address into MMIO reg */ ++ writeq(priv->rx_cqe_base_dma, priv->base + MLXBF_GIGE_RX_CQ_BASE); ++ ++ /* Write RX_WQE_PI with current number of replenished buffers */ ++ writeq(priv->rx_q_entries, priv->base + MLXBF_GIGE_RX_WQE_PI); ++ ++ /* Enable removal of CRC during RX */ ++ data = readq(priv->base + MLXBF_GIGE_RX); ++ data |= MLXBF_GIGE_RX_STRIP_CRC_EN; ++ writeq(data, priv->base + MLXBF_GIGE_RX); ++ ++ /* Enable RX MAC filter pass and discard counters */ ++ writeq(MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC_EN, ++ priv->base + MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC); ++ writeq(MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS_EN, ++ priv->base + MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS); ++ ++ /* Clear MLXBF_GIGE_INT_MASK 'receive pkt' bit to ++ * indicate readiness to receive interrupts ++ */ ++ data = readq(priv->base + MLXBF_GIGE_INT_MASK); ++ data &= ~MLXBF_GIGE_INT_MASK_RX_RECEIVE_PACKET; ++ writeq(data, priv->base + MLXBF_GIGE_INT_MASK); ++ ++ /* Enable RX DMA to write new packets to memory */ ++ data = readq(priv->base + MLXBF_GIGE_RX_DMA); ++ data |= MLXBF_GIGE_RX_DMA_EN; ++ writeq(data, priv->base + MLXBF_GIGE_RX_DMA); ++ ++ writeq(ilog2(priv->rx_q_entries), ++ priv->base + MLXBF_GIGE_RX_WQE_SIZE_LOG2); ++ ++ return 0; ++ ++free_wqe_and_skb: ++ rx_wqe_ptr = priv->rx_wqe_base; ++ for (j = 0; j < i; j++) { ++ dma_unmap_single(priv->dev, *rx_wqe_ptr, ++ MLXBF_GIGE_DEFAULT_BUF_SZ, DMA_FROM_DEVICE); ++ dev_kfree_skb(priv->rx_skb[j]); ++ rx_wqe_ptr++; ++ } ++ dma_free_coherent(priv->dev, wq_size, ++ priv->rx_wqe_base, priv->rx_wqe_base_dma); ++ return -ENOMEM; ++} ++ ++/* Receive Deinitialization ++ * This routine will free allocations done by mlxbf_gige_rx_init(), ++ * namely the RX WQE and RX CQE arrays, as well as all RX buffers ++ */ ++void mlxbf_gige_rx_deinit(struct mlxbf_gige *priv) ++{ ++ dma_addr_t *rx_wqe_ptr; ++ size_t size; ++ u64 data; ++ int i; ++ ++ /* Disable RX DMA to prevent packet transfers to memory */ ++ data = readq(priv->base + MLXBF_GIGE_RX_DMA); ++ data &= ~MLXBF_GIGE_RX_DMA_EN; ++ writeq(data, priv->base + MLXBF_GIGE_RX_DMA); ++ ++ rx_wqe_ptr = priv->rx_wqe_base; ++ ++ for (i = 0; i < priv->rx_q_entries; i++) { ++ dma_unmap_single(priv->dev, *rx_wqe_ptr, MLXBF_GIGE_DEFAULT_BUF_SZ, ++ DMA_FROM_DEVICE); ++ dev_kfree_skb(priv->rx_skb[i]); ++ rx_wqe_ptr++; ++ } ++ ++ size = MLXBF_GIGE_RX_WQE_SZ * priv->rx_q_entries; ++ dma_free_coherent(priv->dev, size, ++ priv->rx_wqe_base, priv->rx_wqe_base_dma); ++ ++ size = MLXBF_GIGE_RX_CQE_SZ * priv->rx_q_entries; ++ dma_free_coherent(priv->dev, size, ++ priv->rx_cqe_base, priv->rx_cqe_base_dma); ++ ++ priv->rx_wqe_base = NULL; ++ priv->rx_wqe_base_dma = 0; ++ priv->rx_cqe_base = NULL; ++ priv->rx_cqe_base_dma = 0; ++ writeq(0, priv->base + MLXBF_GIGE_RX_WQ_BASE); ++ writeq(0, priv->base + MLXBF_GIGE_RX_CQ_BASE); ++} ++ ++static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts) ++{ ++ struct net_device *netdev = priv->netdev; ++ struct sk_buff *skb = NULL, *rx_skb; ++ u16 rx_pi_rem, rx_ci_rem; ++ dma_addr_t *rx_wqe_addr; ++ dma_addr_t rx_buf_dma; ++ u64 *rx_cqe_addr; ++ u64 datalen; ++ u64 rx_cqe; ++ u16 rx_ci; ++ u16 rx_pi; ++ ++ /* Index into RX buffer array is rx_pi w/wrap based on RX_CQE_SIZE */ ++ rx_pi = readq(priv->base + MLXBF_GIGE_RX_WQE_PI); ++ rx_pi_rem = rx_pi % priv->rx_q_entries; ++ ++ rx_wqe_addr = priv->rx_wqe_base + rx_pi_rem; ++ rx_cqe_addr = priv->rx_cqe_base + rx_pi_rem; ++ rx_cqe = *rx_cqe_addr; ++ ++ if ((!!(rx_cqe & MLXBF_GIGE_RX_CQE_VALID_MASK)) != priv->valid_polarity) ++ return false; ++ ++ if ((rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MASK) == 0) { ++ /* Packet is OK, increment stats */ ++ datalen = rx_cqe & MLXBF_GIGE_RX_CQE_PKT_LEN_MASK; ++ netdev->stats.rx_packets++; ++ netdev->stats.rx_bytes += datalen; ++ ++ skb = priv->rx_skb[rx_pi_rem]; ++ ++ skb_put(skb, datalen); ++ ++ skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */ ++ ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ /* Alloc another RX SKB for this same index */ ++ rx_skb = mlxbf_gige_alloc_skb(priv, MLXBF_GIGE_DEFAULT_BUF_SZ, ++ &rx_buf_dma, DMA_FROM_DEVICE); ++ if (!rx_skb) ++ return false; ++ priv->rx_skb[rx_pi_rem] = rx_skb; ++ dma_unmap_single(priv->dev, *rx_wqe_addr, ++ MLXBF_GIGE_DEFAULT_BUF_SZ, DMA_FROM_DEVICE); ++ *rx_wqe_addr = rx_buf_dma; ++ } else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR) { ++ priv->stats.rx_mac_errors++; ++ } else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_TRUNCATED) { ++ priv->stats.rx_truncate_errors++; ++ } ++ ++ /* Let hardware know we've replenished one buffer */ ++ rx_pi++; ++ ++ /* Ensure completion of all writes before notifying HW of replenish */ ++ wmb(); ++ writeq(rx_pi, priv->base + MLXBF_GIGE_RX_WQE_PI); ++ ++ (*rx_pkts)++; ++ ++ rx_pi_rem = rx_pi % priv->rx_q_entries; ++ if (rx_pi_rem == 0) ++ priv->valid_polarity ^= 1; ++ rx_ci = readq(priv->base + MLXBF_GIGE_RX_CQE_PACKET_CI); ++ rx_ci_rem = rx_ci % priv->rx_q_entries; ++ ++ if (skb) ++ netif_receive_skb(skb); ++ ++ return rx_pi_rem != rx_ci_rem; ++} ++ ++/* Driver poll() function called by NAPI infrastructure */ ++int mlxbf_gige_poll(struct napi_struct *napi, int budget) ++{ ++ struct mlxbf_gige *priv; ++ bool remaining_pkts; ++ int work_done = 0; ++ u64 data; ++ ++ priv = container_of(napi, struct mlxbf_gige, napi); ++ ++ mlxbf_gige_handle_tx_complete(priv); ++ ++ do { ++ remaining_pkts = mlxbf_gige_rx_packet(priv, &work_done); ++ } while (remaining_pkts && work_done < budget); ++ ++ /* If amount of work done < budget, turn off NAPI polling ++ * via napi_complete_done(napi, work_done) and then ++ * re-enable interrupts. ++ */ ++ if (work_done < budget && napi_complete_done(napi, work_done)) { ++ /* Clear MLXBF_GIGE_INT_MASK 'receive pkt' bit to ++ * indicate receive readiness ++ */ ++ data = readq(priv->base + MLXBF_GIGE_INT_MASK); ++ data &= ~MLXBF_GIGE_INT_MASK_RX_RECEIVE_PACKET; ++ writeq(data, priv->base + MLXBF_GIGE_INT_MASK); ++ } ++ ++ return work_done; ++} +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_tx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_tx.c +new file mode 100644 +index 000000000..04982e888 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_tx.c +@@ -0,0 +1,284 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* Packet transmit logic for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" ++ ++/* Transmit Initialization ++ * 1) Allocates TX WQE array using coherent DMA mapping ++ * 2) Allocates TX completion counter using coherent DMA mapping ++ */ ++int mlxbf_gige_tx_init(struct mlxbf_gige *priv) ++{ ++ size_t size; ++ ++ size = MLXBF_GIGE_TX_WQE_SZ * priv->tx_q_entries; ++ priv->tx_wqe_base = dma_alloc_coherent(priv->dev, size, ++ &priv->tx_wqe_base_dma, ++ GFP_KERNEL); ++ if (!priv->tx_wqe_base) ++ return -ENOMEM; ++ ++ priv->tx_wqe_next = priv->tx_wqe_base; ++ ++ /* Write TX WQE base address into MMIO reg */ ++ writeq(priv->tx_wqe_base_dma, priv->base + MLXBF_GIGE_TX_WQ_BASE); ++ ++ /* Allocate address for TX completion count */ ++ priv->tx_cc = dma_alloc_coherent(priv->dev, MLXBF_GIGE_TX_CC_SZ, ++ &priv->tx_cc_dma, GFP_KERNEL); ++ if (!priv->tx_cc) { ++ dma_free_coherent(priv->dev, size, ++ priv->tx_wqe_base, priv->tx_wqe_base_dma); ++ return -ENOMEM; ++ } ++ ++ /* Write TX CC base address into MMIO reg */ ++ writeq(priv->tx_cc_dma, priv->base + MLXBF_GIGE_TX_CI_UPDATE_ADDRESS); ++ ++ writeq(ilog2(priv->tx_q_entries), ++ priv->base + MLXBF_GIGE_TX_WQ_SIZE_LOG2); ++ ++ priv->prev_tx_ci = 0; ++ priv->tx_pi = 0; ++ ++ return 0; ++} ++ ++/* Transmit Deinitialization ++ * This routine will free allocations done by mlxbf_gige_tx_init(), ++ * namely the TX WQE array and the TX completion counter ++ */ ++void mlxbf_gige_tx_deinit(struct mlxbf_gige *priv) ++{ ++ u64 *tx_wqe_addr; ++ size_t size; ++ int i; ++ ++ tx_wqe_addr = priv->tx_wqe_base; ++ ++ for (i = 0; i < priv->tx_q_entries; i++) { ++ if (priv->tx_skb[i]) { ++ dma_unmap_single(priv->dev, *tx_wqe_addr, ++ priv->tx_skb[i]->len, DMA_TO_DEVICE); ++ dev_kfree_skb(priv->tx_skb[i]); ++ priv->tx_skb[i] = NULL; ++ } ++ tx_wqe_addr += 2; ++ } ++ ++ size = MLXBF_GIGE_TX_WQE_SZ * priv->tx_q_entries; ++ dma_free_coherent(priv->dev, size, ++ priv->tx_wqe_base, priv->tx_wqe_base_dma); ++ ++ dma_free_coherent(priv->dev, MLXBF_GIGE_TX_CC_SZ, ++ priv->tx_cc, priv->tx_cc_dma); ++ ++ priv->tx_wqe_base = NULL; ++ priv->tx_wqe_base_dma = 0; ++ priv->tx_cc = NULL; ++ priv->tx_cc_dma = 0; ++ priv->tx_wqe_next = NULL; ++ writeq(0, priv->base + MLXBF_GIGE_TX_WQ_BASE); ++ writeq(0, priv->base + MLXBF_GIGE_TX_CI_UPDATE_ADDRESS); ++} ++ ++/* Function that returns status of TX ring: ++ * 0: TX ring is full, i.e. there are no ++ * available un-used entries in TX ring. ++ * non-null: TX ring is not full, i.e. there are ++ * some available entries in TX ring. ++ * The non-null value is a measure of ++ * how many TX entries are available, but ++ * it is not the exact number of available ++ * entries (see below). ++ * ++ * The algorithm makes the assumption that if ++ * (prev_tx_ci == tx_pi) then the TX ring is empty. ++ * An empty ring actually has (tx_q_entries-1) ++ * entries, which allows the algorithm to differentiate ++ * the case of an empty ring vs. a full ring. ++ */ ++static u16 mlxbf_gige_tx_buffs_avail(struct mlxbf_gige *priv) ++{ ++ unsigned long flags; ++ u16 avail; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->prev_tx_ci == priv->tx_pi) ++ avail = priv->tx_q_entries - 1; ++ else ++ avail = ((priv->tx_q_entries + priv->prev_tx_ci - priv->tx_pi) ++ % priv->tx_q_entries) - 1; ++ ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return avail; ++} ++ ++bool mlxbf_gige_handle_tx_complete(struct mlxbf_gige *priv) ++{ ++ struct net_device_stats *stats; ++ u16 tx_wqe_index; ++ u64 *tx_wqe_addr; ++ u64 tx_status; ++ u16 tx_ci; ++ ++ tx_status = readq(priv->base + MLXBF_GIGE_TX_STATUS); ++ if (tx_status & MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL) ++ priv->stats.tx_fifo_full++; ++ tx_ci = readq(priv->base + MLXBF_GIGE_TX_CONSUMER_INDEX); ++ stats = &priv->netdev->stats; ++ ++ /* Transmit completion logic needs to loop until the completion ++ * index (in SW) equals TX consumer index (from HW). These ++ * parameters are unsigned 16-bit values and the wrap case needs ++ * to be supported, that is TX consumer index wrapped from 0xFFFF ++ * to 0 while TX completion index is still < 0xFFFF. ++ */ ++ for (; priv->prev_tx_ci != tx_ci; priv->prev_tx_ci++) { ++ tx_wqe_index = priv->prev_tx_ci % priv->tx_q_entries; ++ /* Each TX WQE is 16 bytes. The 8 MSB store the 2KB TX ++ * buffer address and the 8 LSB contain information ++ * about the TX WQE. ++ */ ++ tx_wqe_addr = priv->tx_wqe_base + ++ (tx_wqe_index * MLXBF_GIGE_TX_WQE_SZ_QWORDS); ++ ++ stats->tx_packets++; ++ stats->tx_bytes += MLXBF_GIGE_TX_WQE_PKT_LEN(tx_wqe_addr); ++ ++ dma_unmap_single(priv->dev, *tx_wqe_addr, ++ priv->tx_skb[tx_wqe_index]->len, DMA_TO_DEVICE); ++ dev_consume_skb_any(priv->tx_skb[tx_wqe_index]); ++ priv->tx_skb[tx_wqe_index] = NULL; ++ ++ /* Ensure completion of updates across all cores */ ++ mb(); ++ } ++ ++ /* Since the TX ring was likely just drained, check if TX queue ++ * had previously been stopped and now that there are TX buffers ++ * available the TX queue can be awakened. ++ */ ++ if (netif_queue_stopped(priv->netdev) && ++ mlxbf_gige_tx_buffs_avail(priv)) ++ netif_wake_queue(priv->netdev); ++ ++ return true; ++} ++ ++/* Function to advance the tx_wqe_next pointer to next TX WQE */ ++void mlxbf_gige_update_tx_wqe_next(struct mlxbf_gige *priv) ++{ ++ /* Advance tx_wqe_next pointer */ ++ priv->tx_wqe_next += MLXBF_GIGE_TX_WQE_SZ_QWORDS; ++ ++ /* Check if 'next' pointer is beyond end of TX ring */ ++ /* If so, set 'next' back to 'base' pointer of ring */ ++ if (priv->tx_wqe_next == (priv->tx_wqe_base + ++ (priv->tx_q_entries * MLXBF_GIGE_TX_WQE_SZ_QWORDS))) ++ priv->tx_wqe_next = priv->tx_wqe_base; ++} ++ ++netdev_tx_t mlxbf_gige_start_xmit(struct sk_buff *skb, ++ struct net_device *netdev) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ long buff_addr, start_dma_page, end_dma_page; ++ struct sk_buff *tx_skb; ++ dma_addr_t tx_buf_dma; ++ unsigned long flags; ++ u64 *tx_wqe_addr; ++ u64 word2; ++ ++ /* If needed, linearize TX SKB as hardware DMA expects this */ ++ if (skb->len > MLXBF_GIGE_DEFAULT_BUF_SZ || skb_linearize(skb)) { ++ dev_kfree_skb(skb); ++ netdev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ buff_addr = (long)skb->data; ++ start_dma_page = buff_addr >> MLXBF_GIGE_DMA_PAGE_SHIFT; ++ end_dma_page = (buff_addr + skb->len - 1) >> MLXBF_GIGE_DMA_PAGE_SHIFT; ++ ++ /* Verify that payload pointer and data length of SKB to be ++ * transmitted does not violate the hardware DMA limitation. ++ */ ++ if (start_dma_page != end_dma_page) { ++ /* DMA operation would fail as-is, alloc new aligned SKB */ ++ tx_skb = mlxbf_gige_alloc_skb(priv, skb->len, ++ &tx_buf_dma, DMA_TO_DEVICE); ++ if (!tx_skb) { ++ /* Free original skb, could not alloc new aligned SKB */ ++ dev_kfree_skb(skb); ++ netdev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ skb_put_data(tx_skb, skb->data, skb->len); ++ ++ /* Free the original SKB */ ++ dev_kfree_skb(skb); ++ } else { ++ tx_skb = skb; ++ tx_buf_dma = dma_map_single(priv->dev, skb->data, ++ skb->len, DMA_TO_DEVICE); ++ if (dma_mapping_error(priv->dev, tx_buf_dma)) { ++ dev_kfree_skb(skb); ++ netdev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ } ++ ++ /* Get address of TX WQE */ ++ tx_wqe_addr = priv->tx_wqe_next; ++ ++ mlxbf_gige_update_tx_wqe_next(priv); ++ ++ /* Put PA of buffer address into first 64-bit word of TX WQE */ ++ *tx_wqe_addr = tx_buf_dma; ++ ++ /* Set TX WQE pkt_len appropriately ++ * NOTE: GigE silicon will automatically pad up to ++ * minimum packet length if needed. ++ */ ++ word2 = tx_skb->len & MLXBF_GIGE_TX_WQE_PKT_LEN_MASK; ++ ++ /* Write entire 2nd word of TX WQE */ ++ *(tx_wqe_addr + 1) = word2; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ priv->tx_skb[priv->tx_pi % priv->tx_q_entries] = tx_skb; ++ priv->tx_pi++; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ if (!netdev_xmit_more()) { ++ /* Create memory barrier before write to TX PI */ ++ wmb(); ++ writeq(priv->tx_pi, priv->base + MLXBF_GIGE_TX_PRODUCER_INDEX); ++ } ++ ++ /* Check if the last TX entry was just used */ ++ if (!mlxbf_gige_tx_buffs_avail(priv)) { ++ /* TX ring is full, inform stack */ ++ netif_stop_queue(netdev); ++ ++ /* Since there is no separate "TX complete" interrupt, need ++ * to explicitly schedule NAPI poll. This will trigger logic ++ * which processes TX completions, and will hopefully drain ++ * the TX ring allowing the TX queue to be awakened. ++ */ ++ napi_schedule(&priv->napi); ++ } ++ ++ return NETDEV_TX_OK; ++} +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0227-mlxbf_gige-clear-valid_polarity-upon-open.patch b/platform/mellanox/non-upstream-patches/patches/0227-mlxbf_gige-clear-valid_polarity-upon-open.patch new file mode 100644 index 0000000000..bfc544b82a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0227-mlxbf_gige-clear-valid_polarity-upon-open.patch @@ -0,0 +1,53 @@ +From 245dc6df595b3c11096d96df641fbde3b38f6bb1 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Wed, 15 Sep 2021 14:08:48 -0400 +Subject: [PATCH backport 5.10 28/63] mlxbf_gige: clear valid_polarity upon + open + +The network interface managed by the mlxbf_gige driver can +get into a problem state where traffic does not flow. +In this state, the interface will be up and enabled, but +will stop processing received packets. This problem state +will happen if three specific conditions occur: + 1) driver has received more than (N * RxRingSize) packets but + less than (N+1 * RxRingSize) packets, where N is an odd number + Note: the command "ethtool -g " will display the + current receive ring size, which currently defaults to 128 + 2) the driver's interface was disabled via "ifconfig oob_net0 down" + during the window described in #1. + 3) the driver's interface is re-enabled via "ifconfig oob_net0 up" + +This patch ensures that the driver's "valid_polarity" field is +cleared during the open() method so that it always matches the +receive polarity used by hardware. Without this fix, the driver +needs to be unloaded and reloaded to correct this problem state. + +Fixes: f92e1869d74e ("Add Mellanox BlueField Gigabit Ethernet driver") +Reviewed-by: Asmaa Mnebhi +Signed-off-by: David Thompson +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index a0a059e01..04c7dc224 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -142,6 +142,13 @@ static int mlxbf_gige_open(struct net_device *netdev) + err = mlxbf_gige_clean_port(priv); + if (err) + goto free_irqs; ++ ++ /* Clear driver's valid_polarity to match hardware, ++ * since the above call to clean_port() resets the ++ * receive polarity used by hardware. ++ */ ++ priv->valid_polarity = 0; ++ + err = mlxbf_gige_rx_init(priv); + if (err) + goto free_irqs; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0228-net-mellanox-mlxbf_gige-Replace-non-standard-interru.patch b/platform/mellanox/non-upstream-patches/patches/0228-net-mellanox-mlxbf_gige-Replace-non-standard-interru.patch new file mode 100644 index 0000000000..97702355a3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0228-net-mellanox-mlxbf_gige-Replace-non-standard-interru.patch @@ -0,0 +1,368 @@ +From cad3deaacd8c633ce18a06a550551f029c3dcef1 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Fri, 15 Oct 2021 12:48:09 -0400 +Subject: [PATCH backport 5.10 29/63] net: mellanox: mlxbf_gige: Replace + non-standard interrupt handling + +BugLink: https://bugs.launchpad.net/bugs/1979827 + +Since the GPIO driver (gpio-mlxbf2.c) supports interrupt handling, +replace the custom routine with simple IRQ request. + +Signed-off-by: Asmaa Mnebhi +Acked-by: David S. Miller +Signed-off-by: Bartosz Golaszewski +(cherry picked from commit 6c2a6ddca763271fa583e22bce10c2805c1ea9f6) +Signed-off-by: Ike Panhc +--- + .../net/ethernet/mellanox/mlxbf_gige/Makefile | 1 - + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 12 - + .../mellanox/mlxbf_gige/mlxbf_gige_gpio.c | 212 ------------------ + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 22 +- + 4 files changed, 9 insertions(+), 238 deletions(-) + delete mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +index e57c1375f..a97c2bef8 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +@@ -3,7 +3,6 @@ + obj-$(CONFIG_MLXBF_GIGE) += mlxbf_gige.o + + mlxbf_gige-y := mlxbf_gige_ethtool.o \ +- mlxbf_gige_gpio.o \ + mlxbf_gige_intr.o \ + mlxbf_gige_main.o \ + mlxbf_gige_mdio.o \ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index e3509e69e..86826a70f 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -51,11 +51,6 @@ + #define MLXBF_GIGE_ERROR_INTR_IDX 0 + #define MLXBF_GIGE_RECEIVE_PKT_INTR_IDX 1 + #define MLXBF_GIGE_LLU_PLU_INTR_IDX 2 +-#define MLXBF_GIGE_PHY_INT_N 3 +- +-#define MLXBF_GIGE_MDIO_DEFAULT_PHY_ADDR 0x3 +- +-#define MLXBF_GIGE_DEFAULT_PHY_INT_GPIO 12 + + struct mlxbf_gige_stats { + u64 hw_access_errors; +@@ -81,11 +76,7 @@ struct mlxbf_gige { + struct platform_device *pdev; + void __iomem *mdio_io; + struct mii_bus *mdiobus; +- void __iomem *gpio_io; +- struct irq_domain *irqdomain; +- u32 phy_int_gpio_mask; + spinlock_t lock; /* for packet processing indices */ +- spinlock_t gpio_lock; /* for GPIO bus access */ + u16 rx_q_entries; + u16 tx_q_entries; + u64 *tx_wqe_base; +@@ -184,7 +175,4 @@ int mlxbf_gige_poll(struct napi_struct *napi, int budget); + extern const struct ethtool_ops mlxbf_gige_ethtool_ops; + void mlxbf_gige_update_tx_wqe_next(struct mlxbf_gige *priv); + +-int mlxbf_gige_gpio_init(struct platform_device *pdev, struct mlxbf_gige *priv); +-void mlxbf_gige_gpio_free(struct mlxbf_gige *priv); +- + #endif /* !defined(__MLXBF_GIGE_H__) */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c +deleted file mode 100644 +index a8d966db5..000000000 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_gpio.c ++++ /dev/null +@@ -1,212 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause +- +-/* Initialize and handle GPIO interrupt triggered by INT_N PHY signal. +- * This GPIO interrupt triggers the PHY state machine to bring the link +- * up/down. +- * +- * Copyright (C) 2021 NVIDIA CORPORATION & AFFILIATES +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "mlxbf_gige.h" +-#include "mlxbf_gige_regs.h" +- +-#define MLXBF_GIGE_GPIO_CAUSE_FALL_EN 0x48 +-#define MLXBF_GIGE_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80 +-#define MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0 0x94 +-#define MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE 0x98 +- +-static void mlxbf_gige_gpio_enable(struct mlxbf_gige *priv) +-{ +- unsigned long flags; +- u32 val; +- +- spin_lock_irqsave(&priv->gpio_lock, flags); +- val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); +- val |= priv->phy_int_gpio_mask; +- writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); +- +- /* The INT_N interrupt level is active low. +- * So enable cause fall bit to detect when GPIO +- * state goes low. +- */ +- val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_FALL_EN); +- val |= priv->phy_int_gpio_mask; +- writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_FALL_EN); +- +- /* Enable PHY interrupt by setting the priority level */ +- val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); +- val |= priv->phy_int_gpio_mask; +- writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); +- spin_unlock_irqrestore(&priv->gpio_lock, flags); +-} +- +-static void mlxbf_gige_gpio_disable(struct mlxbf_gige *priv) +-{ +- unsigned long flags; +- u32 val; +- +- spin_lock_irqsave(&priv->gpio_lock, flags); +- val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); +- val &= ~priv->phy_int_gpio_mask; +- writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0); +- spin_unlock_irqrestore(&priv->gpio_lock, flags); +-} +- +-static irqreturn_t mlxbf_gige_gpio_handler(int irq, void *ptr) +-{ +- struct mlxbf_gige *priv; +- u32 val; +- +- priv = ptr; +- +- /* Check if this interrupt is from PHY device. +- * Return if it is not. +- */ +- val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CAUSE_EVTEN0); +- if (!(val & priv->phy_int_gpio_mask)) +- return IRQ_NONE; +- +- /* Clear interrupt when done, otherwise, no further interrupt +- * will be triggered. +- */ +- val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); +- val |= priv->phy_int_gpio_mask; +- writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE); +- +- generic_handle_irq(priv->phy_irq); +- +- return IRQ_HANDLED; +-} +- +-static void mlxbf_gige_gpio_mask(struct irq_data *irqd) +-{ +- struct mlxbf_gige *priv = irq_data_get_irq_chip_data(irqd); +- +- mlxbf_gige_gpio_disable(priv); +-} +- +-static void mlxbf_gige_gpio_unmask(struct irq_data *irqd) +-{ +- struct mlxbf_gige *priv = irq_data_get_irq_chip_data(irqd); +- +- mlxbf_gige_gpio_enable(priv); +-} +- +-static struct irq_chip mlxbf_gige_gpio_chip = { +- .name = "mlxbf_gige_phy", +- .irq_mask = mlxbf_gige_gpio_mask, +- .irq_unmask = mlxbf_gige_gpio_unmask, +-}; +- +-static int mlxbf_gige_gpio_domain_map(struct irq_domain *d, +- unsigned int irq, +- irq_hw_number_t hwirq) +-{ +- irq_set_chip_data(irq, d->host_data); +- irq_set_chip_and_handler(irq, &mlxbf_gige_gpio_chip, handle_simple_irq); +- irq_set_noprobe(irq); +- +- return 0; +-} +- +-static const struct irq_domain_ops mlxbf_gige_gpio_domain_ops = { +- .map = mlxbf_gige_gpio_domain_map, +- .xlate = irq_domain_xlate_twocell, +-}; +- +-#ifdef CONFIG_ACPI +-static int mlxbf_gige_gpio_resources(struct acpi_resource *ares, +- void *data) +-{ +- struct acpi_resource_gpio *gpio; +- u32 *phy_int_gpio = data; +- +- if (ares->type == ACPI_RESOURCE_TYPE_GPIO) { +- gpio = &ares->data.gpio; +- *phy_int_gpio = gpio->pin_table[0]; +- } +- +- return 1; +-} +-#endif +- +-void mlxbf_gige_gpio_free(struct mlxbf_gige *priv) +-{ +- irq_dispose_mapping(priv->phy_irq); +- irq_domain_remove(priv->irqdomain); +-} +- +-int mlxbf_gige_gpio_init(struct platform_device *pdev, +- struct mlxbf_gige *priv) +-{ +- struct device *dev = &pdev->dev; +- struct resource *res; +- u32 phy_int_gpio = 0; +- int ret; +- +- LIST_HEAD(resources); +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_GPIO0); +- if (!res) +- return -ENODEV; +- +- priv->gpio_io = devm_ioremap(dev, res->start, resource_size(res)); +- if (!priv->gpio_io) +- return -ENOMEM; +- +-#ifdef CONFIG_ACPI +- ret = acpi_dev_get_resources(ACPI_COMPANION(dev), +- &resources, mlxbf_gige_gpio_resources, +- &phy_int_gpio); +- acpi_dev_free_resource_list(&resources); +- if (ret < 0 || !phy_int_gpio) { +- dev_err(dev, "Error retrieving the gpio phy pin"); +- return -EINVAL; +- } +-#endif +- +- priv->phy_int_gpio_mask = BIT(phy_int_gpio); +- +- mlxbf_gige_gpio_disable(priv); +- +- priv->hw_phy_irq = platform_get_irq(pdev, MLXBF_GIGE_PHY_INT_N); +- +- priv->irqdomain = irq_domain_add_simple(NULL, 1, 0, +- &mlxbf_gige_gpio_domain_ops, +- priv); +- if (!priv->irqdomain) { +- dev_err(dev, "Failed to add IRQ domain\n"); +- return -ENOMEM; +- } +- +- priv->phy_irq = irq_create_mapping(priv->irqdomain, 0); +- if (!priv->phy_irq) { +- irq_domain_remove(priv->irqdomain); +- priv->irqdomain = NULL; +- dev_err(dev, "Error mapping PHY IRQ\n"); +- return -EINVAL; +- } +- +- ret = devm_request_irq(dev, priv->hw_phy_irq, mlxbf_gige_gpio_handler, +- IRQF_ONESHOT | IRQF_SHARED, "mlxbf_gige_phy", priv); +- if (ret) { +- dev_err(dev, "Failed to request PHY IRQ"); +- mlxbf_gige_gpio_free(priv); +- return ret; +- } +- +- return ret; +-} +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index 04c7dc224..e4ed38bbd 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -283,8 +283,8 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + void __iomem *llu_base; + void __iomem *plu_base; + void __iomem *base; ++ int addr, phy_irq; + u64 control; +- int addr; + int err; + + mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC); +@@ -331,20 +331,12 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + priv->pdev = pdev; + + spin_lock_init(&priv->lock); +- spin_lock_init(&priv->gpio_lock); + + /* Attach MDIO device */ + err = mlxbf_gige_mdio_probe(pdev, priv); + if (err) + return err; + +- err = mlxbf_gige_gpio_init(pdev, priv); +- if (err) { +- dev_err(&pdev->dev, "PHY IRQ initialization failed\n"); +- mlxbf_gige_mdio_remove(priv); +- return -ENODEV; +- } +- + priv->base = base; + priv->llu_base = llu_base; + priv->plu_base = plu_base; +@@ -365,6 +357,12 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + priv->rx_irq = platform_get_irq(pdev, MLXBF_GIGE_RECEIVE_PKT_INTR_IDX); + priv->llu_plu_irq = platform_get_irq(pdev, MLXBF_GIGE_LLU_PLU_INTR_IDX); + ++ phy_irq = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(&pdev->dev), "phy-gpios", 0); ++ if (phy_irq < 0) { ++ dev_err(&pdev->dev, "Error getting PHY irq. Use polling instead"); ++ phy_irq = PHY_POLL; ++ } ++ + phydev = phy_find_first(priv->mdiobus); + if (!phydev) { + err = -ENODEV; +@@ -372,8 +370,8 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + } + + addr = phydev->mdio.addr; +- priv->mdiobus->irq[addr] = priv->phy_irq; +- phydev->irq = priv->phy_irq; ++ priv->mdiobus->irq[addr] = phy_irq; ++ phydev->irq = phy_irq; + + err = phy_connect_direct(netdev, phydev, + mlxbf_gige_adjust_link, +@@ -409,7 +407,6 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + return 0; + + out: +- mlxbf_gige_gpio_free(priv); + mlxbf_gige_mdio_remove(priv); + return err; + } +@@ -420,7 +417,6 @@ static int mlxbf_gige_remove(struct platform_device *pdev) + + unregister_netdev(priv->netdev); + phy_disconnect(priv->netdev->phydev); +- mlxbf_gige_gpio_free(priv); + mlxbf_gige_mdio_remove(priv); + platform_set_drvdata(pdev, NULL); + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0229-mlxbf_gige-increase-MDIO-polling-rate-to-5us.patch b/platform/mellanox/non-upstream-patches/patches/0229-mlxbf_gige-increase-MDIO-polling-rate-to-5us.patch new file mode 100644 index 0000000000..b0020cca17 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0229-mlxbf_gige-increase-MDIO-polling-rate-to-5us.patch @@ -0,0 +1,52 @@ +From a8ab0bbc8f17a0099c4982f3e0cb78f6c323fa46 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Thu, 5 May 2022 12:23:09 -0400 +Subject: [PATCH backport 5.10 30/63] mlxbf_gige: increase MDIO polling rate to + 5us + +BugLink: https://bugs.launchpad.net/bugs/1979827 + +This patch increases the polling rate used by the +mlxbf_gige driver on the MDIO bus. The previous +polling rate was every 100us, and the new rate is +every 5us. With this change the amount of time +spent waiting for the MDIO BUSY signal to de-assert +drops from ~100us to ~27us for each operation. + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +Link: https://lore.kernel.org/r/20220505162309.20050-1-davthompson@nvidia.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 0a02e282bad4dad455553fc2b9268cf1d003f132) +Signed-off-by: Ike Panhc +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +index e32dd34fd..6c8a4a529 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -105,7 +105,8 @@ static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg) + writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); + + ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET, +- val, !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK), 100, 1000000); ++ val, !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK), ++ 5, 1000000); + + if (ret) { + writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); +@@ -137,7 +138,8 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add, + + /* If the poll timed out, drop the request */ + ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET, +- temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK), 100, 1000000); ++ temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK), ++ 5, 1000000); + + return ret; + } +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0230-mlxbf_gige-remove-driver-managed-interrupt-counts.patch b/platform/mellanox/non-upstream-patches/patches/0230-mlxbf_gige-remove-driver-managed-interrupt-counts.patch new file mode 100644 index 0000000000..fb80c63de8 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0230-mlxbf_gige-remove-driver-managed-interrupt-counts.patch @@ -0,0 +1,97 @@ +From 4eafb2c053cc5935fe826da97fda42abadab5fc1 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Wed, 11 May 2022 09:52:51 -0400 +Subject: [PATCH backport 5.10 31/63] mlxbf_gige: remove driver-managed + interrupt counts + +BugLink: https://bugs.launchpad.net/bugs/1979827 + +The driver currently has three interrupt counters, +which are incremented every time each interrupt handler +executes. These driver-managed counters are not +necessary as the kernel already has logic that manages +interrupt counts and exposes them via /proc/interrupts. +This patch removes the driver-managed counters. + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +Link: https://lore.kernel.org/r/20220511135251.2989-1-davthompson@nvidia.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit f4826443f4d69d2c97c184952c085caf0936a7b8) +Signed-off-by: Ike Panhc +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 3 --- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | 8 +++----- + .../net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c | 9 --------- + 3 files changed, 3 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index 86826a70f..5fdf9b717 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -90,9 +90,6 @@ struct mlxbf_gige { + dma_addr_t rx_cqe_base_dma; + u16 tx_pi; + u16 prev_tx_ci; +- u64 error_intr_count; +- u64 rx_intr_count; +- u64 llu_plu_intr_count; + struct sk_buff *rx_skb[MLXBF_GIGE_MAX_RXQ_SZ]; + struct sk_buff *tx_skb[MLXBF_GIGE_MAX_TXQ_SZ]; + int error_irq; +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +index 92b798f8e..af46b0cd7 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +@@ -24,11 +24,9 @@ static void mlxbf_gige_get_regs(struct net_device *netdev, + regs->version = MLXBF_GIGE_REGS_VERSION; + + /* Read entire MMIO register space and store results +- * into the provided buffer. Each 64-bit word is converted +- * to big-endian to make the output more readable. +- * +- * NOTE: by design, a read to an offset without an existing +- * register will be acknowledged and return zero. ++ * into the provided buffer. By design, a read to an ++ * offset without an existing register will be ++ * acknowledged and return zero. + */ + memcpy_fromio(p, priv->base, MLXBF_GIGE_MMIO_REG_SZ); + } +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c +index c38795be0..5b3519f0c 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c +@@ -17,8 +17,6 @@ static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id) + + priv = dev_id; + +- priv->error_intr_count++; +- + int_status = readq(priv->base + MLXBF_GIGE_INT_STATUS); + + if (int_status & MLXBF_GIGE_INT_STATUS_HW_ACCESS_ERROR) +@@ -75,8 +73,6 @@ static irqreturn_t mlxbf_gige_rx_intr(int irq, void *dev_id) + + priv = dev_id; + +- priv->rx_intr_count++; +- + /* NOTE: GigE silicon automatically disables "packet rx" interrupt by + * setting MLXBF_GIGE_INT_MASK bit0 upon triggering the interrupt + * to the ARM cores. Software needs to re-enable "packet rx" +@@ -90,11 +86,6 @@ static irqreturn_t mlxbf_gige_rx_intr(int irq, void *dev_id) + + static irqreturn_t mlxbf_gige_llu_plu_intr(int irq, void *dev_id) + { +- struct mlxbf_gige *priv; +- +- priv = dev_id; +- priv->llu_plu_intr_count++; +- + return IRQ_HANDLED; + } + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0231-mlxbf_gige-remove-own-module-name-define-and-use-KBU.patch b/platform/mellanox/non-upstream-patches/patches/0231-mlxbf_gige-remove-own-module-name-define-and-use-KBU.patch new file mode 100644 index 0000000000..a21ada96ab --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0231-mlxbf_gige-remove-own-module-name-define-and-use-KBU.patch @@ -0,0 +1,46 @@ +From 62164fc6ed2a1ae28dbf3cf16c9ecfa0c23b2b3d Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Tue, 14 Jun 2022 17:26:02 -0400 +Subject: [PATCH backport 5.10 32/63] mlxbf_gige: remove own module name define + and use KBUILD_MODNAME instead + +BugLink: https://bugs.launchpad.net/bugs/1979827 + +This patch adds use of KBUILD_MODNAME as defined by the build system, +replacing the definition and use of a custom-defined name. + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +Link: https://lore.kernel.org/r/20220614212602.28061-1-davthompson@nvidia.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit linux-next cfbc80e34e3a905f5e89e7c0bc133a9507b05a28) +Signed-off-by: Ike Panhc +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index e4ed38bbd..e8f9290a8 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -19,8 +19,6 @@ + #include "mlxbf_gige.h" + #include "mlxbf_gige_regs.h" + +-#define DRV_NAME "mlxbf_gige" +- + /* Allocate SKB whose payload pointer aligns with the Bluefield + * hardware DMA limitation, i.e. DMA operation can't cross + * a 4KB boundary. A maximum packet size of 2KB is assumed in the +@@ -442,7 +440,7 @@ static struct platform_driver mlxbf_gige_driver = { + .remove = mlxbf_gige_remove, + .shutdown = mlxbf_gige_shutdown, + .driver = { +- .name = DRV_NAME, ++ .name = KBUILD_MODNAME, + .acpi_match_table = ACPI_PTR(mlxbf_gige_acpi_match), + }, + }; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0232-UBUNTU-SAUCE-mlxbf_gige-add-ethtool-mlxbf_gige_set_r.patch b/platform/mellanox/non-upstream-patches/patches/0232-UBUNTU-SAUCE-mlxbf_gige-add-ethtool-mlxbf_gige_set_r.patch new file mode 100644 index 0000000000..ffa4eabcda --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0232-UBUNTU-SAUCE-mlxbf_gige-add-ethtool-mlxbf_gige_set_r.patch @@ -0,0 +1,78 @@ +From 422290c8c36a7a92a64fecea45f431794dc99be6 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Thu, 14 Jul 2022 17:47:18 -0400 +Subject: [PATCH backport 5.10 33/63] UBUNTU: SAUCE: mlxbf_gige: add ethtool + mlxbf_gige_set_ringparam + +This patch adds the "set_ringparam" callback, to be used by +ethtool when changing the size of the mlxbf_gige driver rings. + +BugLink: https://launchpad.net/bugs/1981766 + +Change-Id: I0198f6fbf6b8ea13bd34ed152e13298265138c76 +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Ike Panhc +--- + .../mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | 38 +++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +index af46b0cd7..257724323 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +@@ -42,6 +42,43 @@ static void mlxbf_gige_get_ringparam(struct net_device *netdev, + ering->tx_pending = priv->tx_q_entries; + } + ++static int mlxbf_gige_set_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ering) ++{ ++ const struct net_device_ops *ops = netdev->netdev_ops; ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ int new_rx_q_entries, new_tx_q_entries; ++ ++ /* Device does not have separate queues for small/large frames */ ++ if (ering->rx_mini_pending || ering->rx_jumbo_pending) ++ return -EINVAL; ++ ++ /* Round up to supported values */ ++ new_rx_q_entries = roundup_pow_of_two(ering->rx_pending); ++ new_tx_q_entries = roundup_pow_of_two(ering->tx_pending); ++ ++ /* Check against min values, core checks against max values */ ++ if (new_tx_q_entries < MLXBF_GIGE_MIN_TXQ_SZ || ++ new_rx_q_entries < MLXBF_GIGE_MIN_RXQ_SZ) ++ return -EINVAL; ++ ++ /* If queue sizes did not change, exit now */ ++ if (new_rx_q_entries == priv->rx_q_entries && ++ new_tx_q_entries == priv->tx_q_entries) ++ return 0; ++ ++ if (netif_running(netdev)) ++ ops->ndo_stop(netdev); ++ ++ priv->rx_q_entries = new_rx_q_entries; ++ priv->tx_q_entries = new_tx_q_entries; ++ ++ if (netif_running(netdev)) ++ ops->ndo_open(netdev); ++ ++ return 0; ++} ++ + static const struct { + const char string[ETH_GSTRING_LEN]; + } mlxbf_gige_ethtool_stats_keys[] = { +@@ -124,6 +161,7 @@ static void mlxbf_gige_get_pauseparam(struct net_device *netdev, + const struct ethtool_ops mlxbf_gige_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_ringparam = mlxbf_gige_get_ringparam, ++ .set_ringparam = mlxbf_gige_set_ringparam, + .get_regs_len = mlxbf_gige_get_regs_len, + .get_regs = mlxbf_gige_get_regs, + .get_strings = mlxbf_gige_get_strings, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0233-UBUNTU-SAUCE-Fix-OOB-handling-RX-packets-in-heavy-tr.patch b/platform/mellanox/non-upstream-patches/patches/0233-UBUNTU-SAUCE-Fix-OOB-handling-RX-packets-in-heavy-tr.patch new file mode 100644 index 0000000000..32338657d4 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0233-UBUNTU-SAUCE-Fix-OOB-handling-RX-packets-in-heavy-tr.patch @@ -0,0 +1,108 @@ +From 30e4a53201f1f1cd9ca90057cd8f191c93fdab15 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Wed, 20 Jul 2022 17:50:36 -0400 +Subject: [PATCH backport 5.10 34/63] UBUNTU: SAUCE: Fix OOB handling RX + packets in heavy traffic + +BugLink: https://bugs.launchpad.net/bugs/1982424 + +This is reproducible on systems which already have heavy background +traffic. On top of that, the user issues one of the 2 docker pulls below: +docker pull nvcr.io/ea-doca-hbn/hbn/hbn:latest +OR +docker pull gitlab-master.nvidia.com:5005/dl/dgx/tritonserver:22.02-py3-qa + +The second one is a very large container (17GB) + +When they run docker pull, the OOB interface stops being pingable, +the docker pull is interrupted for a very long time (>3mn) or +times out. + +The main reason for the above is because RX PI = RX CI. I have verified that +by reading RX_CQE_PACKET_CI and RX_WQE_PI. This means the WQEs are full and +HW has nowhere else to put the RX packets. + +I believe there is a race condition after SW receives a RX interrupt, +and the interrupt is disabled. I believe HW still tries to add RX +packets to the RX WQEs. So we need to stop the RX traffic by disabling +the DMA. Also, move reading the RX CI before writing the increased value +of RX PI to MLXBF_GIGE_RX_WQE_PI. Normally RX PI should always be > RX CI. +I suspect that when entering mlxbf_gige_rx_packet, for example we have: +MLXBF_GIGE_RX_WQE_PI = 128 +RX_CQE_PACKET_CI = 128 +(128 being the max size of the WQE) + +Then this code will make MLXBF_GIGE_RX_WQE_PI = 129: +rx_pi++; +/* Ensure completion of all writes before notifying HW of replenish */ +wmb(); +writeq(rx_pi, priv->base + MLXBF_GIGE_RX_WQE_PI); + +which means HW has one more slot to populate and in that time span, the HW +populates that WQE and increases the RX_CQE_PACKET_CI = 129. + +Then this code is subject to a race condition: + +rx_ci = readq(priv->base + MLXBF_GIGE_RX_CQE_PACKET_CI); +rx_ci_rem = rx_ci % priv->rx_q_entries; +return rx_pi_rem != rx_ci_rem; + +because rx_pi_rem will be equal to rx_ci_rem. +so remaining_pkts will be 0 and we will exit mlxbf_gige_poll + +Change-Id: I25a816b9182471643db95b05c803b9f6349bcc87 +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Ike Panhc +--- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +index afa3b92a6..96230763c 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +@@ -266,6 +266,9 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts) + priv->stats.rx_truncate_errors++; + } + ++ rx_ci = readq(priv->base + MLXBF_GIGE_RX_CQE_PACKET_CI); ++ rx_ci_rem = rx_ci % priv->rx_q_entries; ++ + /* Let hardware know we've replenished one buffer */ + rx_pi++; + +@@ -278,8 +281,6 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts) + rx_pi_rem = rx_pi % priv->rx_q_entries; + if (rx_pi_rem == 0) + priv->valid_polarity ^= 1; +- rx_ci = readq(priv->base + MLXBF_GIGE_RX_CQE_PACKET_CI); +- rx_ci_rem = rx_ci % priv->rx_q_entries; + + if (skb) + netif_receive_skb(skb); +@@ -299,6 +300,10 @@ int mlxbf_gige_poll(struct napi_struct *napi, int budget) + + mlxbf_gige_handle_tx_complete(priv); + ++ data = readq(priv->base + MLXBF_GIGE_RX_DMA); ++ data &= ~MLXBF_GIGE_RX_DMA_EN; ++ writeq(data, priv->base + MLXBF_GIGE_RX_DMA); ++ + do { + remaining_pkts = mlxbf_gige_rx_packet(priv, &work_done); + } while (remaining_pkts && work_done < budget); +@@ -314,6 +319,10 @@ int mlxbf_gige_poll(struct napi_struct *napi, int budget) + data = readq(priv->base + MLXBF_GIGE_INT_MASK); + data &= ~MLXBF_GIGE_INT_MASK_RX_RECEIVE_PACKET; + writeq(data, priv->base + MLXBF_GIGE_INT_MASK); ++ ++ data = readq(priv->base + MLXBF_GIGE_RX_DMA); ++ data |= MLXBF_GIGE_RX_DMA_EN; ++ writeq(data, priv->base + MLXBF_GIGE_RX_DMA); + } + + return work_done; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0234-UBUNTU-SAUCE-mlxbf_gige-add-validation-of-ACPI-table.patch b/platform/mellanox/non-upstream-patches/patches/0234-UBUNTU-SAUCE-mlxbf_gige-add-validation-of-ACPI-table.patch new file mode 100644 index 0000000000..3d6cbb2134 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0234-UBUNTU-SAUCE-mlxbf_gige-add-validation-of-ACPI-table.patch @@ -0,0 +1,62 @@ +From 8c7dd66540096a636aa35406cdb023dd549e2755 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Wed, 20 Jul 2022 18:17:09 -0400 +Subject: [PATCH backport 5.10 35/63] UBUNTU: SAUCE: mlxbf_gige: add validation + of ACPI table version + +BugLink: https://bugs.launchpad.net/bugs/1982427 + +This patch checks the "version" property in the OOB ACPI table, +ensuring that the driver probe will only succeed if the expected +version is found. + +Change-Id: I8dc1f877338f9b23ab3560c0315a1727e144dd57 +Signed-off-by: David Thompson +Signed-off-by: Ike Panhc +--- + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index e8f9290a8..c9176a2e6 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -19,6 +19,11 @@ + #include "mlxbf_gige.h" + #include "mlxbf_gige_regs.h" + ++/* This setting defines the version of the ACPI table ++ * content that is compatible with this driver version. ++ */ ++#define MLXBF_GIGE_ACPI_TABLE_VERSION 2 ++ + /* Allocate SKB whose payload pointer aligns with the Bluefield + * hardware DMA limitation, i.e. DMA operation can't cross + * a 4KB boundary. A maximum packet size of 2KB is assumed in the +@@ -282,9 +287,23 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + void __iomem *plu_base; + void __iomem *base; + int addr, phy_irq; ++ u32 version; + u64 control; + int err; + ++ version = 0; ++ err = device_property_read_u32(&pdev->dev, "version", &version); ++ if (err) { ++ dev_err(&pdev->dev, "ACPI table version not found\n"); ++ return -EINVAL; ++ } ++ ++ if (version != MLXBF_GIGE_ACPI_TABLE_VERSION) { ++ dev_err(&pdev->dev, "ACPI table version mismatch: expected %d found %d\n", ++ MLXBF_GIGE_ACPI_TABLE_VERSION, version); ++ return -EINVAL; ++ } ++ + mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC); + if (!mac_res) + return -ENXIO; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0235-UBUNTU-SAUCE-mlxbf_gige-set-driver-version-to-1.27.patch b/platform/mellanox/non-upstream-patches/patches/0235-UBUNTU-SAUCE-mlxbf_gige-set-driver-version-to-1.27.patch new file mode 100644 index 0000000000..1f0fcabc87 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0235-UBUNTU-SAUCE-mlxbf_gige-set-driver-version-to-1.27.patch @@ -0,0 +1,39 @@ +From 438c36fd4f5ca577d03d50d0d037e44a2d25edd1 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Wed, 20 Jul 2022 18:59:14 -0400 +Subject: [PATCH backport 5.10 36/63] UBUNTU: SAUCE: mlxbf_gige: set driver + version to 1.27 + +BugLink: https://bugs.launchpad.net/bugs/1982431 + +This patch adds logic to specify the driver version +via MODULE_VERSION() and sets the value to 1.27 + +Change-Id: I91f775df119877ad6d6eeaa5e5f93dcf1b55c8d2 +Signed-off-by: David Thompson +Signed-off-by: Ike Panhc +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index c9176a2e6..66a50e35f 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -19,6 +19,8 @@ + #include "mlxbf_gige.h" + #include "mlxbf_gige_regs.h" + ++#define DRV_VERSION 1.27 ++ + /* This setting defines the version of the ACPI table + * content that is compatible with this driver version. + */ +@@ -470,3 +472,4 @@ MODULE_DESCRIPTION("Mellanox BlueField SoC Gigabit Ethernet Driver"); + MODULE_AUTHOR("David Thompson "); + MODULE_AUTHOR("Asmaa Mnebhi "); + MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(__stringify(DRV_VERSION)); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0236-UBUNTU-SAUCE-mlxbf_gige-clear-MDIO-gateway-lock-afte.patch b/platform/mellanox/non-upstream-patches/patches/0236-UBUNTU-SAUCE-mlxbf_gige-clear-MDIO-gateway-lock-afte.patch new file mode 100644 index 0000000000..1376f1169c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0236-UBUNTU-SAUCE-mlxbf_gige-clear-MDIO-gateway-lock-afte.patch @@ -0,0 +1,46 @@ +From 7c7da04799f5fe6f7f5751d413dcdf04abe5ea53 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Tue, 13 Sep 2022 13:15:14 -0400 +Subject: [PATCH backport 5.10 37/63] UBUNTU: SAUCE: mlxbf_gige: clear MDIO + gateway lock after read + +BugLink: https://bugs.launchpad.net/bugs/1989495 + +The MDIO gateway (GW) lock in BlueField-2 GIGE logic is +set after read. This patch adds logic to make sure the +lock is always cleared at the end of each MDIO transaction. + +Reviewed-by: Asmaa Mnebhi +Signed-off-by: David Thompson +Signed-off-by: Ike Panhc +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +index 6c8a4a529..b7363c6c3 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -117,6 +117,9 @@ static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg) + /* Only return ad bits of the gw register */ + ret &= MLXBF_GIGE_MDIO_GW_AD_MASK; + ++ /* The MDIO lock is set on read. To release it, clear gw register */ ++ writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ + return ret; + } + +@@ -141,6 +144,9 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add, + temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK), + 5, 1000000); + ++ /* The MDIO lock is set on read. To release it, clear gw register */ ++ writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ + return ret; + } + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0237-mlxbf_gige-compute-MDIO-period-based-on-i1clk.patch b/platform/mellanox/non-upstream-patches/patches/0237-mlxbf_gige-compute-MDIO-period-based-on-i1clk.patch new file mode 100644 index 0000000000..fba0668a54 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0237-mlxbf_gige-compute-MDIO-period-based-on-i1clk.patch @@ -0,0 +1,244 @@ +From 793a81817df0dcee08aad3385a6971895437ab80 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Fri, 26 Aug 2022 11:59:16 -0400 +Subject: [PATCH backport 5.10 38/63] mlxbf_gige: compute MDIO period based on + i1clk + +BugLink: https://launchpad.net/bugs/1989035 + +This patch adds logic to compute the MDIO period based on +the i1clk, and thereafter write the MDIO period into the YU +MDIO config register. The i1clk resource from the ACPI table +is used to provide addressing to YU bootrecord PLL registers. +The values in these registers are used to compute MDIO period. +If the i1clk resource is not present in the ACPI table, then +the current default hardcorded value of 430Mhz is used. +The i1clk clock value of 430MHz is only accurate for boards +with BF2 mid bin and main bin SoCs. The BF2 high bin SoCs +have i1clk = 500MHz, but can support a slower MDIO period. + +Fixes: f92e1869d74e ("Add Mellanox BlueField Gigabit Ethernet driver") +Reviewed-by: Asmaa Mnebhi +Signed-off-by: David Thompson +Link: https://lore.kernel.org/r/20220826155916.12491-1-davthompson@nvidia.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 3a1a274e933fca73fdc960cb1f60636cd285a265) +Signed-off-by: Ike Panhc +--- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 4 +- + .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 121 +++++++++++++++--- + .../mellanox/mlxbf_gige/mlxbf_gige_regs.h | 2 + + 3 files changed, 109 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index 5fdf9b717..5a1027b07 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -75,6 +75,7 @@ struct mlxbf_gige { + struct net_device *netdev; + struct platform_device *pdev; + void __iomem *mdio_io; ++ void __iomem *clk_io; + struct mii_bus *mdiobus; + spinlock_t lock; /* for packet processing indices */ + u16 rx_q_entries; +@@ -137,7 +138,8 @@ enum mlxbf_gige_res { + MLXBF_GIGE_RES_MDIO9, + MLXBF_GIGE_RES_GPIO0, + MLXBF_GIGE_RES_LLU, +- MLXBF_GIGE_RES_PLU ++ MLXBF_GIGE_RES_PLU, ++ MLXBF_GIGE_RES_CLK + }; + + /* Version of register data returned by mlxbf_gige_get_regs() */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +index b7363c6c3..736849d07 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -22,10 +22,23 @@ + #include + + #include "mlxbf_gige.h" ++#include "mlxbf_gige_regs.h" + + #define MLXBF_GIGE_MDIO_GW_OFFSET 0x0 + #define MLXBF_GIGE_MDIO_CFG_OFFSET 0x4 + ++#define MLXBF_GIGE_MDIO_FREQ_REFERENCE 156250000ULL ++#define MLXBF_GIGE_MDIO_COREPLL_CONST 16384ULL ++#define MLXBF_GIGE_MDC_CLK_NS 400 ++#define MLXBF_GIGE_MDIO_PLL_I1CLK_REG1 0x4 ++#define MLXBF_GIGE_MDIO_PLL_I1CLK_REG2 0x8 ++#define MLXBF_GIGE_MDIO_CORE_F_SHIFT 0 ++#define MLXBF_GIGE_MDIO_CORE_F_MASK GENMASK(25, 0) ++#define MLXBF_GIGE_MDIO_CORE_R_SHIFT 26 ++#define MLXBF_GIGE_MDIO_CORE_R_MASK GENMASK(31, 26) ++#define MLXBF_GIGE_MDIO_CORE_OD_SHIFT 0 ++#define MLXBF_GIGE_MDIO_CORE_OD_MASK GENMASK(3, 0) ++ + /* Support clause 22 */ + #define MLXBF_GIGE_MDIO_CL22_ST1 0x1 + #define MLXBF_GIGE_MDIO_CL22_WRITE 0x1 +@@ -50,27 +63,76 @@ + #define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16) + #define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24) + ++#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \ ++ FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13)) ++ ++#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30 ++#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c ++ ++static struct resource corepll_params[] = { ++ [MLXBF_GIGE_VERSION_BF2] = { ++ .start = MLXBF_GIGE_BF2_COREPLL_ADDR, ++ .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1, ++ .name = "COREPLL_RES" ++ }, ++}; ++ ++/* Returns core clock i1clk in Hz */ ++static u64 calculate_i1clk(struct mlxbf_gige *priv) ++{ ++ u8 core_od, core_r; ++ u64 freq_output; ++ u32 reg1, reg2; ++ u32 core_f; ++ ++ reg1 = readl(priv->clk_io + MLXBF_GIGE_MDIO_PLL_I1CLK_REG1); ++ reg2 = readl(priv->clk_io + MLXBF_GIGE_MDIO_PLL_I1CLK_REG2); ++ ++ core_f = (reg1 & MLXBF_GIGE_MDIO_CORE_F_MASK) >> ++ MLXBF_GIGE_MDIO_CORE_F_SHIFT; ++ core_r = (reg1 & MLXBF_GIGE_MDIO_CORE_R_MASK) >> ++ MLXBF_GIGE_MDIO_CORE_R_SHIFT; ++ core_od = (reg2 & MLXBF_GIGE_MDIO_CORE_OD_MASK) >> ++ MLXBF_GIGE_MDIO_CORE_OD_SHIFT; ++ ++ /* Compute PLL output frequency as follow: ++ * ++ * CORE_F / 16384 ++ * freq_output = freq_reference * ---------------------------- ++ * (CORE_R + 1) * (CORE_OD + 1) ++ */ ++ freq_output = div_u64((MLXBF_GIGE_MDIO_FREQ_REFERENCE * core_f), ++ MLXBF_GIGE_MDIO_COREPLL_CONST); ++ freq_output = div_u64(freq_output, (core_r + 1) * (core_od + 1)); ++ ++ return freq_output; ++} ++ + /* Formula for encoding the MDIO period. The encoded value is + * passed to the MDIO config register. + * +- * mdc_clk = 2*(val + 1)*i1clk ++ * mdc_clk = 2*(val + 1)*(core clock in sec) + * +- * 400 ns = 2*(val + 1)*(((1/430)*1000) ns) ++ * i1clk is in Hz: ++ * 400 ns = 2*(val + 1)*(1/i1clk) + * +- * val = (((400 * 430 / 1000) / 2) - 1) ++ * val = (((400/10^9) / (1/i1clk) / 2) - 1) ++ * val = (400/2 * i1clk)/10^9 - 1 + */ +-#define MLXBF_GIGE_I1CLK_MHZ 430 +-#define MLXBF_GIGE_MDC_CLK_NS 400 ++static u8 mdio_period_map(struct mlxbf_gige *priv) ++{ ++ u8 mdio_period; ++ u64 i1clk; + +-#define MLXBF_GIGE_MDIO_PERIOD (((MLXBF_GIGE_MDC_CLK_NS * MLXBF_GIGE_I1CLK_MHZ / 1000) / 2) - 1) ++ i1clk = calculate_i1clk(priv); + +-#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, \ +- MLXBF_GIGE_MDIO_PERIOD) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13)) ++ mdio_period = div_u64((MLXBF_GIGE_MDC_CLK_NS >> 1) * i1clk, 1000000000) - 1; ++ ++ return mdio_period; ++} + + static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add, + int phy_reg, u32 opcode) +@@ -127,9 +189,9 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add, + int phy_reg, u16 val) + { + struct mlxbf_gige *priv = bus->priv; ++ u32 temp; + u32 cmd; + int ret; +- u32 temp; + + if (phy_reg & MII_ADDR_C45) + return -EOPNOTSUPP; +@@ -150,6 +212,18 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add, + return ret; + } + ++static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv) ++{ ++ u8 mdio_period; ++ u32 val; ++ ++ mdio_period = mdio_period_map(priv); ++ ++ val = MLXBF_GIGE_MDIO_CFG_VAL; ++ val |= FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period); ++ writel(val, priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET); ++} ++ + int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + { + struct device *dev = &pdev->dev; +@@ -164,9 +238,22 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + if (IS_ERR(priv->mdio_io)) + return PTR_ERR(priv->mdio_io); + +- /* Configure mdio parameters */ +- writel(MLXBF_GIGE_MDIO_CFG_VAL, +- priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET); ++ /* clk resource shared with other drivers so cannot use ++ * devm_platform_ioremap_resource ++ */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK); ++ if (!res) { ++ /* For backward compatibility with older ACPI tables, also keep ++ * CLK resource internal to the driver. ++ */ ++ res = &corepll_params[MLXBF_GIGE_VERSION_BF2]; ++ } ++ ++ priv->clk_io = devm_ioremap(dev, res->start, resource_size(res)); ++ if (IS_ERR(priv->clk_io)) ++ return PTR_ERR(priv->clk_io); ++ ++ mlxbf_gige_mdio_cfg(priv); + + priv->mdiobus = devm_mdiobus_alloc(dev); + if (!priv->mdiobus) { +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +index 5fb33c929..7be3a7939 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +@@ -8,6 +8,8 @@ + #ifndef __MLXBF_GIGE_REGS_H__ + #define __MLXBF_GIGE_REGS_H__ + ++#define MLXBF_GIGE_VERSION 0x0000 ++#define MLXBF_GIGE_VERSION_BF2 0x0 + #define MLXBF_GIGE_STATUS 0x0010 + #define MLXBF_GIGE_STATUS_READY BIT(0) + #define MLXBF_GIGE_INT_STATUS 0x0028 +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0238-net-mlxbf_gige-Fix-an-IS_ERR-vs-NULL-bug-in-mlxbf_gi.patch b/platform/mellanox/non-upstream-patches/patches/0238-net-mlxbf_gige-Fix-an-IS_ERR-vs-NULL-bug-in-mlxbf_gi.patch new file mode 100644 index 0000000000..dbbfa96154 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0238-net-mlxbf_gige-Fix-an-IS_ERR-vs-NULL-bug-in-mlxbf_gi.patch @@ -0,0 +1,42 @@ +From f6a48751ea5c5943d9eb6e0d7711215ac5aad6c3 Mon Sep 17 00:00:00 2001 +From: Peng Wu +Date: Fri, 30 Sep 2022 11:24:45 -0400 +Subject: [PATCH backport 5.10 39/63] net/mlxbf_gige: Fix an IS_ERR() vs NULL + bug in mlxbf_gige_mdio_probe + +BugLink: https://bugs.launchpad.net/bugs/1991403 + +The devm_ioremap() function returns NULL on error, it doesn't return +error pointers. + +Fixes: 3a1a274e933f ("mlxbf_gige: compute MDIO period based on i1clk") +Signed-off-by: Peng Wu +Link: https://lore.kernel.org/r/20220923023640.116057-1-wupeng58@huawei.com +Signed-off-by: Jakub Kicinski +(cherry picked from commit 4774db8dfc6a2e6649920ebb2fc8e2f062c2080d) +Signed-off-by: David Thompson +Acked-by: Tim Gardner +Acked-by: Kleber Sacilotto de Souza +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +index 736849d07..daa31ddb2 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -250,8 +250,8 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + } + + priv->clk_io = devm_ioremap(dev, res->start, resource_size(res)); +- if (IS_ERR(priv->clk_io)) +- return PTR_ERR(priv->clk_io); ++ if (!priv->clk_io) ++ return -ENOMEM; + + mlxbf_gige_mdio_cfg(priv); + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0239-UBUNTU-SAUCE-mlxbf_gige-add-MDIO-support-for-BlueFie.patch b/platform/mellanox/non-upstream-patches/patches/0239-UBUNTU-SAUCE-mlxbf_gige-add-MDIO-support-for-BlueFie.patch new file mode 100644 index 0000000000..9403bb5ba6 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0239-UBUNTU-SAUCE-mlxbf_gige-add-MDIO-support-for-BlueFie.patch @@ -0,0 +1,484 @@ +From 6073dbcdbce9c9f8e63790217b17913efb5174c5 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Tue, 25 Oct 2022 16:25:19 -0400 +Subject: [PATCH backport 5.10 40/63] UBUNTU: SAUCE: mlxbf_gige: add MDIO + support for BlueField-3 + +BugLink: https://bugs.launchpad.net/bugs/1995148 + +This patch adds initial MDIO support for the BlueField-3 +SoC. Separate header files for the BlueField-2 and the +BlueField-3 SoCs have been created. These header files +hold the SoC-specific MDIO macros since the register +offsets and bit fields have changed. Also, in BlueField-3 +there is a separate register for writing and reading the +MDIO data. Finally, instead of having "if" statements +everywhere to differentiate between SoC-specific logic, +a mlxbf_gige_mdio_gw_t struct was created for this purpose. + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +--- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 19 ++ + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 2 + + .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 172 +++++++++++++----- + .../mellanox/mlxbf_gige/mlxbf_gige_mdio_bf2.h | 53 ++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_mdio_bf3.h | 54 ++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_regs.h | 1 + + 6 files changed, 251 insertions(+), 50 deletions(-) + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf2.h + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf3.h + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index 5a1027b07..421a0b1b7 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -67,6 +67,23 @@ struct mlxbf_gige_stats { + u64 rx_filter_discard_pkts; + }; + ++struct mlxbf_gige_reg_param { ++ u32 mask; ++ u32 shift; ++}; ++ ++struct mlxbf_gige_mdio_gw { ++ u32 gw_address; ++ u32 read_data_address; ++ struct mlxbf_gige_reg_param busy; ++ struct mlxbf_gige_reg_param write_data; ++ struct mlxbf_gige_reg_param read_data; ++ struct mlxbf_gige_reg_param devad; ++ struct mlxbf_gige_reg_param partad; ++ struct mlxbf_gige_reg_param opcode; ++ struct mlxbf_gige_reg_param st1; ++}; ++ + struct mlxbf_gige { + void __iomem *base; + void __iomem *llu_base; +@@ -102,6 +119,8 @@ struct mlxbf_gige { + u8 valid_polarity; + struct napi_struct napi; + struct mlxbf_gige_stats stats; ++ u8 hw_version; ++ struct mlxbf_gige_mdio_gw *mdio_gw; + }; + + /* Rx Work Queue Element definitions */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index 66a50e35f..49695f3e9 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -351,6 +351,8 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + + spin_lock_init(&priv->lock); + ++ priv->hw_version = readq(base + MLXBF_GIGE_VERSION); ++ + /* Attach MDIO device */ + err = mlxbf_gige_mdio_probe(pdev, priv); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +index daa31ddb2..4ee3df30c 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -23,9 +23,75 @@ + + #include "mlxbf_gige.h" + #include "mlxbf_gige_regs.h" ++#include "mlxbf_gige_mdio_bf2.h" ++#include "mlxbf_gige_mdio_bf3.h" + +-#define MLXBF_GIGE_MDIO_GW_OFFSET 0x0 +-#define MLXBF_GIGE_MDIO_CFG_OFFSET 0x4 ++static struct mlxbf_gige_mdio_gw mlxbf_gige_mdio_gw_t[] = { ++ [MLXBF_GIGE_VERSION_BF2] = { ++ .gw_address = MLXBF2_GIGE_MDIO_GW_OFFSET, ++ .read_data_address = MLXBF2_GIGE_MDIO_GW_OFFSET, ++ .busy = { ++ .mask = MLXBF2_GIGE_MDIO_GW_BUSY_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_BUSY_SHIFT, ++ }, ++ .read_data = { ++ .mask = MLXBF2_GIGE_MDIO_GW_AD_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_AD_SHIFT, ++ }, ++ .write_data = { ++ .mask = MLXBF2_GIGE_MDIO_GW_AD_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_AD_SHIFT, ++ }, ++ .devad = { ++ .mask = MLXBF2_GIGE_MDIO_GW_DEVAD_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_DEVAD_SHIFT, ++ }, ++ .partad = { ++ .mask = MLXBF2_GIGE_MDIO_GW_PARTAD_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_PARTAD_SHIFT, ++ }, ++ .opcode = { ++ .mask = MLXBF2_GIGE_MDIO_GW_OPCODE_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_OPCODE_SHIFT, ++ }, ++ .st1 = { ++ .mask = MLXBF2_GIGE_MDIO_GW_ST1_MASK, ++ .shift = MLXBF2_GIGE_MDIO_GW_ST1_SHIFT, ++ }, ++ }, ++ [MLXBF_GIGE_VERSION_BF3] = { ++ .gw_address = MLXBF3_GIGE_MDIO_GW_OFFSET, ++ .read_data_address = MLXBF3_GIGE_MDIO_DATA_READ, ++ .busy = { ++ .mask = MLXBF3_GIGE_MDIO_GW_BUSY_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_BUSY_SHIFT, ++ }, ++ .read_data = { ++ .mask = MLXBF3_GIGE_MDIO_GW_DATA_READ_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_DATA_READ_SHIFT, ++ }, ++ .write_data = { ++ .mask = MLXBF3_GIGE_MDIO_GW_DATA_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_DATA_SHIFT, ++ }, ++ .devad = { ++ .mask = MLXBF3_GIGE_MDIO_GW_DEVAD_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_DEVAD_SHIFT, ++ }, ++ .partad = { ++ .mask = MLXBF3_GIGE_MDIO_GW_PARTAD_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_PARTAD_SHIFT, ++ }, ++ .opcode = { ++ .mask = MLXBF3_GIGE_MDIO_GW_OPCODE_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_OPCODE_SHIFT, ++ }, ++ .st1 = { ++ .mask = MLXBF3_GIGE_MDIO_GW_ST1_MASK, ++ .shift = MLXBF3_GIGE_MDIO_GW_ST1_SHIFT, ++ }, ++ }, ++}; + + #define MLXBF_GIGE_MDIO_FREQ_REFERENCE 156250000ULL + #define MLXBF_GIGE_MDIO_COREPLL_CONST 16384ULL +@@ -47,30 +113,10 @@ + /* Busy bit is set by software and cleared by hardware */ + #define MLXBF_GIGE_MDIO_SET_BUSY 0x1 + +-/* MDIO GW register bits */ +-#define MLXBF_GIGE_MDIO_GW_AD_MASK GENMASK(15, 0) +-#define MLXBF_GIGE_MDIO_GW_DEVAD_MASK GENMASK(20, 16) +-#define MLXBF_GIGE_MDIO_GW_PARTAD_MASK GENMASK(25, 21) +-#define MLXBF_GIGE_MDIO_GW_OPCODE_MASK GENMASK(27, 26) +-#define MLXBF_GIGE_MDIO_GW_ST1_MASK GENMASK(28, 28) +-#define MLXBF_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30) +- +-/* MDIO config register bits */ +-#define MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0) +-#define MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK GENMASK(2, 2) +-#define MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(4, 4) +-#define MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(15, 8) +-#define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16) +-#define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24) +- +-#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \ +- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13)) +- + #define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30 + #define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c ++#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824 ++#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000010 + + static struct resource corepll_params[] = { + [MLXBF_GIGE_VERSION_BF2] = { +@@ -78,6 +124,11 @@ static struct resource corepll_params[] = { + .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1, + .name = "COREPLL_RES" + }, ++ [MLXBF_GIGE_VERSION_BF3] = { ++ .start = MLXBF_GIGE_BF3_COREPLL_ADDR, ++ .end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1, ++ .name = "COREPLL_RES" ++ } + }; + + /* Returns core clock i1clk in Hz */ +@@ -134,19 +185,23 @@ static u8 mdio_period_map(struct mlxbf_gige *priv) + return mdio_period; + } + +-static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add, ++static u32 mlxbf_gige_mdio_create_cmd(struct mlxbf_gige_mdio_gw *mdio_gw, u16 data, int phy_add, + int phy_reg, u32 opcode) + { + u32 gw_reg = 0; + +- gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_AD_MASK, data); +- gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_DEVAD_MASK, phy_reg); +- gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_PARTAD_MASK, phy_add); +- gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_OPCODE_MASK, opcode); +- gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_ST1_MASK, +- MLXBF_GIGE_MDIO_CL22_ST1); +- gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_BUSY_MASK, +- MLXBF_GIGE_MDIO_SET_BUSY); ++ gw_reg |= ((data << mdio_gw->write_data.shift) & ++ mdio_gw->write_data.mask); ++ gw_reg |= ((phy_reg << mdio_gw->devad.shift) & ++ mdio_gw->devad.mask); ++ gw_reg |= ((phy_add << mdio_gw->partad.shift) & ++ mdio_gw->partad.mask); ++ gw_reg |= ((opcode << mdio_gw->opcode.shift) & ++ mdio_gw->opcode.mask); ++ gw_reg |= ((MLXBF_GIGE_MDIO_CL22_ST1 << mdio_gw->st1.shift) & ++ mdio_gw->st1.mask); ++ gw_reg |= ((MLXBF_GIGE_MDIO_SET_BUSY << mdio_gw->busy.shift) & ++ mdio_gw->busy.mask); + + return gw_reg; + } +@@ -162,25 +217,26 @@ static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg) + return -EOPNOTSUPP; + + /* Send mdio read request */ +- cmd = mlxbf_gige_mdio_create_cmd(0, phy_add, phy_reg, MLXBF_GIGE_MDIO_CL22_READ); ++ cmd = mlxbf_gige_mdio_create_cmd(priv->mdio_gw, 0, phy_add, phy_reg, ++ MLXBF_GIGE_MDIO_CL22_READ); + +- writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ writel(cmd, priv->mdio_io + priv->mdio_gw->gw_address); + +- ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET, +- val, !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK), ++ ret = readl_poll_timeout_atomic(priv->mdio_io + priv->mdio_gw->gw_address, ++ val, !(val & priv->mdio_gw->busy.mask), + 5, 1000000); + + if (ret) { +- writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ writel(0, priv->mdio_io + priv->mdio_gw->gw_address); + return ret; + } + +- ret = readl(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ ret = readl(priv->mdio_io + priv->mdio_gw->read_data_address); + /* Only return ad bits of the gw register */ +- ret &= MLXBF_GIGE_MDIO_GW_AD_MASK; ++ ret &= priv->mdio_gw->read_data.mask; + + /* The MDIO lock is set on read. To release it, clear gw register */ +- writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ writel(0, priv->mdio_io + priv->mdio_gw->gw_address); + + return ret; + } +@@ -197,17 +253,17 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add, + return -EOPNOTSUPP; + + /* Send mdio write request */ +- cmd = mlxbf_gige_mdio_create_cmd(val, phy_add, phy_reg, ++ cmd = mlxbf_gige_mdio_create_cmd(priv->mdio_gw, val, phy_add, phy_reg, + MLXBF_GIGE_MDIO_CL22_WRITE); +- writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ writel(cmd, priv->mdio_io + priv->mdio_gw->gw_address); + + /* If the poll timed out, drop the request */ +- ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET, +- temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK), ++ ret = readl_poll_timeout_atomic(priv->mdio_io + priv->mdio_gw->gw_address, ++ temp, !(temp & priv->mdio_gw->busy.mask), + 5, 1000000); + + /* The MDIO lock is set on read. To release it, clear gw register */ +- writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET); ++ writel(0, priv->mdio_io + priv->mdio_gw->gw_address); + + return ret; + } +@@ -219,9 +275,20 @@ static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv) + + mdio_period = mdio_period_map(priv); + +- val = MLXBF_GIGE_MDIO_CFG_VAL; +- val |= FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period); +- writel(val, priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET); ++ if (priv->hw_version == MLXBF_GIGE_VERSION_BF2) { ++ val = MLXBF2_GIGE_MDIO_CFG_VAL; ++ val |= FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period); ++ writel(val, priv->mdio_io + MLXBF2_GIGE_MDIO_CFG_OFFSET); ++ } else { ++ val = FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | ++ FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1); ++ writel(val, priv->mdio_io + MLXBF3_GIGE_MDIO_CFG_REG0); ++ val = FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period); ++ writel(val, priv->mdio_io + MLXBF3_GIGE_MDIO_CFG_REG1); ++ val = FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | ++ FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13); ++ writel(val, priv->mdio_io + MLXBF3_GIGE_MDIO_CFG_REG2); ++ } + } + + int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) +@@ -230,6 +297,9 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + struct resource *res; + int ret; + ++ if (priv->hw_version > MLXBF_GIGE_VERSION_BF3) ++ return -ENODEV; ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MDIO9); + if (!res) + return -ENODEV; +@@ -246,13 +316,15 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + /* For backward compatibility with older ACPI tables, also keep + * CLK resource internal to the driver. + */ +- res = &corepll_params[MLXBF_GIGE_VERSION_BF2]; ++ res = &corepll_params[priv->hw_version]; + } + + priv->clk_io = devm_ioremap(dev, res->start, resource_size(res)); + if (!priv->clk_io) + return -ENOMEM; + ++ priv->mdio_gw = &mlxbf_gige_mdio_gw_t[priv->hw_version]; ++ + mlxbf_gige_mdio_cfg(priv); + + priv->mdiobus = devm_mdiobus_alloc(dev); +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf2.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf2.h +new file mode 100644 +index 000000000..7f1ff0ac7 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf2.h +@@ -0,0 +1,53 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ ++ ++/* MDIO support for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES, ALL RIGHTS RESERVED. ++ * ++ * This software product is a proprietary product of NVIDIA CORPORATION & ++ * AFFILIATES (the "Company") and all right, title, and interest in and to the ++ * software product, including all associated intellectual property rights, are ++ * and shall remain exclusively with the Company. ++ * ++ * This software product is governed by the End User License Agreement ++ * provided with the software product. ++ */ ++ ++#ifndef __MLXBF_GIGE_MDIO_BF2_H__ ++#define __MLXBF_GIGE_MDIO_BF2_H__ ++ ++#include ++ ++#define MLXBF2_GIGE_MDIO_GW_OFFSET 0x0 ++#define MLXBF2_GIGE_MDIO_CFG_OFFSET 0x4 ++ ++/* MDIO GW register bits */ ++#define MLXBF2_GIGE_MDIO_GW_AD_MASK GENMASK(15, 0) ++#define MLXBF2_GIGE_MDIO_GW_DEVAD_MASK GENMASK(20, 16) ++#define MLXBF2_GIGE_MDIO_GW_PARTAD_MASK GENMASK(25, 21) ++#define MLXBF2_GIGE_MDIO_GW_OPCODE_MASK GENMASK(27, 26) ++#define MLXBF2_GIGE_MDIO_GW_ST1_MASK GENMASK(28, 28) ++#define MLXBF2_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30) ++ ++#define MLXBF2_GIGE_MDIO_GW_AD_SHIFT 0 ++#define MLXBF2_GIGE_MDIO_GW_DEVAD_SHIFT 16 ++#define MLXBF2_GIGE_MDIO_GW_PARTAD_SHIFT 21 ++#define MLXBF2_GIGE_MDIO_GW_OPCODE_SHIFT 26 ++#define MLXBF2_GIGE_MDIO_GW_ST1_SHIFT 28 ++#define MLXBF2_GIGE_MDIO_GW_BUSY_SHIFT 30 ++ ++/* MDIO config register bits */ ++#define MLXBF2_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0) ++#define MLXBF2_GIGE_MDIO_CFG_MDIO3_3_MASK GENMASK(2, 2) ++#define MLXBF2_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(4, 4) ++#define MLXBF2_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(15, 8) ++#define MLXBF2_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16) ++#define MLXBF2_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24) ++ ++#define MLXBF2_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \ ++ FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \ ++ FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \ ++ FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \ ++ FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13)) ++ ++#endif /* __MLXBF_GIGE_MDIO_BF2_H__ */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf3.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf3.h +new file mode 100644 +index 000000000..9dd9144b9 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio_bf3.h +@@ -0,0 +1,54 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ ++ ++/* MDIO support for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES, ALL RIGHTS RESERVED. ++ * ++ * This software product is a proprietary product of NVIDIA CORPORATION & ++ * AFFILIATES (the "Company") and all right, title, and interest in and to the ++ * software product, including all associated intellectual property rights, are ++ * and shall remain exclusively with the Company. ++ * ++ * This software product is governed by the End User License Agreement ++ * provided with the software product. ++ */ ++ ++#ifndef __MLXBF_GIGE_MDIO_BF3_H__ ++#define __MLXBF_GIGE_MDIO_BF3_H__ ++ ++#include ++ ++#define MLXBF3_GIGE_MDIO_GW_OFFSET 0x80 ++#define MLXBF3_GIGE_MDIO_DATA_READ 0x8c ++#define MLXBF3_GIGE_MDIO_CFG_REG0 0x100 ++#define MLXBF3_GIGE_MDIO_CFG_REG1 0x104 ++#define MLXBF3_GIGE_MDIO_CFG_REG2 0x108 ++ ++/* MDIO GW register bits */ ++#define MLXBF3_GIGE_MDIO_GW_ST1_MASK GENMASK(1, 1) ++#define MLXBF3_GIGE_MDIO_GW_OPCODE_MASK GENMASK(3, 2) ++#define MLXBF3_GIGE_MDIO_GW_PARTAD_MASK GENMASK(8, 4) ++#define MLXBF3_GIGE_MDIO_GW_DEVAD_MASK GENMASK(13, 9) ++/* For BlueField-3, this field is only used for mdio write */ ++#define MLXBF3_GIGE_MDIO_GW_DATA_MASK GENMASK(29, 14) ++#define MLXBF3_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30) ++ ++#define MLXBF3_GIGE_MDIO_GW_DATA_READ_MASK GENMASK(15, 0) ++ ++#define MLXBF3_GIGE_MDIO_GW_ST1_SHIFT 1 ++#define MLXBF3_GIGE_MDIO_GW_OPCODE_SHIFT 2 ++#define MLXBF3_GIGE_MDIO_GW_PARTAD_SHIFT 4 ++#define MLXBF3_GIGE_MDIO_GW_DEVAD_SHIFT 9 ++#define MLXBF3_GIGE_MDIO_GW_DATA_SHIFT 14 ++#define MLXBF3_GIGE_MDIO_GW_BUSY_SHIFT 30 ++ ++#define MLXBF3_GIGE_MDIO_GW_DATA_READ_SHIFT 0 ++ ++/* MDIO config register bits */ ++#define MLXBF3_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0) ++#define MLXBF3_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(2, 2) ++#define MLXBF3_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(7, 0) ++#define MLXBF3_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(7, 0) ++#define MLXBF3_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(15, 8) ++ ++#endif /* __MLXBF_GIGE_MDIO_BF3_H__ */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +index 7be3a7939..8d52dbef4 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +@@ -10,6 +10,7 @@ + + #define MLXBF_GIGE_VERSION 0x0000 + #define MLXBF_GIGE_VERSION_BF2 0x0 ++#define MLXBF_GIGE_VERSION_BF3 0x1 + #define MLXBF_GIGE_STATUS 0x0010 + #define MLXBF_GIGE_STATUS_READY BIT(0) + #define MLXBF_GIGE_INT_STATUS 0x0028 +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0240-UBUNTU-SAUCE-mlxbf_gige-support-10M-100M-1G-speeds-o.patch b/platform/mellanox/non-upstream-patches/patches/0240-UBUNTU-SAUCE-mlxbf_gige-support-10M-100M-1G-speeds-o.patch new file mode 100644 index 0000000000..a8a1d325df --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0240-UBUNTU-SAUCE-mlxbf_gige-support-10M-100M-1G-speeds-o.patch @@ -0,0 +1,237 @@ +From b9f0d98629a7720d2b6e34aed529f943cf421c04 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Tue, 25 Oct 2022 17:19:27 -0400 +Subject: [PATCH backport 5.10 41/63] UBUNTU: SAUCE: mlxbf_gige: support + 10M/100M/1G speeds on BlueField-3 + +BugLink: https://bugs.launchpad.net/bugs/1995148 + +The BlueField-3 OOB interface supports 10Mbps, 100Mbps, and 1Gbps speeds. +The external PHY is responsible for autonegotiating the speed with the +link partner. Once the autonegotiation is done, the BlueField PLU needs +to be configured accordingly. + +This patch does two things: +1) Initialize the advertised control flow/duplex/speed in the probe + based on the BlueField SoC generation (2 or 3) +2) Adjust the PLU speed config in the PHY interrupt handler + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +--- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 8 ++ + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 109 +++++++++++++++--- + .../mellanox/mlxbf_gige/mlxbf_gige_regs.h | 21 ++++ + 3 files changed, 123 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index 421a0b1b7..a453b9cd9 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + /* The silicon design supports a maximum RX ring size of + * 32K entries. Based on current testing this maximum size +@@ -84,6 +85,12 @@ struct mlxbf_gige_mdio_gw { + struct mlxbf_gige_reg_param st1; + }; + ++struct mlxbf_gige_link_cfg { ++ void (*set_phy_link_mode)(struct phy_device *phydev); ++ void (*adjust_link)(struct net_device *netdev); ++ phy_interface_t phy_mode; ++}; ++ + struct mlxbf_gige { + void __iomem *base; + void __iomem *llu_base; +@@ -121,6 +128,7 @@ struct mlxbf_gige { + struct mlxbf_gige_stats stats; + u8 hw_version; + struct mlxbf_gige_mdio_gw *mdio_gw; ++ int prev_speed; + }; + + /* Rx Work Queue Element definitions */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index 49695f3e9..106b83bd6 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -270,13 +270,103 @@ static const struct net_device_ops mlxbf_gige_netdev_ops = { + .ndo_get_stats64 = mlxbf_gige_get_stats64, + }; + +-static void mlxbf_gige_adjust_link(struct net_device *netdev) ++static void mlxbf_gige_bf2_adjust_link(struct net_device *netdev) + { + struct phy_device *phydev = netdev->phydev; + + phy_print_status(phydev); + } + ++static void mlxbf_gige_bf3_adjust_link(struct net_device *netdev) ++{ ++ struct mlxbf_gige *priv = netdev_priv(netdev); ++ struct phy_device *phydev = netdev->phydev; ++ unsigned long flags; ++ u8 sgmii_mode; ++ u16 ipg_size; ++ u32 val; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ if (phydev->link && phydev->speed != priv->prev_speed) { ++ switch (phydev->speed) { ++ case 1000: ++ ipg_size = MLXBF_GIGE_1G_IPG_SIZE; ++ sgmii_mode = MLXBF_GIGE_1G_SGMII_MODE; ++ break; ++ case 100: ++ ipg_size = MLXBF_GIGE_100M_IPG_SIZE; ++ sgmii_mode = MLXBF_GIGE_100M_SGMII_MODE; ++ break; ++ case 10: ++ ipg_size = MLXBF_GIGE_10M_IPG_SIZE; ++ sgmii_mode = MLXBF_GIGE_10M_SGMII_MODE; ++ break; ++ default: ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return; ++ } ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLU_TX_REG0); ++ val &= ~(MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK | MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK); ++ val |= FIELD_PREP(MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK, ipg_size); ++ val |= FIELD_PREP(MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK, sgmii_mode); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLU_TX_REG0); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLU_RX_REG0); ++ val &= ~MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK, sgmii_mode); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLU_RX_REG0); ++ ++ priv->prev_speed = phydev->speed; ++ } ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ phy_print_status(phydev); ++} ++ ++static void mlxbf_gige_bf2_set_phy_link_mode(struct phy_device *phydev) ++{ ++ /* MAC only supports 1000T full duplex mode */ ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); ++ ++ /* Only symmetric pause with flow control enabled is supported so no ++ * need to negotiate pause. ++ */ ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising); ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising); ++} ++ ++static void mlxbf_gige_bf3_set_phy_link_mode(struct phy_device *phydev) ++{ ++ /* MAC only supports full duplex mode */ ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); ++ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); ++ ++ /* Only symmetric pause with flow control enabled is supported so no ++ * need to negotiate pause. ++ */ ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising); ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising); ++} ++ ++static struct mlxbf_gige_link_cfg mlxbf_gige_link_cfgs[] = { ++ [MLXBF_GIGE_VERSION_BF2] = { ++ .set_phy_link_mode = mlxbf_gige_bf2_set_phy_link_mode, ++ .adjust_link = mlxbf_gige_bf2_adjust_link, ++ .phy_mode = PHY_INTERFACE_MODE_GMII ++ }, ++ [MLXBF_GIGE_VERSION_BF3] = { ++ .set_phy_link_mode = mlxbf_gige_bf3_set_phy_link_mode, ++ .adjust_link = mlxbf_gige_bf3_adjust_link, ++ .phy_mode = PHY_INTERFACE_MODE_SGMII ++ } ++}; ++ + static int mlxbf_gige_probe(struct platform_device *pdev) + { + struct phy_device *phydev; +@@ -395,25 +485,14 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + phydev->irq = phy_irq; + + err = phy_connect_direct(netdev, phydev, +- mlxbf_gige_adjust_link, +- PHY_INTERFACE_MODE_GMII); ++ mlxbf_gige_link_cfgs[priv->hw_version].adjust_link, ++ mlxbf_gige_link_cfgs[priv->hw_version].phy_mode); + if (err) { + dev_err(&pdev->dev, "Could not attach to PHY\n"); + goto out; + } + +- /* MAC only supports 1000T full duplex mode */ +- phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); +- phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT); +- phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); +- phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); +- phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); +- +- /* Only symmetric pause with flow control enabled is supported so no +- * need to negotiate pause. +- */ +- linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising); +- linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising); ++ mlxbf_gige_link_cfgs[priv->hw_version].set_phy_link_mode(phydev); + + /* Display information about attached PHY device */ + phy_attached_info(phydev); +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +index 8d52dbef4..cd0973229 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +@@ -8,6 +8,8 @@ + #ifndef __MLXBF_GIGE_REGS_H__ + #define __MLXBF_GIGE_REGS_H__ + ++#include ++ + #define MLXBF_GIGE_VERSION 0x0000 + #define MLXBF_GIGE_VERSION_BF2 0x0 + #define MLXBF_GIGE_VERSION_BF3 0x1 +@@ -78,4 +80,23 @@ + */ + #define MLXBF_GIGE_MMIO_REG_SZ (MLXBF_GIGE_MAC_CFG + 8) + ++#define MLXBF_GIGE_PLU_TX_REG0 0x80 ++#define MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK GENMASK(11, 0) ++#define MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK GENMASK(15, 14) ++ ++#define MLXBF_GIGE_PLU_RX_REG0 0x10 ++#define MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK GENMASK(25, 24) ++ ++#define MLXBF_GIGE_1G_SGMII_MODE 0x0 ++#define MLXBF_GIGE_10M_SGMII_MODE 0x1 ++#define MLXBF_GIGE_100M_SGMII_MODE 0x2 ++ ++/* ipg_size default value for 1G is fixed by HW to 11 + End = 12. ++ * So for 100M it is 12 * 10 - 1 = 119 ++ * For 10M, it is 12 * 100 - 1 = 1199 ++ */ ++#define MLXBF_GIGE_1G_IPG_SIZE 11 ++#define MLXBF_GIGE_100M_IPG_SIZE 119 ++#define MLXBF_GIGE_10M_IPG_SIZE 1199 ++ + #endif /* !defined(__MLXBF_GIGE_REGS_H__) */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0241-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-Serdes-confi.patch b/platform/mellanox/non-upstream-patches/patches/0241-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-Serdes-confi.patch new file mode 100644 index 0000000000..bdeef431bc --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0241-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-Serdes-confi.patch @@ -0,0 +1,1865 @@ +From e2017fcee49f8d2b36a59d5d6076259f4e4feeac Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Tue, 25 Oct 2022 18:24:01 -0400 +Subject: [PATCH backport 5.10 42/63] UBUNTU: SAUCE: mlxbf_gige: add + BlueField-3 Serdes configuration + +BugLink: https://bugs.launchpad.net/bugs/1995148 + +The BlueField-3 out-of-band Ethernet interface requires +SerDes configuration. There are two aspects to this: + +Configuration of PLL: + 1) Initialize UPHY registers to values dependent on p1clk clock + 2) Load PLL best known values via the gateway register + 3) Set the fuses to tune up the SerDes voltage + 4) Lock the PLL + 5) Get the lanes out of functional reset. + 6) Configure the UPHY microcontroller via gateway reads/writes + +Configuration of lanes: + 1) Configure and open TX lanes + 2) Configure and open RX lanes + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +--- + .../net/ethernet/mellanox/mlxbf_gige/Makefile | 3 +- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 4 +- + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 76 +- + .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 36 - + .../mellanox/mlxbf_gige/mlxbf_gige_uphy.c | 1191 +++++++++++++++++ + .../mellanox/mlxbf_gige/mlxbf_gige_uphy.h | 398 ++++++ + 6 files changed, 1645 insertions(+), 63 deletions(-) + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c + create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +index a97c2bef8..524af17ca 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +@@ -7,4 +7,5 @@ mlxbf_gige-y := mlxbf_gige_ethtool.o \ + mlxbf_gige_main.o \ + mlxbf_gige_mdio.o \ + mlxbf_gige_rx.o \ +- mlxbf_gige_tx.o ++ mlxbf_gige_tx.o \ ++ mlxbf_gige_uphy.o +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index a453b9cd9..e9bd09ee0 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -100,6 +100,7 @@ struct mlxbf_gige { + struct platform_device *pdev; + void __iomem *mdio_io; + void __iomem *clk_io; ++ void __iomem *fuse_gw_io; + struct mii_bus *mdiobus; + spinlock_t lock; /* for packet processing indices */ + u16 rx_q_entries; +@@ -166,7 +167,8 @@ enum mlxbf_gige_res { + MLXBF_GIGE_RES_GPIO0, + MLXBF_GIGE_RES_LLU, + MLXBF_GIGE_RES_PLU, +- MLXBF_GIGE_RES_CLK ++ MLXBF_GIGE_RES_CLK, ++ MLXBF_GIGE_RES_FUSE_GW + }; + + /* Version of register data returned by mlxbf_gige_get_regs() */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index 106b83bd6..f97e49670 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -18,13 +18,25 @@ + + #include "mlxbf_gige.h" + #include "mlxbf_gige_regs.h" ++#include "mlxbf_gige_uphy.h" + +-#define DRV_VERSION 1.27 ++#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30 ++#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c ++#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824 ++#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000020 + +-/* This setting defines the version of the ACPI table +- * content that is compatible with this driver version. +- */ +-#define MLXBF_GIGE_ACPI_TABLE_VERSION 2 ++static struct resource corepll_params[] = { ++ [MLXBF_GIGE_VERSION_BF2] = { ++ .start = MLXBF_GIGE_BF2_COREPLL_ADDR, ++ .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1, ++ .name = "COREPLL_RES" ++ }, ++ [MLXBF_GIGE_VERSION_BF3] = { ++ .start = MLXBF_GIGE_BF3_COREPLL_ADDR, ++ .end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1, ++ .name = "COREPLL_RES" ++ } ++}; + + /* Allocate SKB whose payload pointer aligns with the Bluefield + * hardware DMA limitation, i.e. DMA operation can't cross +@@ -371,31 +383,20 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + { + struct phy_device *phydev; + struct net_device *netdev; ++ struct resource *clk_res; + struct resource *mac_res; + struct resource *llu_res; + struct resource *plu_res; + struct mlxbf_gige *priv; + void __iomem *llu_base; + void __iomem *plu_base; ++ void __iomem *clk_io; + void __iomem *base; + int addr, phy_irq; +- u32 version; ++ u64 soc_version; + u64 control; + int err; + +- version = 0; +- err = device_property_read_u32(&pdev->dev, "version", &version); +- if (err) { +- dev_err(&pdev->dev, "ACPI table version not found\n"); +- return -EINVAL; +- } +- +- if (version != MLXBF_GIGE_ACPI_TABLE_VERSION) { +- dev_err(&pdev->dev, "ACPI table version mismatch: expected %d found %d\n", +- MLXBF_GIGE_ACPI_TABLE_VERSION, version); +- return -EINVAL; +- } +- + mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC); + if (!mac_res) + return -ENXIO; +@@ -404,6 +405,25 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + if (IS_ERR(base)) + return PTR_ERR(base); + ++ soc_version = readq(base + MLXBF_GIGE_VERSION); ++ if (soc_version > MLXBF_GIGE_VERSION_BF3) ++ return -ENODEV; ++ ++ /* clk resource shared with other drivers so cannot use ++ * devm_platform_ioremap_resource ++ */ ++ clk_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK); ++ if (!clk_res) { ++ /* For backward compatibility with older ACPI tables, also keep ++ * CLK resource internal to the driver. ++ */ ++ clk_res = &corepll_params[soc_version]; ++ } ++ ++ clk_io = devm_ioremap(&pdev->dev, clk_res->start, resource_size(clk_res)); ++ if (!clk_io) ++ return -ENOMEM; ++ + llu_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_LLU); + if (!llu_res) + return -ENXIO; +@@ -441,17 +461,23 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + + spin_lock_init(&priv->lock); + +- priv->hw_version = readq(base + MLXBF_GIGE_VERSION); ++ priv->clk_io = clk_io; ++ priv->base = base; ++ priv->llu_base = llu_base; ++ priv->plu_base = plu_base; ++ priv->hw_version = soc_version; ++ ++ if (priv->hw_version == MLXBF_GIGE_VERSION_BF3) { ++ err = mlxbf_gige_config_uphy(priv); ++ if (err) ++ return err; ++ } + + /* Attach MDIO device */ + err = mlxbf_gige_mdio_probe(pdev, priv); + if (err) + return err; + +- priv->base = base; +- priv->llu_base = llu_base; +- priv->plu_base = plu_base; +- + priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ; + priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ; + +@@ -553,4 +579,4 @@ MODULE_DESCRIPTION("Mellanox BlueField SoC Gigabit Ethernet Driver"); + MODULE_AUTHOR("David Thompson "); + MODULE_AUTHOR("Asmaa Mnebhi "); + MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_VERSION(__stringify(DRV_VERSION)); ++ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +index 4ee3df30c..21acdcea3 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +@@ -113,24 +113,6 @@ static struct mlxbf_gige_mdio_gw mlxbf_gige_mdio_gw_t[] = { + /* Busy bit is set by software and cleared by hardware */ + #define MLXBF_GIGE_MDIO_SET_BUSY 0x1 + +-#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30 +-#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c +-#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824 +-#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000010 +- +-static struct resource corepll_params[] = { +- [MLXBF_GIGE_VERSION_BF2] = { +- .start = MLXBF_GIGE_BF2_COREPLL_ADDR, +- .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1, +- .name = "COREPLL_RES" +- }, +- [MLXBF_GIGE_VERSION_BF3] = { +- .start = MLXBF_GIGE_BF3_COREPLL_ADDR, +- .end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1, +- .name = "COREPLL_RES" +- } +-}; +- + /* Returns core clock i1clk in Hz */ + static u64 calculate_i1clk(struct mlxbf_gige *priv) + { +@@ -297,9 +279,6 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + struct resource *res; + int ret; + +- if (priv->hw_version > MLXBF_GIGE_VERSION_BF3) +- return -ENODEV; +- + res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MDIO9); + if (!res) + return -ENODEV; +@@ -308,21 +287,6 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) + if (IS_ERR(priv->mdio_io)) + return PTR_ERR(priv->mdio_io); + +- /* clk resource shared with other drivers so cannot use +- * devm_platform_ioremap_resource +- */ +- res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK); +- if (!res) { +- /* For backward compatibility with older ACPI tables, also keep +- * CLK resource internal to the driver. +- */ +- res = &corepll_params[priv->hw_version]; +- } +- +- priv->clk_io = devm_ioremap(dev, res->start, resource_size(res)); +- if (!priv->clk_io) +- return -ENOMEM; +- + priv->mdio_gw = &mlxbf_gige_mdio_gw_t[priv->hw_version]; + + mlxbf_gige_mdio_cfg(priv); +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c +new file mode 100644 +index 000000000..9d64eb886 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c +@@ -0,0 +1,1191 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause ++ ++/* UPHY support for Nvidia Gigabit Ethernet driver ++ * ++ * Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++#include ++#include ++ ++#include "mlxbf_gige.h" ++#include "mlxbf_gige_uphy.h" ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_clm_init[] = { ++ {.addr = 0x001, .wdata = 0x0105}, ++ {.addr = 0x008, .wdata = 0x0001}, ++ {.addr = 0x00B, .wdata = 0x8420}, ++ {.addr = 0x00E, .wdata = 0x0110}, ++ {.addr = 0x010, .wdata = 0x3010}, ++ {.addr = 0x027, .wdata = 0x0104}, ++ {.addr = 0x02F, .wdata = 0x09EA}, ++ {.addr = 0x055, .wdata = 0x0008}, ++ {.addr = 0x058, .wdata = 0x0088}, ++ {.addr = 0x072, .wdata = 0x3222}, ++ {.addr = 0x073, .wdata = 0x7654}, ++ {.addr = 0x074, .wdata = 0xBA98}, ++ {.addr = 0x075, .wdata = 0xDDDC} ++}; ++ ++#define MLXBF_GIGE_UPHY_CLM_INIT_NUM_ENTRIES \ ++ (sizeof(mlxbf_gige_clm_init) / sizeof(struct mlxbf_gige_uphy_cfg_reg)) ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_imem_init[] = { ++ {.addr = 0x39C, .wdata = 0x0000}, ++ {.addr = 0x39D, .wdata = 0x0095}, ++ {.addr = 0x3BF, .wdata = 0x9027}, ++ {.addr = 0x39E, .wdata = 0xA8F6}, ++ {.addr = 0x39F, .wdata = 0xAA10}, ++ {.addr = 0x3A0, .wdata = 0xA8D4}, ++ {.addr = 0x3A1, .wdata = 0xA7AE}, ++ {.addr = 0x3A2, .wdata = 0xA7CC}, ++ {.addr = 0x3A3, .wdata = 0x9BE4}, ++ {.addr = 0x3A4, .wdata = 0xB2D2}, ++ {.addr = 0x3A5, .wdata = 0xB1F2}, ++ {.addr = 0x3AE, .wdata = 0x7C38}, ++ {.addr = 0x3AF, .wdata = 0x7C4A}, ++ {.addr = 0x3B0, .wdata = 0x7C25}, ++ {.addr = 0x3B1, .wdata = 0x7C74}, ++ {.addr = 0x3B2, .wdata = 0x3C00}, ++ {.addr = 0x3B3, .wdata = 0x3C11}, ++ {.addr = 0x3B4, .wdata = 0x3C5D}, ++ {.addr = 0x3B5, .wdata = 0x3C5D} ++}; ++ ++#define MLXBF_GIGE_UPHY_DLM_IMEM_INIT_NUM_ENTRIES \ ++ (sizeof(mlxbf_gige_dlm_imem_init) / sizeof(struct mlxbf_gige_uphy_cfg_reg)) ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_seq_imem_wr_en_init = { ++ .addr = 0x39A, .wdata = 0x0001 ++}; ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_seq_imem_wr_dis_init = { ++ .addr = 0x39A, .wdata = 0x0000 ++}; ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_imem_data[] = { ++ { /* .iaddr = 0x0000 */ .wdata = 0x02DF}, ++ { /* .iaddr = 0x0001 */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x0002 */ .wdata = 0xD508}, ++ { /* .iaddr = 0x0003 */ .wdata = 0x022F}, ++ { /* .iaddr = 0x0004 */ .wdata = 0xC401}, ++ { /* .iaddr = 0x0005 */ .wdata = 0xD341}, ++ { /* .iaddr = 0x0006 */ .wdata = 0xC402}, ++ { /* .iaddr = 0x0007 */ .wdata = 0xD342}, ++ { /* .iaddr = 0x0008 */ .wdata = 0xC403}, ++ { /* .iaddr = 0x0009 */ .wdata = 0xD343}, ++ { /* .iaddr = 0x000A */ .wdata = 0xC404}, ++ { /* .iaddr = 0x000B */ .wdata = 0xD344}, ++ { /* .iaddr = 0x000C */ .wdata = 0xC417}, ++ { /* .iaddr = 0x000D */ .wdata = 0xD355}, ++ { /* .iaddr = 0x000E */ .wdata = 0xC418}, ++ { /* .iaddr = 0x000F */ .wdata = 0xD356}, ++ { /* .iaddr = 0x0010 */ .wdata = 0xF021}, ++ { /* .iaddr = 0x0011 */ .wdata = 0xF003}, ++ { /* .iaddr = 0x0012 */ .wdata = 0xE224}, ++ { /* .iaddr = 0x0013 */ .wdata = 0x0DA9}, ++ { /* .iaddr = 0x0014 */ .wdata = 0xF003}, ++ { /* .iaddr = 0x0015 */ .wdata = 0xE21C}, ++ { /* .iaddr = 0x0016 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0017 */ .wdata = 0x0D87}, ++ { /* .iaddr = 0x0018 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0019 */ .wdata = 0xE806}, ++ { /* .iaddr = 0x001A */ .wdata = 0xC3C5}, ++ { /* .iaddr = 0x001B */ .wdata = 0xD306}, ++ { /* .iaddr = 0x001C */ .wdata = 0xEEDF}, ++ { /* .iaddr = 0x001D */ .wdata = 0xE806}, ++ { /* .iaddr = 0x001E */ .wdata = 0xC3C6}, ++ { /* .iaddr = 0x001F */ .wdata = 0xD306}, ++ { /* .iaddr = 0x0020 */ .wdata = 0xF002}, ++ { /* .iaddr = 0x0021 */ .wdata = 0xC3C8}, ++ { /* .iaddr = 0x0022 */ .wdata = 0x409A}, ++ { /* .iaddr = 0x0023 */ .wdata = 0xF021}, ++ { /* .iaddr = 0x0024 */ .wdata = 0xEEE0}, ++ { /* .iaddr = 0x0025 */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x0026 */ .wdata = 0xD70D}, ++ { /* .iaddr = 0x0027 */ .wdata = 0xC305}, ++ { /* .iaddr = 0x0028 */ .wdata = 0xD328}, ++ { /* .iaddr = 0x0029 */ .wdata = 0xC300}, ++ { /* .iaddr = 0x002A */ .wdata = 0xD314}, ++ { /* .iaddr = 0x002B */ .wdata = 0xC301}, ++ { /* .iaddr = 0x002C */ .wdata = 0xD318}, ++ { /* .iaddr = 0x002D */ .wdata = 0xC303}, ++ { /* .iaddr = 0x002E */ .wdata = 0xD320}, ++ { /* .iaddr = 0x002F */ .wdata = 0xC302}, ++ { /* .iaddr = 0x0030 */ .wdata = 0xD31C}, ++ { /* .iaddr = 0x0031 */ .wdata = 0xC304}, ++ { /* .iaddr = 0x0032 */ .wdata = 0xD324}, ++ { /* .iaddr = 0x0033 */ .wdata = 0xC358}, ++ { /* .iaddr = 0x0034 */ .wdata = 0xD330}, ++ { /* .iaddr = 0x0035 */ .wdata = 0xC307}, ++ { /* .iaddr = 0x0036 */ .wdata = 0xD115}, ++ { /* .iaddr = 0x0037 */ .wdata = 0xF021}, ++ { /* .iaddr = 0x0038 */ .wdata = 0xD70D}, ++ { /* .iaddr = 0x0039 */ .wdata = 0xC305}, ++ { /* .iaddr = 0x003A */ .wdata = 0xD328}, ++ { /* .iaddr = 0x003B */ .wdata = 0xC300}, ++ { /* .iaddr = 0x003C */ .wdata = 0xD314}, ++ { /* .iaddr = 0x003D */ .wdata = 0xC301}, ++ { /* .iaddr = 0x003E */ .wdata = 0xD318}, ++ { /* .iaddr = 0x003F */ .wdata = 0xC303}, ++ { /* .iaddr = 0x0040 */ .wdata = 0xD320}, ++ { /* .iaddr = 0x0041 */ .wdata = 0xC302}, ++ { /* .iaddr = 0x0042 */ .wdata = 0xD31C}, ++ { /* .iaddr = 0x0043 */ .wdata = 0xC304}, ++ { /* .iaddr = 0x0044 */ .wdata = 0xD324}, ++ { /* .iaddr = 0x0045 */ .wdata = 0xC358}, ++ { /* .iaddr = 0x0046 */ .wdata = 0xD330}, ++ { /* .iaddr = 0x0047 */ .wdata = 0xC307}, ++ { /* .iaddr = 0x0048 */ .wdata = 0xD115}, ++ { /* .iaddr = 0x0049 */ .wdata = 0xF021}, ++ { /* .iaddr = 0x004A */ .wdata = 0xC70D}, ++ { /* .iaddr = 0x004B */ .wdata = 0xD70F}, ++ { /* .iaddr = 0x004C */ .wdata = 0xC328}, ++ { /* .iaddr = 0x004D */ .wdata = 0xD305}, ++ { /* .iaddr = 0x004E */ .wdata = 0xC314}, ++ { /* .iaddr = 0x004F */ .wdata = 0xD300}, ++ { /* .iaddr = 0x0050 */ .wdata = 0xC318}, ++ { /* .iaddr = 0x0051 */ .wdata = 0xD301}, ++ { /* .iaddr = 0x0052 */ .wdata = 0xC320}, ++ { /* .iaddr = 0x0053 */ .wdata = 0xD303}, ++ { /* .iaddr = 0x0054 */ .wdata = 0xC31C}, ++ { /* .iaddr = 0x0055 */ .wdata = 0xD302}, ++ { /* .iaddr = 0x0056 */ .wdata = 0xC324}, ++ { /* .iaddr = 0x0057 */ .wdata = 0xD304}, ++ { /* .iaddr = 0x0058 */ .wdata = 0xC330}, ++ { /* .iaddr = 0x0059 */ .wdata = 0xD358}, ++ { /* .iaddr = 0x005A */ .wdata = 0xC115}, ++ { /* .iaddr = 0x005B */ .wdata = 0xD307}, ++ { /* .iaddr = 0x005C */ .wdata = 0xF021}, ++ { /* .iaddr = 0x005D */ .wdata = 0x0249}, ++ { /* .iaddr = 0x005E */ .wdata = 0x0362}, ++ { /* .iaddr = 0x005F */ .wdata = 0x023D}, ++ { /* .iaddr = 0x0060 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0061 */ .wdata = 0x0369}, ++ { /* .iaddr = 0x0062 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0063 */ .wdata = 0x0CEA}, ++ { /* .iaddr = 0x0064 */ .wdata = 0xEEC2}, ++ { /* .iaddr = 0x0065 */ .wdata = 0xD701}, ++ { /* .iaddr = 0x0066 */ .wdata = 0x02C8}, ++ { /* .iaddr = 0x0067 */ .wdata = 0xC3C3}, ++ { /* .iaddr = 0x0068 */ .wdata = 0xD306}, ++ { /* .iaddr = 0x0069 */ .wdata = 0xC3C8}, ++ { /* .iaddr = 0x006A */ .wdata = 0x009A}, ++ { /* .iaddr = 0x006B */ .wdata = 0xC3D1}, ++ { /* .iaddr = 0x006C */ .wdata = 0xD309}, ++ { /* .iaddr = 0x006D */ .wdata = 0x0C46}, ++ { /* .iaddr = 0x006E */ .wdata = 0x0DE7}, ++ { /* .iaddr = 0x006F */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x0070 */ .wdata = 0xC3D9}, ++ { /* .iaddr = 0x0071 */ .wdata = 0x0DDE}, ++ { /* .iaddr = 0x0072 */ .wdata = 0x02D7}, ++ { /* .iaddr = 0x0073 */ .wdata = 0xF021}, ++ { /* .iaddr = 0x0074 */ .wdata = 0x1441}, ++ { /* .iaddr = 0x0075 */ .wdata = 0xF003}, ++ { /* .iaddr = 0x0076 */ .wdata = 0xC03F}, ++ { /* .iaddr = 0x0077 */ .wdata = 0xF704}, ++ { /* .iaddr = 0x0078 */ .wdata = 0xF009}, ++ { /* .iaddr = 0x0079 */ .wdata = 0xE21A}, ++ { /* .iaddr = 0x007A */ .wdata = 0xF002}, ++ { /* .iaddr = 0x007B */ .wdata = 0x0C52}, ++ { /* .iaddr = 0x007C */ .wdata = 0xE206}, ++ { /* .iaddr = 0x007D */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x007E */ .wdata = 0xD01A}, ++ { /* .iaddr = 0x007F */ .wdata = 0x3C5D}, ++ { /* .iaddr = 0x0080 */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x0081 */ .wdata = 0xD01A}, ++ { /* .iaddr = 0x0082 */ .wdata = 0x0E12}, ++ { /* .iaddr = 0x0083 */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x0084 */ .wdata = 0x13E1}, ++ { /* .iaddr = 0x0085 */ .wdata = 0x1441}, ++ { /* .iaddr = 0x0086 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0087 */ .wdata = 0xD70E}, ++ { /* .iaddr = 0x0088 */ .wdata = 0xD70F}, ++ { /* .iaddr = 0x0089 */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x008A */ .wdata = 0xD70E}, ++ { /* .iaddr = 0x008B */ .wdata = 0xC458}, ++ { /* .iaddr = 0x008C */ .wdata = 0x13BE}, ++ { /* .iaddr = 0x008D */ .wdata = 0xEEC0}, ++ { /* .iaddr = 0x008E */ .wdata = 0xF29B}, ++ { /* .iaddr = 0x008F */ .wdata = 0xE20A}, ++ { /* .iaddr = 0x0090 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0091 */ .wdata = 0xD01D}, ++ { /* .iaddr = 0x0092 */ .wdata = 0xEEC1}, ++ { /* .iaddr = 0x0093 */ .wdata = 0xD3FD}, ++ { /* .iaddr = 0x0094 */ .wdata = 0xF021} ++}; ++ ++#define MLXBF_GIGE_UPHY_DLM_IMEM_DATA_NUM_ENTRIES \ ++ (sizeof(mlxbf_gige_dlm_imem_data) / sizeof(struct mlxbf_gige_uphy_cfg_reg)) ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_seq_imem_csum_en = { ++ .addr = 0x39A, .wdata = 0x0004 ++}; ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_seq_imem_csum_dis = { ++ .addr = 0x39A, .wdata = 0x0000 ++}; ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_seq_imem_bmap_clr[] = { ++ {.addr = 0x39E, .wdata = 0x0000}, ++ {.addr = 0x39F, .wdata = 0x0000}, ++ {.addr = 0x3A0, .wdata = 0x0000}, ++ {.addr = 0x3A1, .wdata = 0x0000}, ++ {.addr = 0x3A2, .wdata = 0x0000}, ++ {.addr = 0x3A3, .wdata = 0x0000}, ++ {.addr = 0x3A4, .wdata = 0x0000}, ++ {.addr = 0x3A5, .wdata = 0x0000}, ++ {.addr = 0x3A6, .wdata = 0x0000}, ++ {.addr = 0x3A7, .wdata = 0x0000}, ++ {.addr = 0x3A8, .wdata = 0x0000}, ++ {.addr = 0x3A9, .wdata = 0x0000}, ++ {.addr = 0x3AA, .wdata = 0x0000}, ++ {.addr = 0x3AB, .wdata = 0x0000}, ++ {.addr = 0x3AC, .wdata = 0x0000}, ++ {.addr = 0x3AD, .wdata = 0x0000}, ++ {.addr = 0x3AE, .wdata = 0x0000}, ++ {.addr = 0x3AF, .wdata = 0x0000}, ++ {.addr = 0x3B0, .wdata = 0x0000}, ++ {.addr = 0x3B1, .wdata = 0x0000}, ++ {.addr = 0x3B2, .wdata = 0x0000}, ++ {.addr = 0x3B3, .wdata = 0x0000}, ++ {.addr = 0x3B4, .wdata = 0x0000}, ++ {.addr = 0x3B5, .wdata = 0x0000}, ++ {.addr = 0x3B6, .wdata = 0x0000}, ++ {.addr = 0x3B7, .wdata = 0x0000}, ++ {.addr = 0x3B8, .wdata = 0x0000}, ++ {.addr = 0x3B9, .wdata = 0x0000}, ++ {.addr = 0x3BA, .wdata = 0x0000}, ++ {.addr = 0x3BB, .wdata = 0x0000}, ++ {.addr = 0x3BC, .wdata = 0x0000}, ++ {.addr = 0x3BD, .wdata = 0x0000} ++}; ++ ++#define MLXBF_GIGE_DLM_SEQ_IMEM_BMAP_CLR_NUM_ENTRIES \ ++ (sizeof(mlxbf_gige_dlm_seq_imem_bmap_clr) / sizeof(struct mlxbf_gige_uphy_cfg_reg)) ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_tx_init[] = { ++ {.addr = 0x002, .wdata = 0x5125}, ++ {.addr = 0x01C, .wdata = 0x0018}, ++ {.addr = 0x01E, .wdata = 0x0E00}, ++ {.addr = 0x01F, .wdata = 0xC200}, ++ {.addr = 0x023, .wdata = 0x0277}, ++ {.addr = 0x024, .wdata = 0x026B}, ++ {.addr = 0x053, .wdata = 0x0700}, ++ {.addr = 0x059, .wdata = 0x1011}, ++ {.addr = 0x060, .wdata = 0x0000}, ++ {.addr = 0x062, .wdata = 0x0135}, ++ {.addr = 0x063, .wdata = 0x0443}, ++ {.addr = 0x064, .wdata = 0x0000}, ++ {.addr = 0x066, .wdata = 0x0061}, ++ {.addr = 0x067, .wdata = 0x0042}, ++ {.addr = 0x06A, .wdata = 0x1212}, ++ {.addr = 0x06B, .wdata = 0x1515}, ++ {.addr = 0x06C, .wdata = 0x011A}, ++ {.addr = 0x06D, .wdata = 0x0132}, ++ {.addr = 0x06E, .wdata = 0x0632}, ++ {.addr = 0x06F, .wdata = 0x0643}, ++ {.addr = 0x070, .wdata = 0x0233}, ++ {.addr = 0x071, .wdata = 0x0433}, ++ {.addr = 0x07E, .wdata = 0x6A08}, ++ {.addr = 0x08D, .wdata = 0x2101}, ++ {.addr = 0x093, .wdata = 0x0015}, ++ {.addr = 0x096, .wdata = 0x7555}, ++ {.addr = 0x0A9, .wdata = 0xE754}, ++ {.addr = 0x0AA, .wdata = 0x7ED1}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000} ++}; ++ ++#define MLXBF_GIGE_DLM_TX_NUM_ENTRIES \ ++ (sizeof(mlxbf_gige_dlm_tx_init) / sizeof(struct mlxbf_gige_uphy_cfg_reg)) ++ ++static const struct mlxbf_gige_uphy_cfg_reg ++mlxbf_gige_dlm_rx_init[] = { ++ {.addr = 0x003, .wdata = 0x5125}, ++ {.addr = 0x01D, .wdata = 0x0004}, ++ {.addr = 0x028, .wdata = 0x1000}, ++ {.addr = 0x029, .wdata = 0x1001}, ++ {.addr = 0x02E, .wdata = 0x0004}, ++ {.addr = 0x053, .wdata = 0x0700}, ++ {.addr = 0x057, .wdata = 0x5044}, ++ {.addr = 0x05B, .wdata = 0x1011}, ++ {.addr = 0x0D2, .wdata = 0x0002}, ++ {.addr = 0x0D9, .wdata = 0x0000}, ++ {.addr = 0x0DA, .wdata = 0x0000}, ++ {.addr = 0x0DB, .wdata = 0x0000}, ++ {.addr = 0x0E2, .wdata = 0x0000}, ++ {.addr = 0x0E7, .wdata = 0xBB10}, ++ {.addr = 0x0E8, .wdata = 0xBB10}, ++ {.addr = 0x0EC, .wdata = 0x0111}, ++ {.addr = 0x0ED, .wdata = 0x1C00}, ++ {.addr = 0x0F5, .wdata = 0x0000}, ++ {.addr = 0x102, .wdata = 0x0CA6}, ++ {.addr = 0x107, .wdata = 0x0020}, ++ {.addr = 0x10C, .wdata = 0x1E31}, ++ {.addr = 0x10D, .wdata = 0x1D29}, ++ {.addr = 0x111, .wdata = 0x00E7}, ++ {.addr = 0x112, .wdata = 0x5202}, ++ {.addr = 0x117, .wdata = 0x0493}, ++ {.addr = 0x11B, .wdata = 0x0148}, ++ {.addr = 0x120, .wdata = 0x23DE}, ++ {.addr = 0x121, .wdata = 0x2294}, ++ {.addr = 0x125, .wdata = 0x03FF}, ++ {.addr = 0x126, .wdata = 0x25F0}, ++ {.addr = 0x12B, .wdata = 0xC633}, ++ {.addr = 0x136, .wdata = 0x0F6A}, ++ {.addr = 0x143, .wdata = 0x0000}, ++ {.addr = 0x148, .wdata = 0x0001}, ++ {.addr = 0x14E, .wdata = 0x0000}, ++ {.addr = 0x155, .wdata = 0x2003}, ++ {.addr = 0x15C, .wdata = 0x099B}, ++ {.addr = 0x161, .wdata = 0x0088}, ++ {.addr = 0x16B, .wdata = 0x0433}, ++ {.addr = 0x172, .wdata = 0x099B}, ++ {.addr = 0x17C, .wdata = 0x045D}, ++ {.addr = 0x17D, .wdata = 0x006A}, ++ {.addr = 0x181, .wdata = 0x0000}, ++ {.addr = 0x189, .wdata = 0x1590}, ++ {.addr = 0x18E, .wdata = 0x0080}, ++ {.addr = 0x18F, .wdata = 0x90EC}, ++ {.addr = 0x191, .wdata = 0x79F8}, ++ {.addr = 0x194, .wdata = 0x000A}, ++ {.addr = 0x195, .wdata = 0x000A}, ++ {.addr = 0x1EB, .wdata = 0x0133}, ++ {.addr = 0x1F0, .wdata = 0x0030}, ++ {.addr = 0x1F1, .wdata = 0x0030}, ++ {.addr = 0x1F5, .wdata = 0x3737}, ++ {.addr = 0x1F6, .wdata = 0x3737}, ++ {.addr = 0x1FA, .wdata = 0x2C00}, ++ {.addr = 0x1FF, .wdata = 0x0516}, ++ {.addr = 0x200, .wdata = 0x0516}, ++ {.addr = 0x204, .wdata = 0x3010}, ++ {.addr = 0x209, .wdata = 0x0429}, ++ {.addr = 0x20E, .wdata = 0x0010}, ++ {.addr = 0x213, .wdata = 0x005A}, ++ {.addr = 0x214, .wdata = 0x0000}, ++ {.addr = 0x216, .wdata = 0x0000}, ++ {.addr = 0x218, .wdata = 0x0000}, ++ {.addr = 0x225, .wdata = 0x0000}, ++ {.addr = 0x22A, .wdata = 0x0000}, ++ {.addr = 0x22B, .wdata = 0x0000}, ++ {.addr = 0x231, .wdata = 0x0000}, ++ {.addr = 0x232, .wdata = 0x0000}, ++ {.addr = 0x233, .wdata = 0x0000}, ++ {.addr = 0x245, .wdata = 0x0300}, ++ {.addr = 0x24A, .wdata = 0x0000}, ++ {.addr = 0x24F, .wdata = 0xFFF3}, ++ {.addr = 0x254, .wdata = 0x0000}, ++ {.addr = 0x259, .wdata = 0x0000}, ++ {.addr = 0x25E, .wdata = 0x0000}, ++ {.addr = 0x265, .wdata = 0x0009}, ++ {.addr = 0x267, .wdata = 0x0174}, ++ {.addr = 0x271, .wdata = 0x01F0}, ++ {.addr = 0x273, .wdata = 0x0170}, ++ {.addr = 0x275, .wdata = 0x7828}, ++ {.addr = 0x279, .wdata = 0x3E3A}, ++ {.addr = 0x27D, .wdata = 0x8468}, ++ {.addr = 0x283, .wdata = 0x000C}, ++ {.addr = 0x285, .wdata = 0x7777}, ++ {.addr = 0x288, .wdata = 0x5503}, ++ {.addr = 0x28C, .wdata = 0x0030}, ++ {.addr = 0x28E, .wdata = 0xBBBB}, ++ {.addr = 0x290, .wdata = 0xBBBB}, ++ {.addr = 0x293, .wdata = 0x0021}, ++ {.addr = 0x2FA, .wdata = 0x3B40}, ++ {.addr = 0x2FB, .wdata = 0x7777}, ++ {.addr = 0x30A, .wdata = 0x8022}, ++ {.addr = 0x319, .wdata = 0x205E}, ++ {.addr = 0x31B, .wdata = 0x0000}, ++ {.addr = 0x31D, .wdata = 0x6004}, ++ {.addr = 0x320, .wdata = 0x3014}, ++ {.addr = 0x322, .wdata = 0x6004}, ++ {.addr = 0x326, .wdata = 0x6004}, ++ {.addr = 0x32A, .wdata = 0x5000}, ++ {.addr = 0x32E, .wdata = 0x5000}, ++ {.addr = 0x332, .wdata = 0x6004}, ++ {.addr = 0x336, .wdata = 0x6063}, ++ {.addr = 0x389, .wdata = 0x0310}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000}, ++ {.addr = 0x3FF, .wdata = 0x0000} ++}; ++ ++#define MLXBF_GIGE_DLM_RX_NUM_ENTRIES \ ++ (sizeof(mlxbf_gige_dlm_rx_init) / sizeof(struct mlxbf_gige_uphy_cfg_reg)) ++ ++/* returns plu clock p1clk in Hz */ ++static u64 mlxbf_gige_calculate_p1clk(struct mlxbf_gige *priv) ++{ ++ u8 core_od, core_r; ++ u64 freq_output; ++ u32 reg1, reg2; ++ u32 core_f; ++ ++ reg1 = readl(priv->clk_io + MLXBF_GIGE_P1CLK_REG1); ++ reg2 = readl(priv->clk_io + MLXBF_GIGE_P1CLK_REG2); ++ ++ core_f = (reg1 & MLXBF_GIGE_P1_CORE_F_MASK) >> ++ MLXBF_GIGE_P1_CORE_F_SHIFT; ++ core_r = (reg1 & MLXBF_GIGE_P1_CORE_R_MASK) >> ++ MLXBF_GIGE_P1_CORE_R_SHIFT; ++ core_od = (reg2 & MLXBF_GIGE_P1_CORE_OD_MASK) >> ++ MLXBF_GIGE_P1_CORE_OD_SHIFT; ++ ++ /* Compute PLL output frequency as follow: ++ * ++ * CORE_F / 16384 ++ * freq_output = freq_reference * ---------------------------- ++ * (CORE_R + 1) * (CORE_OD + 1) ++ */ ++ freq_output = div_u64(MLXBF_GIGE_P1_FREQ_REFERENCE * core_f, ++ MLXBF_GIGE_P1_CLK_CONST); ++ freq_output = div_u64(freq_output, (core_r + 1) * (core_od + 1)); ++ ++ return freq_output; ++} ++ ++static void mlxbf_gige_ugl_static_config(struct mlxbf_gige *priv) ++{ ++ u32 val, p1clk_mhz; ++ u32 const_factor; ++ u64 p1clk; ++ ++ /* p1clk is the PLU clock in Hz */ ++ p1clk = mlxbf_gige_calculate_p1clk(priv); ++ ++ /* get p1clk in MHz */ ++ p1clk_mhz = div_u64(p1clk, 1000000); ++ ++ /* Multiply the p1clk clock by 12 according to HW requirements */ ++ const_factor = p1clk_mhz * MLXBF_GIGE_P1CLK_MULT_FACTOR; ++ ++ /* ugl_cr_bridge_desc */ ++ val = readl(priv->plu_base + MLXBF_GIGE_UGL_CR_BRIDGE_DESC); ++ val &= ~MLXBF_GIGE_UGL_CR_BRIDGE_ALL_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK, ++ MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_VAL(const_factor)); ++ val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK, ++ MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_VAL(const_factor)); ++ val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK, ++ MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_UGL_CR_BRIDGE_DESC); ++ ++ /* pll1x_fsm_counters */ ++ val = MLXBF_GIGE_PLL1X_FSM_DEFAULT_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_DEFAULT_CYCLES); ++ ++ val = MLXBF_GIGE_PLL1X_FSM_SLEEP_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_SLEEP_CYCLES); ++ ++ val = MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_CYCLES); ++ ++ val = MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_CYCLES); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES); ++ val &= ~MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK, ++ MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES); ++ ++ /* tx_fsm_counters */ ++ val = MLXBF_GIGE_TX_FSM_DEFAULT_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_DEFAULT_CYCLES); ++ ++ val = MLXBF_GIGE_TX_FSM_SLEEP_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_SLEEP_CYCLES); ++ ++ val = MLXBF_GIGE_TX_FSM_POWERUP_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_POWERUP_CYCLES); ++ ++ val = MLXBF_GIGE_TX_FSM_CAL_FLOW_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_FLOW_CYCLES); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES); ++ val &= ~MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK, ++ MLXBF_GIGE_TX_FSM_CAL_ABORT_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES); ++ ++ /* rx_fsm_counters */ ++ val = MLXBF_GIGE_RX_FSM_DEFAULT_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_DEFAULT_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_SLEEP_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_SLEEP_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_POWERUP_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_POWERUP_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_TERM_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_TERM_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_CAL_FLOW_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CAL_FLOW_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_CAL_ABORT_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CAL_ABORT_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_EQ_FLOW_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EQ_FLOW_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_EQ_ABORT_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EQ_ABORT_CYCLES); ++ ++ val = MLXBF_GIGE_RX_FSM_EOM_FLOW_VAL(const_factor); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EOM_FLOW_CYCLES); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES); ++ val &= ~MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK, ++ MLXBF_GIGE_RX_FSM_CDR_LOCK_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES); ++ ++ /* periodic_flows_timer_max_value */ ++ val = readl(priv->plu_base + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX); ++ val &= ~MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK, ++ MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX); ++ ++ /* plltop.center.iddq_cycles */ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLL_IDDQ_CYCLES); ++ val &= ~MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK, ++ MLXBF_GIGE_PLL_IDDQ_CYCLES_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL_IDDQ_CYCLES); ++ ++ /* lanetop.center.iddq_cycles */ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_IDDQ_CYCLES); ++ val &= ~MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK; ++ val |= FIELD_PREP(MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK, ++ MLXBF_GIGE_LANE_IDDQ_CYCLES_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_IDDQ_CYCLES); ++ ++ /* lanetop.center.power_governor0 */ ++ val = FIELD_PREP(MLXBF_GIGE_LANE_PWR_GOV0_RISE_MASK, ++ MLXBF_GIGE_LANE_PWR_GOV0_RISE_VAL(const_factor)); ++ val |= FIELD_PREP(MLXBF_GIGE_LANE_PWR_GOV0_FALL_MASK, ++ MLXBF_GIGE_LANE_PWR_GOV0_FALL_VAL(const_factor)); ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_PWR_GOV0); ++} ++ ++static int mlxbf_gige_uphy_gw_write(struct mlxbf_gige *priv, u16 addr, ++ u16 data, bool is_pll) ++{ ++ u32 cmd, val; ++ int ret; ++ ++ cmd = MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, data, 0, is_pll); ++ ++ /* Send PLL or lane GW write request */ ++ writel(cmd, priv->plu_base + MLXBF_GIGE_UPHY_GW(is_pll)); ++ ++ /* If the poll times out, drop the request */ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_UPHY_GW(is_pll), ++ val, ++ !(val & MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll)), ++ 5, 1000000); ++ if (ret) ++ dev_dbg(priv->dev, "Failed to send GW write request\n"); ++ ++ return ret; ++} ++ ++static int mlxbf_gige_uphy_gw_read(struct mlxbf_gige *priv, u16 addr, ++ bool is_pll) ++{ ++ u32 cmd, val; ++ int ret; ++ ++ cmd = MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, 0, 1, is_pll); ++ ++ /* Send PLL or lane GW read request */ ++ writel(cmd, priv->plu_base + MLXBF_GIGE_UPHY_GW(is_pll)); ++ ++ /* If the poll times out, drop the request */ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_UPHY_GW(is_pll), ++ val, ++ !(val & MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll)), ++ 5, 1000000); ++ if (ret) { ++ dev_dbg(priv->dev, "Failed to send GW read request\n"); ++ return ret; ++ } ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_UPHY_GW_DESC0(is_pll)); ++ val &= MLXBF_GIGE_UPHY_GW_DESC0_DATA_MASK(is_pll); ++ ++ return val; ++} ++ ++static int mlxbf_gige_load_uphy_clm_init_pkg(struct mlxbf_gige *priv) ++{ ++ int ret = 0; ++ int i; ++ ++ for (i = 0; i < MLXBF_GIGE_UPHY_CLM_INIT_NUM_ENTRIES; i++) { ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_clm_init[i].addr, ++ mlxbf_gige_clm_init[i].wdata, ++ true); ++ if (ret) { ++ dev_dbg(priv->dev, "Failed to load clm init pkg\n"); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ ++static int mlxbf_gige_load_clm_production_fuses(struct mlxbf_gige *priv) ++{ ++ u8 bg_trim_room; ++ u8 cvb_trim_room; ++ u8 speedo_room; ++ int ret; ++ u32 val; ++ ++ val = readl(priv->fuse_gw_io); ++ bg_trim_room = (val & MLXBF_GIGE_YU_BG_TRIM_ROOM_MASK) >> ++ MLXBF_GIGE_YU_BG_TRIM_ROOM_SHIFT; ++ cvb_trim_room = (val & MLXBF_GIGE_YU_CVB_TRIM_ROOM_MASK) >> ++ MLXBF_GIGE_YU_CVB_TRIM_ROOM_SHIFT; ++ speedo_room = (val & MLXBF_GIGE_YU_SPEEDO_ROOM_MASK) >> ++ MLXBF_GIGE_YU_SPEEDO_ROOM_SHIFT; ++ ++ val = ((bg_trim_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) << ++ MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_VLD_SHIFT); ++ val |= ((cvb_trim_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) << ++ MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_VLD_SHIFT); ++ val |= ((speedo_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) << ++ MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_VLD_SHIFT); ++ val |= ((bg_trim_room & MLXBF_GIGE_YU_FUSE_MASK) << ++ MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_SHIFT); ++ val |= ((cvb_trim_room & MLXBF_GIGE_YU_FUSE_MASK) << ++ MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_SHIFT); ++ val |= ((speedo_room & MLXBF_GIGE_YU_FUSE_MASK) << ++ MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_SHIFT); ++ ++ ret = mlxbf_gige_uphy_gw_write(priv, MLXBF_GIGE_MGMT_BGAP_FUSE_CTRL_ADDR, val, true); ++ if (ret) ++ dev_dbg(priv->dev, "Failed to load clm production fuses\n"); ++ ++ return ret; ++} ++ ++static int mlxbf_gige_init_pll(struct mlxbf_gige *priv) ++{ ++ int ret; ++ ++ ret = mlxbf_gige_load_uphy_clm_init_pkg(priv); ++ if (ret) ++ return ret; ++ ++ ret = mlxbf_gige_load_clm_production_fuses(priv); ++ ++ return ret; ++} ++ ++static int mlxbf_gige_lock_pll(struct mlxbf_gige *priv) ++{ ++ int ret; ++ u32 val; ++ ++ /* plltop.center.uphy_pll_rst_reg_ */ ++ val = readl(priv->plu_base + MLXBF_GIGE_UPHY_PLL_RST_REG); ++ val |= MLXBF_GIGE_UPHY_PLL_RST_REG_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_UPHY_PLL_RST_REG); ++ ++ /* cause_or.clrcause.bulk */ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK); ++ val |= MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK); ++ ++ writel(0, priv->plu_base + MLXBF_GIGE_PLL_CAL); ++ ++ /* Stop polling when fsm state is UGL_PLL1X_FSM_STATE_SLEEP */ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_PLL_FSM_CTRL, ++ val, (val == MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SLEEP), ++ 5, 1000000); ++ if (ret) { ++ dev_dbg(priv->dev, "Polling timeout on fsm state sleep\n"); ++ return ret; ++ } ++ ++ udelay(MLXBF_GIGE_PLL_STAB_TIME); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); ++ val |= MLXBF_GIGE_PLL_SLEEP_FW_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); ++ ++ udelay(MLXBF_GIGE_PLL_STAB_TIME); ++ writel(MLXBF_GIGE_PLL_RCAL_MASK, priv->plu_base + MLXBF_GIGE_PLL_RCAL); ++ ++ /* Stop polling when fsm state is UGL_PLL1X_FSM_STATE_IDLE */ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_PLL_FSM_CTRL, ++ val, (val == MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDLE), ++ 5, 1000000); ++ if (ret) { ++ dev_dbg(priv->dev, "Polling timeout on fsm state idle\n"); ++ return ret; ++ } ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); ++ val &= ~MLXBF_GIGE_PLL_SLEEP_FW_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); ++ ++ writel(MLXBF_GIGE_PLL_CAL_MASK, priv->plu_base + MLXBF_GIGE_PLL_CAL); ++ ++ /* Stop polling when cal_valid is different from 0 */ ++ ret = readl_poll_timeout_atomic(priv->plu_base + MLXBF_GIGE_PLL_CAL_VLD, ++ val, !!(val & MLXBF_GIGE_PLL_CAL_VLD_MASK), ++ 5, 1000000); ++ if (ret) { ++ dev_dbg(priv->dev, "Polling timeout on cal_valid\n"); ++ return ret; ++ } ++ ++ /* pll_enable */ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLL_ENABLE); ++ val |= MLXBF_GIGE_PLL_ENABLE_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLL_ENABLE); ++ ++ return ret; ++} ++ ++static void mlxbf_gige_get_lane_out_of_rst(struct mlxbf_gige *priv) ++{ ++ u32 val; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RST_REG); ++ val |= MLXBF_GIGE_LANE_RST_REG_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RST_REG); ++} ++ ++static int mlxbf_gige_load_imem(struct mlxbf_gige *priv) ++{ ++ u16 csum_status; ++ int ret = 0; ++ int i; ++ ++ for (i = 0; i < MLXBF_GIGE_UPHY_DLM_IMEM_INIT_NUM_ENTRIES; i++) { ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_imem_init[i].addr, ++ mlxbf_gige_dlm_imem_init[i].wdata, ++ false); ++ if (ret) ++ return ret; ++ } ++ ++ /* Resets the internal counter for MLXBF_GIGE_DLM_IMEM_DATA_ADDR to base address */ ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_seq_imem_wr_en_init.addr, ++ mlxbf_gige_dlm_seq_imem_wr_en_init.wdata, ++ false); ++ if (ret) ++ return ret; ++ ++ /* HW increments the address MLXBF_GIGE_DLM_IMEM_DATA_ADDR internally. */ ++ for (i = 0; i < MLXBF_GIGE_UPHY_DLM_IMEM_DATA_NUM_ENTRIES; i++) { ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ MLXBF_GIGE_LANE_IMEM_DATA_ADDR, ++ mlxbf_gige_dlm_imem_data[i].wdata, ++ false); ++ if (ret) ++ return ret; ++ } ++ ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_seq_imem_wr_dis_init.addr, ++ mlxbf_gige_dlm_seq_imem_wr_dis_init.wdata, ++ false); ++ if (ret) ++ return ret; ++ ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_seq_imem_csum_en.addr, ++ mlxbf_gige_dlm_seq_imem_csum_en.wdata, ++ false); ++ if (ret) ++ return ret; ++ ++ udelay(MLXBF_GIGE_PLL_DLM_IMEM_CSUM_TIMEOUT); ++ ++ ret = mlxbf_gige_uphy_gw_read(priv, MLXBF_GIGE_LANE_CSUM_STS_ADDR, false); ++ if (ret < 0) ++ return ret; ++ ++ csum_status = ((ret & MLXBF_GIGE_IMEM_CSUM_STATUS_MASK) >> ++ MLXBF_GIGE_IMEM_CSUM_STATUS_SHIFT); ++ ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_seq_imem_csum_dis.addr, ++ mlxbf_gige_dlm_seq_imem_csum_dis.wdata, ++ false); ++ if (ret) ++ return ret; ++ ++ if (csum_status != MLXBF_GIGE_IMEM_CSUM_RUN_AND_VALID) { ++ dev_err(priv->dev, "%s: invalid checksum\n", __func__); ++ ++ /* recovery flow */ ++ for (i = 0; i < MLXBF_GIGE_DLM_SEQ_IMEM_BMAP_CLR_NUM_ENTRIES; i++) { ++ mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_seq_imem_bmap_clr[i].addr, ++ mlxbf_gige_dlm_seq_imem_bmap_clr[i].wdata, ++ false); ++ } ++ ++ return MLXBF_GIGE_INVALID_IMEM_CSUM; ++ } ++ ++ return ret; ++} ++ ++static int mlxbf_gige_plu_tx_power_ctrl(struct mlxbf_gige *priv, bool is_pwr_on) ++{ ++ int ret = 0; ++ u32 val; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); ++ val &= ~MLXBF_GIGE_LANE_TX_SLEEP_VAL_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); ++ ++ if (is_pwr_on) { ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ val &= ~MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ val |= MLXBF_GIGE_PLU_TX_POWERUP_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ } else { ++ val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ val &= ~MLXBF_GIGE_PLU_TX_POWERUP_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ val |= MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_LANE_TX_FSM_CTRL, val, ++ ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) == MLXBF_GIGE_TX_FSM_IDDQ), ++ 5, 1000000); ++ if (ret) ++ dev_dbg(priv->dev, "Polling timeout on tx fsm iddq state\n"); ++ } ++ ++ return ret; ++} ++ ++static int mlxbf_gige_dlm_tx_init_pkg(struct mlxbf_gige *priv) ++{ ++ int ret = 0; ++ int i; ++ ++ for (i = 0; i < MLXBF_GIGE_DLM_TX_NUM_ENTRIES; i++) { ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_tx_init[i].addr, ++ mlxbf_gige_dlm_tx_init[i].wdata, ++ false); ++ if (ret) { ++ dev_dbg(priv->dev, "Failed to load dlm tx init pkg\n"); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ ++static int mlxbf_gige_tx_lane_open(struct mlxbf_gige *priv) ++{ ++ u32 val; ++ int ret; ++ ++ /* Prepare the TX lane before opening it */ ++ ++ ret = mlxbf_gige_plu_tx_power_ctrl(priv, false); ++ if (ret) ++ return ret; ++ ++ /* Calibration of TX elastic buffer */ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); ++ val &= ~MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK; ++ val |= MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_VAL; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ val |= MLXBF_GIGE_LANE_TX_DATA_EN_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ ++ writel(MLXBF_GIGE_LANE_TX_CAL_MASK, priv->plu_base + MLXBF_GIGE_LANE_TX_CAL); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ val &= ~MLXBF_GIGE_LANE_TX_RATE_ID_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); ++ val &= ~MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); ++ ++ /* Loading the DLM tx init package should be done before lane power on */ ++ ret = mlxbf_gige_dlm_tx_init_pkg(priv); ++ if (ret) ++ return ret; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); ++ val &= ~MLXBF_GIGE_LANE_TX_BITS_SWAP_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); ++ ++ ret = mlxbf_gige_plu_tx_power_ctrl(priv, true); ++ if (ret) ++ return ret; ++ ++ /* After preparing the TX lane, open it for data transmission */ ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); ++ val &= ~MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); ++ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_LANE_TX_FSM_CTRL, val, ++ ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) == MLXBF_GIGE_TX_DATA_EN), ++ 5, 1000000); ++ if (ret) { ++ dev_dbg(priv->dev, "Polling timeout on fsm tx data enable state\n"); ++ return ret; ++ } ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ val |= MLXBF_GIGE_LANE_TX_PERIODIC_CAL_EN_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); ++ ++ return ret; ++} ++ ++static int mlxbf_gige_dlm_rx_init_pkg(struct mlxbf_gige *priv) ++{ ++ int ret = 0; ++ int i; ++ ++ for (i = 0; i < MLXBF_GIGE_DLM_RX_NUM_ENTRIES; i++) { ++ ret = mlxbf_gige_uphy_gw_write(priv, ++ mlxbf_gige_dlm_rx_init[i].addr, ++ mlxbf_gige_dlm_rx_init[i].wdata, ++ false); ++ if (ret) { ++ dev_dbg(priv->dev, "Failed to load dlm rx init pkg\n"); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ ++static int mlxbf_gige_plu_rx_power_ctrl(struct mlxbf_gige *priv, bool is_pwr_on) ++{ ++ int ret = 0; ++ u32 val; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ val &= ~MLXBF_GIGE_LANE_RX_SLEEP_VAL_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ ++ if (is_pwr_on) { ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ val &= ~MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ val |= MLXBF_GIGE_PLU_RX_POWERUP_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ } else { ++ /* Enable HW watchdogs. */ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); ++ val |= MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK; ++ val |= MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ val &= ~MLXBF_GIGE_PLU_RX_POWERUP_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ val |= MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_LANE_RX_FSM_CTRL, val, ++ ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) == MLXBF_GIGE_RX_FSM_IDDQ), ++ 5, 1000000); ++ if (ret) { ++ dev_dbg(priv->dev, "Polling timeout on rx fsm iddq state\n"); ++ return ret; ++ } ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); ++ val &= ~MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK; ++ val &= ~MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); ++ } ++ ++ return ret; ++} ++ ++static int mlxbf_gige_rx_lane_open(struct mlxbf_gige *priv) ++{ ++ u32 val; ++ int ret; ++ ++ ret = mlxbf_gige_plu_rx_power_ctrl(priv, false); ++ if (ret) ++ return ret; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ val &= ~MLXBF_GIGE_LANE_RX_RATE_ID_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); ++ val &= ~MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP_RDY_CHICKEN_MASK; ++ val &= ~MLXBF_GIGE_LANE_RX_DATA_SPLIT_LSB_VLD_CHICKEN_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ val &= ~MLXBF_GIGE_LANE_RX_RATE_ID0_SPEED_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); ++ ++ ret = mlxbf_gige_dlm_rx_init_pkg(priv); ++ if (ret) ++ return ret; ++ ++ writel(MLXBF_GIGE_LANE_RX_CAL_MASK, priv->plu_base + MLXBF_GIGE_LANE_RX_CAL); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); ++ val &= ~MLXBF_GIGE_LANE_RX_CDR_RESET_REG_MASK; ++ val |= MLXBF_GIGE_LANE_RX_CDR_EN_MASK; ++ val |= MLXBF_GIGE_LANE_RX_DATA_EN_MASK; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_TRAIN); ++ val &= ~MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK; ++ val |= MLXBF_GIGE_LANE_RX_EQ_TRAIN_VAL; ++ writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_TRAIN); ++ ++ ret = mlxbf_gige_plu_rx_power_ctrl(priv, true); ++ if (ret) ++ return ret; ++ ++ ret = readl_poll_timeout_atomic(priv->plu_base + ++ MLXBF_GIGE_LANE_RX_FSM_CTRL, val, ++ ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) == MLXBF_GIGE_RX_FSM_ACTIVE), ++ 5, 1000000); ++ if (ret) ++ dev_dbg(priv->dev, "Polling timeout on rx fsm active state\n"); ++ ++ return ret; ++} ++ ++static bool mlxbf_gige_is_uphy_ready(struct mlxbf_gige *priv) ++{ ++ u32 val; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_FSM_CTRL); ++ if ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) != MLXBF_GIGE_TX_DATA_EN) ++ return false; ++ ++ val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_FSM_CTRL); ++ if ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) != MLXBF_GIGE_RX_FSM_ACTIVE) ++ return false; ++ ++ return true; ++} ++ ++int mlxbf_gige_config_uphy(struct mlxbf_gige *priv) ++{ ++ struct platform_device *pdev = priv->pdev; ++ struct device *dev = &pdev->dev; ++ int ret = 0; ++ ++ priv->fuse_gw_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_FUSE_GW); ++ if (IS_ERR(priv->fuse_gw_io)) ++ return PTR_ERR(priv->fuse_gw_io); ++ ++ if (mlxbf_gige_is_uphy_ready(priv)) ++ return 0; ++ ++ mlxbf_gige_ugl_static_config(priv); ++ ret = mlxbf_gige_init_pll(priv); ++ if (ret) { ++ dev_err(dev, "%s: Failed to initialize PLL\n", __func__); ++ return ret; ++ } ++ ++ ret = mlxbf_gige_lock_pll(priv); ++ if (ret) { ++ dev_err(dev, "%s: Failed to lock PLL\n", __func__); ++ return ret; ++ } ++ ++ /* Due to hardware design issue, we need to get the lanes out of reset ++ * before configuring the imem. ++ */ ++ mlxbf_gige_get_lane_out_of_rst(priv); ++ ret = mlxbf_gige_load_imem(priv); ++ if (ret) { ++ dev_err(dev, "%s: Failed to load imem\n", __func__); ++ return ret; ++ } ++ ++ ret = mlxbf_gige_tx_lane_open(priv); ++ if (ret) { ++ dev_err(dev, "%s: Failed to open tx lane\n", __func__); ++ return ret; ++ } ++ ++ ret = mlxbf_gige_rx_lane_open(priv); ++ if (ret) ++ dev_err(dev, "%s: Failed to open rx lane\n", __func__); ++ ++ return ret; ++} +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h +new file mode 100644 +index 000000000..a32be2407 +--- /dev/null ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h +@@ -0,0 +1,398 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ ++ ++/* UPHY support for Mellanox Gigabit Ethernet driver ++ * ++ * Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#ifndef __MLXBF_GIGE_UPHY_H__ ++#define __MLXBF_GIGE_UPHY_H__ ++ ++#include ++ ++/* Some registers' values depend on the p1clk clock. The following ++ * formula applies: ++ * ((time_in_ns*const_factor)/MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ */ ++#define MLXBF_GIGE_TIME_FACTOR_TO_USEC 10000 ++ ++/* All addresses represent the offset from the base PLU address */ ++ ++#define MLXBF_GIGE_PLU_POWERUP 0x488 ++#define MLXBF_GIGE_PLU_TX_POWERUP_MASK GENMASK(28, 28) ++#define MLXBF_GIGE_PLU_RX_POWERUP_MASK GENMASK(27, 27) ++ ++#define MLXBF_GIGE_LANE_CFG_FLAT0_BASE 0x23000 ++#define MLXBF_GIGE_AE_SYS_IMEM_RAM_DATA_CTRL_WDATA 0x23ef8 ++#define MLXBF_GIGE_AE_SYS_IMEM_RAM_STAT_IMEM_CSUM_STS 0x23f00 ++#define MLXBF_GIGE_IMEM_CSUM_STATUS_MASK GENMASK(6, 5) ++#define MLXBF_GIGE_IMEM_CSUM_STATUS_SHIFT 5 ++ ++#define MLXBF_GIGE_PLL_CFG_FLAT0_BASE 0x25000 ++#define MLXBF_GIGE_PLL_CFG_FLAT0_MGMT_BGAP_FUSE_CTRL 0x251d8 ++#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_SHIFT 0 ++#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_SHIFT 4 ++#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_SHIFT 8 ++#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_VLD_SHIFT 12 ++#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_VLD_SHIFT 13 ++#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_VLD_SHIFT 14 ++ ++#define MLXBF_GIGE_LANE_TX_FSM_CTRL 0x26000 ++#define MLXBF_GIGE_LANE_TX_FSM_PS_MASK GENMASK(3, 0) ++ ++#define MLXBF_GIGE_LANE_TX_BITS_SWAP 0x2600c ++#define MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK GENMASK(20, 16) ++#define MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_VAL \ ++ FIELD_PREP(MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK, 0x3) ++#define MLXBF_GIGE_LANE_TX_BITS_SWAP_MASK GENMASK(0, 0) ++ ++#define MLXBF_GIGE_LANE_TX_DATA_EN 0x26010 ++#define MLXBF_GIGE_LANE_TX_RATE_ID_MASK GENMASK(30, 28) ++#define MLXBF_GIGE_LANE_TX_DATA_EN_MASK GENMASK(23, 23) ++#define MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK GENMASK(21, 21) ++#define MLXBF_GIGE_LANE_TX_PERIODIC_CAL_EN_MASK GENMASK(17, 17) ++ ++#define MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED 0x26014 ++#define MLXBF_GIGE_LANE_TX_SLEEP_VAL_MASK GENMASK(9, 8) ++#define MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED_MASK GENMASK(2, 0) ++ ++#define MLXBF_GIGE_LANE_TX_CAL 0x26018 ++#define MLXBF_GIGE_LANE_TX_CAL_MASK GENMASK(0, 0) ++ ++#define MLXBF_GIGE_LANE_RX_FSM_CTRL 0x26040 ++#define MLXBF_GIGE_LANE_RX_FSM_PS_MASK GENMASK(3, 0) ++ ++#define MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN 0x26054 ++#define MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK GENMASK(31, 31) ++#define MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK GENMASK(30, 30) ++ ++#define MLXBF_GIGE_LANE_RX_RATE_ID 0x26058 ++#define MLXBF_GIGE_LANE_RX_RATE_ID0_SPEED_MASK GENMASK(18, 16) ++#define MLXBF_GIGE_LANE_RX_RATE_ID_MASK GENMASK(14, 12) ++#define MLXBF_GIGE_LANE_RX_SLEEP_VAL_MASK GENMASK(7, 6) ++#define MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK GENMASK(4, 4) ++ ++#define MLXBF_GIGE_LANE_RX_CAL 0x2605c ++#define MLXBF_GIGE_LANE_RX_CAL_MASK GENMASK(0, 0) ++ ++#define MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP 0x26060 ++#define MLXBF_GIGE_LANE_RX_DATA_SPLIT_LSB_VLD_CHICKEN_MASK GENMASK(5, 5) ++#define MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP_RDY_CHICKEN_MASK GENMASK(4, 4) ++#define MLXBF_GIGE_LANE_RX_CDR_RESET_REG_MASK GENMASK(3, 3) ++#define MLXBF_GIGE_LANE_RX_CDR_EN_MASK GENMASK(2, 2) ++#define MLXBF_GIGE_LANE_RX_DATA_EN_MASK GENMASK(1, 1) ++ ++#define MLXBF_GIGE_LANE_RX_EQ_TRAIN 0x26064 ++#define MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK GENMASK(2, 0) ++#define MLXBF_GIGE_LANE_RX_EQ_TRAIN_VAL \ ++ FIELD_PREP(MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK, 0x3) ++ ++#define MLXBF_GIGE_LANE_GW 0x26100 ++#define MLXBF_GIGE_LANE_GW_ADDR_MASK GENMASK(10, 1) ++#define MLXBF_GIGE_LANE_GW_RW_MASK GENMASK(11, 11) ++#define MLXBF_GIGE_LANE_GW_DATA_MASK GENMASK(27, 12) ++#define MLXBF_GIGE_LANE_GW_DATA_EN_MASK GENMASK(28, 28) ++#define MLXBF_GIGE_LANE_GW_BUSY_MASK GENMASK(30, 30) ++#define MLXBF_GIGE_LANE_GW_ADDR_SHIFT 1 ++#define MLXBF_GIGE_LANE_GW_DESC0 0x2610c ++#define MLXBF_GIGE_LANE_GW_DESC0_DATA_MASK GENMASK(15, 0) ++ ++#define MLXBF_GIGE_TX_FSM_DEFAULT_CYCLES 0x26600 ++#define MLXBF_GIGE_TX_FSM_DEFAULT_VAL(const_factor) \ ++ ((200 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_TX_FSM_SLEEP_CYCLES 0x26604 ++#define MLXBF_GIGE_TX_FSM_SLEEP_VAL(const_factor) \ ++ ((1000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_TX_FSM_POWERUP_CYCLES 0x26608 ++#define MLXBF_GIGE_TX_FSM_POWERUP_VAL(const_factor) \ ++ ((10000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_TX_FSM_CAL_FLOW_CYCLES 0x2660c ++#define MLXBF_GIGE_TX_FSM_CAL_FLOW_VAL(const_factor) \ ++ ((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES 0x26610 ++#define MLXBF_GIGE_TX_FSM_CAL_ABORT_VAL(const_factor) \ ++ ((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK GENMASK(18, 0) ++ ++#define MLXBF_GIGE_RX_FSM_DEFAULT_CYCLES 0x26614 ++#define MLXBF_GIGE_RX_FSM_DEFAULT_VAL(const_factor) \ ++ ((200 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_SLEEP_CYCLES 0x26618 ++#define MLXBF_GIGE_RX_FSM_SLEEP_VAL(const_factor) \ ++ ((1000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_POWERUP_CYCLES 0x2661c ++#define MLXBF_GIGE_RX_FSM_POWERUP_VAL(const_factor) \ ++ ((10000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_TERM_CYCLES 0x26620 ++#define MLXBF_GIGE_RX_FSM_TERM_VAL(const_factor) \ ++ ((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_CAL_FLOW_CYCLES 0x26624 ++#define MLXBF_GIGE_RX_FSM_CAL_FLOW_VAL(const_factor) \ ++ ((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_CAL_ABORT_CYCLES 0x26628 ++#define MLXBF_GIGE_RX_FSM_CAL_ABORT_VAL(const_factor) \ ++ ((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_EQ_FLOW_CYCLES 0x2662c ++#define MLXBF_GIGE_RX_FSM_EQ_FLOW_VAL(const_factor) \ ++ ((48000000 / MLXBF_GIGE_TIME_FACTOR_TO_USEC) * (const_factor)) ++ ++#define MLXBF_GIGE_RX_FSM_EQ_ABORT_CYCLES 0x26630 ++#define MLXBF_GIGE_RX_FSM_EQ_ABORT_VAL(const_factor) \ ++ ((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_RX_FSM_EOM_FLOW_CYCLES 0x26634 ++#define MLXBF_GIGE_RX_FSM_EOM_FLOW_VAL(const_factor) \ ++ ((4000000 / MLXBF_GIGE_TIME_FACTOR_TO_USEC) * (const_factor)) ++ ++#define MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES 0x26638 ++#define MLXBF_GIGE_RX_FSM_CDR_LOCK_VAL(const_factor) \ ++ ((30000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK GENMASK(20, 0) ++ ++#define MLXBF_GIGE_LANE_PWR_GOV0 0x26650 ++#define MLXBF_GIGE_LANE_PWR_GOV0_FALL_VAL(const_factor) \ ++ ((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_LANE_PWR_GOV0_FALL_MASK GENMASK(31, 16) ++#define MLXBF_GIGE_LANE_PWR_GOV0_RISE_VAL(const_factor) \ ++ ((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_LANE_PWR_GOV0_RISE_MASK GENMASK(15, 0) ++ ++#define MLXBF_GIGE_LANE_IDDQ_CYCLES 0x26660 ++#define MLXBF_GIGE_LANE_IDDQ_CYCLES_VAL(const_factor) \ ++ ((2000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK GENMASK(28, 16) ++ ++#define MLXBF_GIGE_LANE_RST_REG 0x26660 ++#define MLXBF_GIGE_LANE_RST_REG_MASK GENMASK(7, 6) ++ ++#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX 0x26668 ++#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_VAL(const_factor) \ ++ ((2500000 / (MLXBF_GIGE_TIME_FACTOR_TO_USEC * 8)) * (const_factor)) ++#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK GENMASK(22, 0) ++ ++#define MLXBF_GIGE_PLL_FSM_CTRL 0x26800 ++#define MLXBF_GIGE_PLL_FSM_PS_MASK GENMASK(3, 0) ++ ++#define MLXBF_GIGE_PLL_GW 0x26810 ++#define MLXBF_GIGE_PLL_GW_ADDR_MASK GENMASK(10, 1) ++#define MLXBF_GIGE_PLL_GW_RW_MASK GENMASK(11, 11) ++#define MLXBF_GIGE_PLL_GW_DATA_MASK GENMASK(27, 12) ++#define MLXBF_GIGE_PLL_GW_DATA_EN_MASK GENMASK(28, 28) ++#define MLXBF_GIGE_PLL_GW_BUSY_MASK GENMASK(30, 30) ++#define MLXBF_GIGE_PLL_GW_ADDR_SHIFT 1 ++#define MLXBF_GIGE_PLL_GW_DESC0 0x2681c ++#define MLXBF_GIGE_PLL_GW_DESC0_DATA_MASK GENMASK(15, 0) ++ ++#define MLXBF_GIGE_PLL_SLEEP_FW 0x26820 ++#define MLXBF_GIGE_PLL_SLEEP_FW_MASK GENMASK(14, 14) ++ ++#define MLXBF_GIGE_PLL_ENABLE 0x26820 ++#define MLXBF_GIGE_PLL_ENABLE_MASK GENMASK(1, 1) ++ ++#define MLXBF_GIGE_PLL_RCAL 0x26828 ++#define MLXBF_GIGE_PLL_RCAL_MASK GENMASK(0, 0) ++ ++#define MLXBF_GIGE_PLL_CAL_VLD 0x2682c ++#define MLXBF_GIGE_PLL_CAL_VLD_MASK GENMASK(1, 0) ++ ++#define MLXBF_GIGE_PLL_CAL 0x26830 ++#define MLXBF_GIGE_PLL_CAL_MASK GENMASK(0, 0) ++ ++#define MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK 0x26878 ++#define MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK_MASK GENMASK(16, 0) ++ ++#define MLXBF_GIGE_PLL1X_FSM_DEFAULT_CYCLES 0x26900 ++#define MLXBF_GIGE_PLL1X_FSM_DEFAULT_VAL(const_factor) \ ++ ((250 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_PLL1X_FSM_SLEEP_CYCLES 0x26904 ++#define MLXBF_GIGE_PLL1X_FSM_SLEEP_VAL(const_factor) \ ++ ((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_CYCLES 0x26908 ++#define MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_VAL(const_factor) \ ++ ((40000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_CYCLES 0x2690c ++#define MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_VAL(const_factor) \ ++ ((300000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES 0x26910 ++#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_VAL(const_factor) \ ++ ((100000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK GENMASK(18, 0) ++ ++#define MLXBF_GIGE_PLL_IDDQ_CYCLES 0x26914 ++#define MLXBF_GIGE_PLL_IDDQ_CYCLES_VAL(const_factor) \ ++ ((2000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK GENMASK(28, 16) ++ ++#define MLXBF_GIGE_UPHY_PLL_RST_REG 0x26914 ++#define MLXBF_GIGE_UPHY_PLL_RST_REG_MASK GENMASK(2, 2) ++ ++#define MLXBF_GIGE_UGL_CR_BRIDGE_DESC 0x26a90 ++#define MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK GENMASK(5, 0) ++#define MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK GENMASK(13, 8) ++#define MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK GENMASK(21, 16) ++#define MLXBF_GIGE_UGL_CR_BRIDGE_ALL_MASK \ ++ (MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK | \ ++ MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK | \ ++ MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK) ++ ++#define MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_VAL(const_factor) \ ++ ((10 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_VAL(const_factor) \ ++ ((30 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++#define MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_VAL(const_factor) \ ++ ((10 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) ++ ++/* rw = 0 for write and 1 for read. ++ * data_en should be set to 1 only for a write transaction. ++ */ ++#define MLXBF_GIGE_PLL_GW_CREATE_CMD(addr, data, rw) \ ++ ((((addr) << MLXBF_GIGE_PLL_GW_ADDR_SHIFT) & MLXBF_GIGE_PLL_GW_ADDR_MASK) | \ ++ FIELD_PREP(MLXBF_GIGE_PLL_GW_RW_MASK, rw) | \ ++ FIELD_PREP(MLXBF_GIGE_PLL_GW_DATA_MASK, data) | \ ++ FIELD_PREP(MLXBF_GIGE_PLL_GW_DATA_EN_MASK, !rw) | \ ++ FIELD_PREP(MLXBF_GIGE_PLL_GW_BUSY_MASK, 1)) ++ ++#define MLXBF_GIGE_LANE_GW_CREATE_CMD(addr, data, rw) \ ++ ((((addr) << MLXBF_GIGE_LANE_GW_ADDR_SHIFT) & MLXBF_GIGE_LANE_GW_ADDR_MASK) | \ ++ FIELD_PREP(MLXBF_GIGE_LANE_GW_RW_MASK, rw) | \ ++ FIELD_PREP(MLXBF_GIGE_LANE_GW_DATA_MASK, data) | \ ++ FIELD_PREP(MLXBF_GIGE_LANE_GW_DATA_EN_MASK, !rw) | \ ++ FIELD_PREP(MLXBF_GIGE_LANE_GW_BUSY_MASK, 1)) ++ ++#define MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, data, rw, is_pll) \ ++ ((is_pll) ? MLXBF_GIGE_PLL_GW_CREATE_CMD(addr, data, rw) : \ ++ MLXBF_GIGE_LANE_GW_CREATE_CMD(addr, data, rw)) ++ ++#define MLXBF_GIGE_UPHY_GW(is_pll) \ ++ ((is_pll) ? MLXBF_GIGE_PLL_GW : MLXBF_GIGE_LANE_GW) ++ ++#define MLXBF_GIGE_UPHY_GW_DESC0(is_pll) \ ++ ((is_pll) ? MLXBF_GIGE_PLL_GW_DESC0 : MLXBF_GIGE_LANE_GW_DESC0) ++ ++#define MLXBF_GIGE_UPHY_GW_DESC0_DATA_MASK(is_pll) \ ++ ((is_pll) ? MLXBF_GIGE_PLL_GW_DESC0_DATA_MASK : \ ++ MLXBF_GIGE_LANE_GW_DESC0_DATA_MASK) ++ ++#define MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll) \ ++ ((is_pll) ? MLXBF_GIGE_PLL_GW_BUSY_MASK : \ ++ MLXBF_GIGE_LANE_GW_BUSY_MASK) ++ ++/* bootrecord p1clk */ ++#define MLXBF_GIGE_P1CLK_REG1 0x14 ++#define MLXBF_GIGE_P1CLK_REG2 0x18 ++#define MLXBF_GIGE_P1_CORE_F_SHIFT 0 ++#define MLXBF_GIGE_P1_CORE_F_MASK GENMASK(25, 0) ++#define MLXBF_GIGE_P1_CORE_R_SHIFT 26 ++#define MLXBF_GIGE_P1_CORE_R_MASK GENMASK(31, 26) ++#define MLXBF_GIGE_P1_CORE_OD_SHIFT 0 ++#define MLXBF_GIGE_P1_CORE_OD_MASK GENMASK(3, 0) ++ ++#define MLXBF_GIGE_P1CLK_MULT_FACTOR 12 ++#define MLXBF_GIGE_P1_FREQ_REFERENCE 156250000ULL ++#define MLXBF_GIGE_P1_CLK_CONST 16384ULL ++ ++/* There is a 32-bit crspace to 16-bit UPHY address encoding. ++ * The 16-bit address can be accessed via the GW register. ++ * Subtract the crspace region base address from the actual ++ * address that needs to be accessed via the gw. ++ * Then divide it by 4 since crspace registers are 4 bit aligned ++ */ ++#define MLXBF_GIGE_32B_TO_16B_ADDR(addr, base) (((addr) - (base)) >> 2) ++ ++#define MLXBF_GIGE_LANE_CSUM_STS_ADDR \ ++ MLXBF_GIGE_32B_TO_16B_ADDR( \ ++ MLXBF_GIGE_AE_SYS_IMEM_RAM_STAT_IMEM_CSUM_STS, \ ++ MLXBF_GIGE_LANE_CFG_FLAT0_BASE) ++ ++#define MLXBF_GIGE_IMEM_CSUM_RUN_AND_VALID 0x3 ++#define MLXBF_GIGE_INVALID_IMEM_CSUM -1 ++ ++#define MLXBF_GIGE_LANE_IMEM_DATA_ADDR \ ++ MLXBF_GIGE_32B_TO_16B_ADDR( \ ++ MLXBF_GIGE_AE_SYS_IMEM_RAM_DATA_CTRL_WDATA, \ ++ MLXBF_GIGE_LANE_CFG_FLAT0_BASE) ++ ++#define MLXBF_GIGE_MGMT_BGAP_FUSE_CTRL_ADDR \ ++ MLXBF_GIGE_32B_TO_16B_ADDR( \ ++ MLXBF_GIGE_PLL_CFG_FLAT0_MGMT_BGAP_FUSE_CTRL, \ ++ MLXBF_GIGE_PLL_CFG_FLAT0_BASE) ++ ++#define MLXBF_GIGE_YU_BG_TRIM_ROOM_MASK GENMASK(4, 0) ++#define MLXBF_GIGE_YU_BG_TRIM_ROOM_SHIFT 0 ++#define MLXBF_GIGE_YU_CVB_TRIM_ROOM_MASK GENMASK(9, 5) ++#define MLXBF_GIGE_YU_CVB_TRIM_ROOM_SHIFT 5 ++#define MLXBF_GIGE_YU_SPEEDO_ROOM_MASK GENMASK(14, 10) ++#define MLXBF_GIGE_YU_SPEEDO_ROOM_SHIFT 10 ++#define MLXBF_GIGE_YU_FUSE_VALID_SHIFT 4 ++/* Fuse mask without valid bit */ ++#define MLXBF_GIGE_YU_FUSE_MASK 0xf ++ ++enum { ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDDQ, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SLEEP, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_RCAL_DONE_WAIT1, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_RCAL_DONE_WAIT0, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDLE, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_CAL_DONE_WAIT1, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_CAL_DONE_WAIT0, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_ACTIVE, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_LOCK, ++ MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SPEED_CHANGE ++}; ++ ++enum { ++ MLXBF_GIGE_TX_FSM_IDDQ, ++ MLXBF_GIGE_TX_FSM_SLEEP, ++ MLXBF_GIGE_TX_FSM_SPEED_CHANGE, ++ MLXBF_GIGE_TX_FSM_POWERUP, ++ MLXBF_GIGE_TX_UGL_TX_POWERUP, ++ MLXBF_GIGE_TX_CAL_DONE_WAIT1, ++ MLXBF_GIGE_TX_CAL_ABORT, ++ MLXBF_GIGE_TX_CAL_ABORT_DONE_WAIT1, ++ MLXBF_GIGE_TX_CAL_DONE_WAIT0, ++ MLXBF_GIGE_TX_CAL_DONE, ++ MLXBF_GIGE_TX_DATA_READY, ++ MLXBF_GIGE_TX_DATA_EN_RDY, ++ MLXBF_GIGE_TX_DATA_EN ++}; ++ ++enum { ++ MLXBF_GIGE_RX_FSM_IDDQ, ++ MLXBF_GIGE_RX_FSM_SLEEP, ++ MLXBF_GIGE_RX_FSM_SPEED_CHANGE, ++ MLXBF_GIGE_RX_FSM_POWERUP, ++ MLXBF_GIGE_RX_FSM_CAL, ++ MLXBF_GIGE_RX_FSM_WAIT_TERM, ++ MLXBF_GIGE_RX_FSM_DATA_EN_RDY, ++ MLXBF_GIGE_RX_FSM_DATA_EN, ++ MLXBF_GIGE_RX_FSM_CDR_EN, ++ MLXBF_GIGE_RX_FSM_ACTIVE, ++ MLXBF_GIGE_RX_FSM_EQ, ++ MLXBF_GIGE_RX_FSM_EOM ++}; ++ ++#define MLXBF_GIGE_PLL_STAB_TIME 6 /* us */ ++#define MLXBF_GIGE_PLL_DLM_IMEM_CSUM_TIMEOUT 15 /* us */ ++ ++struct mlxbf_gige_uphy_cfg_reg { ++ u16 addr; ++ u16 wdata; ++}; ++ ++int mlxbf_gige_config_uphy(struct mlxbf_gige *priv); ++ ++#endif /* __MLXBF_GIGE_UPHY_H__ */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0242-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-ethtool_ops.patch b/platform/mellanox/non-upstream-patches/patches/0242-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-ethtool_ops.patch new file mode 100644 index 0000000000..d08aafb301 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0242-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-ethtool_ops.patch @@ -0,0 +1,95 @@ +From 33acf11a1ea46d88fbb27afff1537bdf5dd0e822 Mon Sep 17 00:00:00 2001 +From: David Thompson +Date: Fri, 28 Oct 2022 18:08:46 -0400 +Subject: [PATCH backport 5.10 43/63] UBUNTU: SAUCE: mlxbf_gige: add + BlueField-3 ethtool_ops + +BugLink: https://bugs.launchpad.net/bugs/1995148 + +This patch adds logic to support initialization of a +BlueField-3 specific "ethtool_ops" data structure. The +BlueField-3 data structure supports the "set_link_ksettings" +callback, while the BlueField-2 data structure does not. + +Signed-off-by: David Thompson +Signed-off-by: Asmaa Mnebhi +--- + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 3 ++- + .../mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | 17 ++++++++++++++++- + .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 4 +++- + 3 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index e9bd09ee0..cbabdac3e 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -200,7 +200,8 @@ struct sk_buff *mlxbf_gige_alloc_skb(struct mlxbf_gige *priv, + int mlxbf_gige_request_irqs(struct mlxbf_gige *priv); + void mlxbf_gige_free_irqs(struct mlxbf_gige *priv); + int mlxbf_gige_poll(struct napi_struct *napi, int budget); +-extern const struct ethtool_ops mlxbf_gige_ethtool_ops; ++extern const struct ethtool_ops mlxbf_gige_bf2_ethtool_ops; ++extern const struct ethtool_ops mlxbf_gige_bf3_ethtool_ops; + void mlxbf_gige_update_tx_wqe_next(struct mlxbf_gige *priv); + + #endif /* !defined(__MLXBF_GIGE_H__) */ +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +index 257724323..3156ef064 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +@@ -158,7 +158,7 @@ static void mlxbf_gige_get_pauseparam(struct net_device *netdev, + pause->tx_pause = 1; + } + +-const struct ethtool_ops mlxbf_gige_ethtool_ops = { ++const struct ethtool_ops mlxbf_gige_bf2_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_ringparam = mlxbf_gige_get_ringparam, + .set_ringparam = mlxbf_gige_set_ringparam, +@@ -171,3 +171,18 @@ const struct ethtool_ops mlxbf_gige_ethtool_ops = { + .get_pauseparam = mlxbf_gige_get_pauseparam, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + }; ++ ++const struct ethtool_ops mlxbf_gige_bf3_ethtool_ops = { ++ .get_link = ethtool_op_get_link, ++ .get_ringparam = mlxbf_gige_get_ringparam, ++ .set_ringparam = mlxbf_gige_set_ringparam, ++ .get_regs_len = mlxbf_gige_get_regs_len, ++ .get_regs = mlxbf_gige_get_regs, ++ .get_strings = mlxbf_gige_get_strings, ++ .get_sset_count = mlxbf_gige_get_sset_count, ++ .get_ethtool_stats = mlxbf_gige_get_ethtool_stats, ++ .nway_reset = phy_ethtool_nway_reset, ++ .get_pauseparam = mlxbf_gige_get_pauseparam, ++ .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .set_link_ksettings = phy_ethtool_set_link_ksettings, ++}; +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index f97e49670..197ec8ccb 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -451,7 +451,6 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + + SET_NETDEV_DEV(netdev, &pdev->dev); + netdev->netdev_ops = &mlxbf_gige_netdev_ops; +- netdev->ethtool_ops = &mlxbf_gige_ethtool_ops; + priv = netdev_priv(netdev); + priv->netdev = netdev; + +@@ -468,9 +467,12 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + priv->hw_version = soc_version; + + if (priv->hw_version == MLXBF_GIGE_VERSION_BF3) { ++ netdev->ethtool_ops = &mlxbf_gige_bf3_ethtool_ops; + err = mlxbf_gige_config_uphy(priv); + if (err) + return err; ++ } else { ++ netdev->ethtool_ops = &mlxbf_gige_bf2_ethtool_ops; + } + + /* Attach MDIO device */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0243-UBUNTU-SAUCE-bluefield_edac-Add-SMC-support.patch b/platform/mellanox/non-upstream-patches/patches/0243-UBUNTU-SAUCE-bluefield_edac-Add-SMC-support.patch new file mode 100644 index 0000000000..51f40a5b73 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0243-UBUNTU-SAUCE-bluefield_edac-Add-SMC-support.patch @@ -0,0 +1,291 @@ +From 9bebe7236f4e3d956feda9911ffee5f31dfbdb13 Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Wed, 6 Jul 2022 03:37:38 -0400 +Subject: [PATCH backport 5.10 44/63] UBUNTU: SAUCE: bluefield_edac: Add SMC + support + +BugLink: https://launchpad.net/bugs/1980812 + +This patch adds secure read/write calls to bluefield_edac. The +ACPI table entry decides whether the secure calls need to be +used for accessing the EMI registers. + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/edac/bluefield_edac.c | 168 +++++++++++++++++++++++++++++++--- + 1 file changed, 154 insertions(+), 14 deletions(-) + +diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c +index e4736eb37..8e1127a56 100644 +--- a/drivers/edac/bluefield_edac.c ++++ b/drivers/edac/bluefield_edac.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include "edac_module.h" + +@@ -47,6 +48,18 @@ + #define MLXBF_EDAC_MAX_DIMM_PER_MC 2 + #define MLXBF_EDAC_ERROR_GRAIN 8 + ++#define MLNX_WRITE_REG_32 (0x82000009) ++#define MLNX_READ_REG_32 (0x8200000A) ++#define MLNX_WRITE_REG_64 (0x8200000B) ++#define MLNX_READ_REG_64 (0x8200000C) ++#define MLNX_SIP_SVC_UID (0x8200ff01) ++#define MLNX_SIP_SVC_VERSION (0x8200ff03) ++ ++#define SMCCC_ACCESS_VIOLATION (-4) ++ ++#define MLNX_EDAC_SVC_REQ_MAJOR 0 ++#define MLNX_EDAC_SVC_MIN_MINOR 3 ++ + /* + * Request MLNX_SIP_GET_DIMM_INFO + * +@@ -72,9 +85,12 @@ + #define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24) + + struct bluefield_edac_priv { ++ struct device *dev; + int dimm_ranks[MLXBF_EDAC_MAX_DIMM_PER_MC]; + void __iomem *emi_base; + int dimm_per_mc; ++ bool svc_sreg_support; ++ uint32_t sreg_tbl_edac; + }; + + static u64 smc_call1(u64 smc_op, u64 smc_arg) +@@ -86,6 +102,73 @@ static u64 smc_call1(u64 smc_op, u64 smc_arg) + return res.a0; + } + ++static int secure_readl(void __iomem *addr, uint32_t *result, uint32_t sreg_tbl) ++{ ++ struct arm_smccc_res res; ++ int status; ++ ++ arm_smccc_smc(MLNX_READ_REG_32, sreg_tbl, (uintptr_t) addr, ++ 0, 0, 0, 0, 0, &res); ++ ++ status = res.a0; ++ ++ switch (status) { ++ case SMCCC_RET_NOT_SUPPORTED: ++ case SMCCC_ACCESS_VIOLATION: ++ return -1; ++ default: ++ *result = (uint32_t)res.a1; ++ return 0; ++ } ++ ++} ++ ++static int secure_writel(void __iomem *addr, uint32_t data, uint32_t sreg_tbl) ++{ ++ struct arm_smccc_res res; ++ int status; ++ ++ arm_smccc_smc(MLNX_WRITE_REG_32, sreg_tbl, data, (uintptr_t) addr, ++ 0, 0, 0, 0, &res); ++ ++ status = res.a0; ++ ++ switch (status) { ++ case SMCCC_RET_NOT_SUPPORTED: ++ case SMCCC_ACCESS_VIOLATION: ++ return -1; ++ default: ++ return 0; ++ } ++ ++} ++ ++static int edac_readl(void __iomem *addr, uint32_t *result, ++ bool sreg_support, uint32_t sreg_tbl) ++{ ++ int err = 0; ++ ++ if (sreg_support) ++ err = secure_readl(addr, result, sreg_tbl); ++ else ++ *result = readl(addr); ++ ++ return err; ++} ++ ++static int edac_writel(void __iomem *addr, uint32_t data, ++ bool sreg_support, uint32_t sreg_tbl) ++{ ++ int err = 0; ++ ++ if (sreg_support) ++ err = secure_writel(addr, data, sreg_tbl); ++ else ++ writel(data, addr); ++ ++ return err; ++} ++ + /* + * Gather the ECC information from the External Memory Interface registers + * and report it to the edac handler. +@@ -99,7 +182,7 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci, + u32 ecc_latch_select, dram_syndrom, serr, derr, syndrom; + enum hw_event_mc_err_type ecc_type; + u64 ecc_dimm_addr; +- int ecc_dimm; ++ int ecc_dimm, err; + + ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED : + HW_EVENT_ERR_UNCORRECTED; +@@ -109,14 +192,22 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci, + * registers with information about the last ECC error occurrence. + */ + ecc_latch_select = MLXBF_ECC_LATCH_SEL__START; +- writel(ecc_latch_select, priv->emi_base + MLXBF_ECC_LATCH_SEL); ++ err = edac_writel(priv->emi_base + MLXBF_ECC_LATCH_SEL, ++ ecc_latch_select, priv->svc_sreg_support, ++ priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "ECC latch select write failed.\n"); + + /* + * Verify that the ECC reported info in the registers is of the + * same type as the one asked to report. If not, just report the + * error without the detailed information. + */ +- dram_syndrom = readl(priv->emi_base + MLXBF_SYNDROM); ++ err = edac_readl(priv->emi_base + MLXBF_SYNDROM, &dram_syndrom, ++ priv->svc_sreg_support, priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "DRAM syndrom read failed.\n"); ++ + serr = FIELD_GET(MLXBF_SYNDROM__SERR, dram_syndrom); + derr = FIELD_GET(MLXBF_SYNDROM__DERR, dram_syndrom); + syndrom = FIELD_GET(MLXBF_SYNDROM__SYN, dram_syndrom); +@@ -127,13 +218,24 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci, + return; + } + +- dram_additional_info = readl(priv->emi_base + MLXBF_ADD_INFO); ++ err = edac_readl(priv->emi_base + MLXBF_ADD_INFO, &dram_additional_info, ++ priv->svc_sreg_support, priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "DRAM additional info read failed.\n"); ++ + err_prank = FIELD_GET(MLXBF_ADD_INFO__ERR_PRANK, dram_additional_info); + + ecc_dimm = (err_prank >= 2 && priv->dimm_ranks[0] <= 2) ? 1 : 0; + +- edea0 = readl(priv->emi_base + MLXBF_ERR_ADDR_0); +- edea1 = readl(priv->emi_base + MLXBF_ERR_ADDR_1); ++ err = edac_readl(priv->emi_base + MLXBF_ERR_ADDR_0, &edea0, ++ priv->svc_sreg_support, priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "Error addr 0 read failed.\n"); ++ ++ err = edac_readl(priv->emi_base + MLXBF_ERR_ADDR_1, &edea1, ++ priv->svc_sreg_support, priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "Error addr 1 read failed.\n"); + + ecc_dimm_addr = ((u64)edea1 << 32) | edea0; + +@@ -147,6 +249,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci) + { + struct bluefield_edac_priv *priv = mci->pvt_info; + u32 ecc_count, single_error_count, double_error_count, ecc_error = 0; ++ int err; + + /* + * The memory controller might not be initialized by the firmware +@@ -155,7 +258,11 @@ static void bluefield_edac_check(struct mem_ctl_info *mci) + if (mci->edac_cap == EDAC_FLAG_NONE) + return; + +- ecc_count = readl(priv->emi_base + MLXBF_ECC_CNT); ++ err = edac_readl(priv->emi_base + MLXBF_ECC_CNT, &ecc_count, ++ priv->svc_sreg_support, priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "ECC count read failed.\n"); ++ + single_error_count = FIELD_GET(MLXBF_ECC_CNT__SERR_CNT, ecc_count); + double_error_count = FIELD_GET(MLXBF_ECC_CNT__DERR_CNT, ecc_count); + +@@ -172,8 +279,12 @@ static void bluefield_edac_check(struct mem_ctl_info *mci) + } + + /* Write to clear reported errors. */ +- if (ecc_count) +- writel(ecc_error, priv->emi_base + MLXBF_ECC_ERR); ++ if (ecc_count) { ++ err = edac_writel(priv->emi_base + MLXBF_ECC_ERR, ecc_error, ++ priv->svc_sreg_support, priv->sreg_tbl_edac); ++ if (err) ++ dev_err(priv->dev, "ECC Error write failed.\n"); ++ } + } + + /* Initialize the DIMMs information for the given memory controller. */ +@@ -244,6 +355,7 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev) + struct bluefield_edac_priv *priv; + struct device *dev = &pdev->dev; + struct edac_mc_layer layers[1]; ++ struct arm_smccc_res res; + struct mem_ctl_info *mci; + struct resource *emi_res; + unsigned int mc_idx, dimm_count; +@@ -280,12 +392,40 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev) + + priv = mci->pvt_info; + ++ /* ++ * ACPI indicates whether we use SMCs to access registers or not. ++ * If sreg_tbl_perf is not present, just assume we're not using SMCs. ++ */ ++ if (device_property_read_u32(dev, ++ "sec_reg_block", &priv->sreg_tbl_edac)) { ++ priv->svc_sreg_support = false; ++ } else { ++ /* ++ * Check service version to see if we actually do support the ++ * needed SMCs. If we have the calls we need, mark support for ++ * them in the pmc struct. ++ */ ++ arm_smccc_smc(MLNX_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); ++ if (res.a0 == MLNX_EDAC_SVC_REQ_MAJOR && ++ res.a1 >= MLNX_EDAC_SVC_MIN_MINOR) ++ priv->svc_sreg_support = true; ++ else { ++ dev_err(dev, "Required SMCs are not supported.\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ } ++ + priv->dimm_per_mc = dimm_count; +- priv->emi_base = devm_ioremap_resource(dev, emi_res); +- if (IS_ERR(priv->emi_base)) { +- dev_err(dev, "failed to map EMI IO resource\n"); +- ret = PTR_ERR(priv->emi_base); +- goto err; ++ if (!priv->svc_sreg_support) { ++ priv->emi_base = devm_ioremap_resource(dev, emi_res); ++ if (IS_ERR(priv->emi_base)) { ++ dev_err(dev, "failed to map EMI IO resource\n"); ++ ret = PTR_ERR(priv->emi_base); ++ goto err; ++ } ++ } else { ++ priv->emi_base = (void __iomem *) emi_res->start; + } + + mci->pdev = dev; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0244-UBUNTU-SAUCE-bluefield_edac-Update-license-and-copyr.patch b/platform/mellanox/non-upstream-patches/patches/0244-UBUNTU-SAUCE-bluefield_edac-Update-license-and-copyr.patch new file mode 100644 index 0000000000..1e80cc4bb3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0244-UBUNTU-SAUCE-bluefield_edac-Update-license-and-copyr.patch @@ -0,0 +1,40 @@ +From 8f60f2a6f44e75005bb94add0288d2c390870b11 Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Thu, 7 Jul 2022 05:13:21 -0400 +Subject: [PATCH backport 5.10 45/63] UBUNTU: SAUCE: bluefield_edac: Update + license and copyright info + +BugLink: https://launchpad.net/bugs/1980812 + +Signed-off-by: Shravan Kumar Ramani +Signed-off-by: Ike Panhc +--- + drivers/edac/bluefield_edac.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c +index 8e1127a56..c21eb015f 100644 +--- a/drivers/edac/bluefield_edac.c ++++ b/drivers/edac/bluefield_edac.c +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause + /* + * Bluefield-specific EDAC driver. + * +- * Copyright (c) 2019 Mellanox Technologies. ++ * Copyright (c) 2022 NVIDIA Corporation. + */ + + #include +@@ -492,5 +492,5 @@ static struct platform_driver bluefield_edac_mc_driver = { + module_platform_driver(bluefield_edac_mc_driver); + + MODULE_DESCRIPTION("Mellanox BlueField memory edac driver"); +-MODULE_AUTHOR("Mellanox Technologies"); +-MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Shravan Kumar Ramani "); ++MODULE_LICENSE("Dual BSD/GPL"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0245-gpio-mlxbf2-Convert-to-device-PM-ops.patch b/platform/mellanox/non-upstream-patches/patches/0245-gpio-mlxbf2-Convert-to-device-PM-ops.patch new file mode 100644 index 0000000000..18c4647701 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0245-gpio-mlxbf2-Convert-to-device-PM-ops.patch @@ -0,0 +1,93 @@ +From c1facb3e3527a3f0d9125cc2336ae407acbbcc03 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Mon, 16 Aug 2021 14:59:48 +0300 +Subject: [PATCH backport 5.10 46/63] gpio: mlxbf2: Convert to device PM ops + +Convert driver to use modern device PM ops interface. + +Signed-off-by: Andy Shevchenko +Acked-by: Asmaa Mnebhi +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-mlxbf2.c | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c +index befa5e109..68c471c10 100644 +--- a/drivers/gpio/gpio-mlxbf2.c ++++ b/drivers/gpio/gpio-mlxbf2.c +@@ -47,12 +47,10 @@ + #define YU_GPIO_MODE0_SET 0x54 + #define YU_GPIO_MODE0_CLEAR 0x58 + +-#ifdef CONFIG_PM + struct mlxbf2_gpio_context_save_regs { + u32 gpio_mode0; + u32 gpio_mode1; + }; +-#endif + + /* BlueField-2 gpio block context structure. */ + struct mlxbf2_gpio_context { +@@ -61,9 +59,7 @@ struct mlxbf2_gpio_context { + /* YU GPIO blocks address */ + void __iomem *gpio_io; + +-#ifdef CONFIG_PM + struct mlxbf2_gpio_context_save_regs *csave_regs; +-#endif + }; + + /* BlueField-2 gpio shared structure. */ +@@ -284,11 +280,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev) + return 0; + } + +-#ifdef CONFIG_PM +-static int mlxbf2_gpio_suspend(struct platform_device *pdev, +- pm_message_t state) ++static int __maybe_unused mlxbf2_gpio_suspend(struct device *dev) + { +- struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); ++ struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev); + + gs->csave_regs->gpio_mode0 = readl(gs->gpio_io + + YU_GPIO_MODE0); +@@ -298,9 +292,9 @@ static int mlxbf2_gpio_suspend(struct platform_device *pdev, + return 0; + } + +-static int mlxbf2_gpio_resume(struct platform_device *pdev) ++static int __maybe_unused mlxbf2_gpio_resume(struct device *dev) + { +- struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); ++ struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev); + + writel(gs->csave_regs->gpio_mode0, gs->gpio_io + + YU_GPIO_MODE0); +@@ -309,7 +303,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev) + + return 0; + } +-#endif ++static SIMPLE_DEV_PM_OPS(mlxbf2_pm_ops, mlxbf2_gpio_suspend, mlxbf2_gpio_resume); + + static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = { + { "MLNXBF22", 0 }, +@@ -321,12 +315,9 @@ static struct platform_driver mlxbf2_gpio_driver = { + .driver = { + .name = "mlxbf2_gpio", + .acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match), ++ .pm = &mlxbf2_pm_ops, + }, + .probe = mlxbf2_gpio_probe, +-#ifdef CONFIG_PM +- .suspend = mlxbf2_gpio_suspend, +- .resume = mlxbf2_gpio_resume, +-#endif + }; + + module_platform_driver(mlxbf2_gpio_driver); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0246-gpio-mlxbf2-Drop-wrong-use-of-ACPI_PTR.patch b/platform/mellanox/non-upstream-patches/patches/0246-gpio-mlxbf2-Drop-wrong-use-of-ACPI_PTR.patch new file mode 100644 index 0000000000..7f58101601 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0246-gpio-mlxbf2-Drop-wrong-use-of-ACPI_PTR.patch @@ -0,0 +1,50 @@ +From 6b12d567b86b79ff28397aa428778d9f159fb8da Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Mon, 16 Aug 2021 14:59:49 +0300 +Subject: [PATCH backport 5.10 47/63] gpio: mlxbf2: Drop wrong use of + ACPI_PTR() + +ACPI_PTR() is more harmful than helpful. For example, in this case +if CONFIG_ACPI=n, the ID table left unused which is not what we want. + +Instead of adding ifdeffery here and there, drop ACPI_PTR() and +replace acpi.h with mod_devicetable.h. + +Signed-off-by: Andy Shevchenko +Acked-by: Asmaa Mnehi +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-mlxbf2.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c +index 68c471c10..8e6f78092 100644 +--- a/drivers/gpio/gpio-mlxbf2.c ++++ b/drivers/gpio/gpio-mlxbf2.c +@@ -1,6 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 + +-#include + #include + #include + #include +@@ -8,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -314,7 +314,7 @@ MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match); + static struct platform_driver mlxbf2_gpio_driver = { + .driver = { + .name = "mlxbf2_gpio", +- .acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match), ++ .acpi_match_table = mlxbf2_gpio_acpi_match, + .pm = &mlxbf2_pm_ops, + }, + .probe = mlxbf2_gpio_probe, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0247-gpio-mlxbf2-Use-devm_platform_ioremap_resource.patch b/platform/mellanox/non-upstream-patches/patches/0247-gpio-mlxbf2-Use-devm_platform_ioremap_resource.patch new file mode 100644 index 0000000000..dc24c6dc4d --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0247-gpio-mlxbf2-Use-devm_platform_ioremap_resource.patch @@ -0,0 +1,48 @@ +From a75294f3e540e2d76a39583dbae875c428196f79 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Mon, 16 Aug 2021 14:59:50 +0300 +Subject: [PATCH backport 5.10 48/63] gpio: mlxbf2: Use + devm_platform_ioremap_resource() + +Simplify the platform_get_resource() and devm_ioremap_resource() +calls with devm_platform_ioremap_resource(). + +Signed-off-by: Andy Shevchenko +Acked-by: Asmaa Mnebhi +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-mlxbf2.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c +index 8e6f78092..661d5a831 100644 +--- a/drivers/gpio/gpio-mlxbf2.c ++++ b/drivers/gpio/gpio-mlxbf2.c +@@ -228,7 +228,6 @@ mlxbf2_gpio_probe(struct platform_device *pdev) + struct mlxbf2_gpio_context *gs; + struct device *dev = &pdev->dev; + struct gpio_chip *gc; +- struct resource *res; + unsigned int npins; + int ret; + +@@ -237,13 +236,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev) + return -ENOMEM; + + /* YU GPIO block address */ +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) +- return -ENODEV; +- +- gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res)); +- if (!gs->gpio_io) +- return -ENOMEM; ++ gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(gs->gpio_io)) ++ return PTR_ERR(gs->gpio_io); + + ret = mlxbf2_gpio_get_lock_res(pdev); + if (ret) { +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0248-gpio-mlxbf2-Use-DEFINE_RES_MEM_NAMED-helper-macro.patch b/platform/mellanox/non-upstream-patches/patches/0248-gpio-mlxbf2-Use-DEFINE_RES_MEM_NAMED-helper-macro.patch new file mode 100644 index 0000000000..441d83e30a --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0248-gpio-mlxbf2-Use-DEFINE_RES_MEM_NAMED-helper-macro.patch @@ -0,0 +1,37 @@ +From e3e44e5389d723c49f187d91c16df0ec1b67ce53 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Mon, 16 Aug 2021 14:59:51 +0300 +Subject: [PATCH backport 5.10 49/63] gpio: mlxbf2: Use DEFINE_RES_MEM_NAMED() + helper macro + +Use DEFINE_RES_MEM_NAMED() to save a couple of lines of code, which makes +the code a bit shorter and easier to read. + +Signed-off-by: Andy Shevchenko +Acked-by: Asmaa Mnebhi +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-mlxbf2.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c +index 661d5a831..177d03ef4 100644 +--- a/drivers/gpio/gpio-mlxbf2.c ++++ b/drivers/gpio/gpio-mlxbf2.c +@@ -69,11 +69,8 @@ struct mlxbf2_gpio_param { + struct mutex *lock; + }; + +-static struct resource yu_arm_gpio_lock_res = { +- .start = YU_ARM_GPIO_LOCK_ADDR, +- .end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1, +- .name = "YU_ARM_GPIO_LOCK", +-}; ++static struct resource yu_arm_gpio_lock_res = ++ DEFINE_RES_MEM_NAMED(YU_ARM_GPIO_LOCK_ADDR, YU_ARM_GPIO_LOCK_SIZE, "YU_ARM_GPIO_LOCK"); + + static DEFINE_MUTEX(yu_arm_gpio_lock_mutex); + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0249-gpio-mlxbf2-Introduce-IRQ-support.patch b/platform/mellanox/non-upstream-patches/patches/0249-gpio-mlxbf2-Introduce-IRQ-support.patch new file mode 100644 index 0000000000..0bde44f14f --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0249-gpio-mlxbf2-Introduce-IRQ-support.patch @@ -0,0 +1,222 @@ +From 1eac5d74f7cd42e661479080a47547b657c16a18 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Fri, 15 Oct 2021 12:48:08 -0400 +Subject: [PATCH backport 5.10 51/63] gpio: mlxbf2: Introduce IRQ support + +BugLink: https://bugs.launchpad.net/bugs/1979827 + +Introduce standard IRQ handling in the gpio-mlxbf2.c +driver. + +Signed-off-by: Asmaa Mnebhi +Acked-by: David S. Miller +Signed-off-by: Bartosz Golaszewski +(cherry picked from commit 2b725265cb08d6a0001bf81631ccb5728d095229) +Signed-off-by: Ike Panhc +--- + drivers/gpio/gpio-mlxbf2.c | 142 ++++++++++++++++++++++++++++++++++++- + 1 file changed, 140 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c +index 40a052bc6..3d89912a0 100644 +--- a/drivers/gpio/gpio-mlxbf2.c ++++ b/drivers/gpio/gpio-mlxbf2.c +@@ -1,9 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0 + ++/* ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -43,9 +48,14 @@ + #define YU_GPIO_MODE0 0x0c + #define YU_GPIO_DATASET 0x14 + #define YU_GPIO_DATACLEAR 0x18 ++#define YU_GPIO_CAUSE_RISE_EN 0x44 ++#define YU_GPIO_CAUSE_FALL_EN 0x48 + #define YU_GPIO_MODE1_CLEAR 0x50 + #define YU_GPIO_MODE0_SET 0x54 + #define YU_GPIO_MODE0_CLEAR 0x58 ++#define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80 ++#define YU_GPIO_CAUSE_OR_EVTEN0 0x94 ++#define YU_GPIO_CAUSE_OR_CLRCAUSE 0x98 + + struct mlxbf2_gpio_context_save_regs { + u32 gpio_mode0; +@@ -55,6 +65,7 @@ struct mlxbf2_gpio_context_save_regs { + /* BlueField-2 gpio block context structure. */ + struct mlxbf2_gpio_context { + struct gpio_chip gc; ++ struct irq_chip irq_chip; + + /* YU GPIO blocks address */ + void __iomem *gpio_io; +@@ -218,15 +229,114 @@ static int mlxbf2_gpio_direction_output(struct gpio_chip *chip, + return ret; + } + ++static void mlxbf2_gpio_irq_enable(struct irq_data *irqd) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); ++ struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); ++ int offset = irqd_to_hwirq(irqd); ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); ++ val |= BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); ++ ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ val |= BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++} ++ ++static void mlxbf2_gpio_irq_disable(struct irq_data *irqd) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); ++ struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); ++ int offset = irqd_to_hwirq(irqd); ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ val &= ~BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++} ++ ++static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr) ++{ ++ struct mlxbf2_gpio_context *gs = ptr; ++ struct gpio_chip *gc = &gs->gc; ++ unsigned long pending; ++ u32 level; ++ ++ pending = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0); ++ writel(pending, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); ++ ++ for_each_set_bit(level, &pending, gc->ngpio) { ++ int gpio_irq = irq_find_mapping(gc->irq.domain, level); ++ generic_handle_irq(gpio_irq); ++ } ++ ++ return IRQ_RETVAL(pending); ++} ++ ++static int ++mlxbf2_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); ++ struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); ++ int offset = irqd_to_hwirq(irqd); ++ unsigned long flags; ++ bool fall = false; ++ bool rise = false; ++ u32 val; ++ ++ switch (type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_BOTH: ++ fall = true; ++ rise = true; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ rise = true; ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ fall = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ if (fall) { ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); ++ val |= BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); ++ } ++ ++ if (rise) { ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); ++ val |= BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); ++ } ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++ ++ return 0; ++} ++ + /* BlueField-2 GPIO driver initialization routine. */ + static int + mlxbf2_gpio_probe(struct platform_device *pdev) + { + struct mlxbf2_gpio_context *gs; + struct device *dev = &pdev->dev; ++ struct gpio_irq_chip *girq; + struct gpio_chip *gc; + unsigned int npins; +- int ret; ++ const char *name; ++ int ret, irq; ++ ++ name = dev_name(dev); + + gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); + if (!gs) +@@ -266,6 +376,34 @@ mlxbf2_gpio_probe(struct platform_device *pdev) + gc->ngpio = npins; + gc->owner = THIS_MODULE; + ++ irq = platform_get_irq(pdev, 0); ++ if (irq >= 0) { ++ gs->irq_chip.name = name; ++ gs->irq_chip.irq_set_type = mlxbf2_gpio_irq_set_type; ++ gs->irq_chip.irq_enable = mlxbf2_gpio_irq_enable; ++ gs->irq_chip.irq_disable = mlxbf2_gpio_irq_disable; ++ ++ girq = &gs->gc.irq; ++ girq->chip = &gs->irq_chip; ++ girq->handler = handle_simple_irq; ++ girq->default_type = IRQ_TYPE_NONE; ++ /* This will let us handle the parent IRQ in the driver */ ++ girq->num_parents = 0; ++ girq->parents = NULL; ++ girq->parent_handler = NULL; ++ ++ /* ++ * Directly request the irq here instead of passing ++ * a flow-handler because the irq is shared. ++ */ ++ ret = devm_request_irq(dev, irq, mlxbf2_gpio_irq_handler, ++ IRQF_SHARED, name, gs); ++ if (ret) { ++ dev_err(dev, "failed to request IRQ"); ++ return ret; ++ } ++ } ++ + platform_set_drvdata(pdev, gs); + + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); +@@ -320,5 +458,5 @@ static struct platform_driver mlxbf2_gpio_driver = { + module_platform_driver(mlxbf2_gpio_driver); + + MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); +-MODULE_AUTHOR("Mellanox Technologies"); ++MODULE_AUTHOR("Asmaa Mnebhi "); + MODULE_LICENSE("GPL v2"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0250-UBUNTU-SAUCE-gpio-mlxbf2.c-support-driver-version.patch b/platform/mellanox/non-upstream-patches/patches/0250-UBUNTU-SAUCE-gpio-mlxbf2.c-support-driver-version.patch new file mode 100644 index 0000000000..1bdc64da28 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0250-UBUNTU-SAUCE-gpio-mlxbf2.c-support-driver-version.patch @@ -0,0 +1,35 @@ +From e71b4be56c799c407a4b8b08528dc3a1bb31cda3 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Fri, 8 Jul 2022 16:56:40 -0400 +Subject: [PATCH backport 5.10 52/63] UBUNTU: SAUCE: gpio-mlxbf2.c: support + driver version + +BugLink: https://launchpad.net/bugs/1981108 + +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Ike Panhc +--- + drivers/gpio/gpio-mlxbf2.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c +index 3d89912a0..cf9dbe8e5 100644 +--- a/drivers/gpio/gpio-mlxbf2.c ++++ b/drivers/gpio/gpio-mlxbf2.c +@@ -20,6 +20,8 @@ + #include + #include + ++#define DRV_VERSION "1.5" ++ + /* + * There are 3 YU GPIO blocks: + * gpio[0]: HOST_GPIO0->HOST_GPIO31 +@@ -460,3 +462,4 @@ module_platform_driver(mlxbf2_gpio_driver); + MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); + MODULE_AUTHOR("Asmaa Mnebhi "); + MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRV_VERSION); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0251-mmc-sdhci-of-dwcmshc-add-rockchip-platform-support.patch b/platform/mellanox/non-upstream-patches/patches/0251-mmc-sdhci-of-dwcmshc-add-rockchip-platform-support.patch new file mode 100644 index 0000000000..0f4e702ba7 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0251-mmc-sdhci-of-dwcmshc-add-rockchip-platform-support.patch @@ -0,0 +1,395 @@ +From 6995d23f8b01b24dd6786413f9219334136b6d32 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Tue, 16 Mar 2021 15:18:22 +0800 +Subject: [PATCH backport 5.10 53/63] mmc: sdhci-of-dwcmshc: add rockchip + platform support + +sdhci based synopsys MMC IP is also used on some rockchip platforms, +so add a basic support here. + +Signed-off-by: Shawn Lin +Link: https://lore.kernel.org/r/1615879102-45919-3-git-send-email-shawn.lin@rock-chips.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 261 +++++++++++++++++++++++++++- + 1 file changed, 253 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index 59d8d96ce..06873686d 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -9,9 +9,11 @@ + + #include + #include ++#include + #include + #include + #include ++#include + #include + + #include "sdhci-pltfm.h" +@@ -21,11 +23,52 @@ + /* DWCMSHC specific Mode Select value */ + #define DWCMSHC_CTRL_HS400 0x7 + ++/* DWC IP vendor area 1 pointer */ ++#define DWCMSHC_P_VENDOR_AREA1 0xe8 ++#define DWCMSHC_AREA1_MASK GENMASK(11, 0) ++/* Offset inside the vendor area 1 */ ++#define DWCMSHC_HOST_CTRL3 0x8 ++#define DWCMSHC_EMMC_CONTROL 0x2c ++#define DWCMSHC_ENHANCED_STROBE BIT(8) ++#define DWCMSHC_EMMC_ATCTRL 0x40 ++ ++/* Rockchip specific Registers */ ++#define DWCMSHC_EMMC_DLL_CTRL 0x800 ++#define DWCMSHC_EMMC_DLL_RXCLK 0x804 ++#define DWCMSHC_EMMC_DLL_TXCLK 0x808 ++#define DWCMSHC_EMMC_DLL_STRBIN 0x80c ++#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) ++#define DWCMSHC_EMMC_DLL_STATUS0 0x840 ++#define DWCMSHC_EMMC_DLL_START BIT(0) ++#define DWCMSHC_EMMC_DLL_LOCKED BIT(8) ++#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9) ++#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 ++#define DWCMSHC_EMMC_DLL_START_POINT 16 ++#define DWCMSHC_EMMC_DLL_INC 8 ++#define DWCMSHC_EMMC_DLL_DLYENA BIT(27) ++#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 ++#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 ++#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) ++#define DLL_RXCLK_NO_INVERTER 1 ++#define DLL_RXCLK_INVERTER 0 ++#define DLL_LOCK_WO_TMOUT(x) \ ++ ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ ++ (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) ++#define RK3568_MAX_CLKS 3 ++ + #define BOUNDARY_OK(addr, len) \ + ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) + ++struct rk3568_priv { ++ /* Rockchip specified optional clocks */ ++ struct clk_bulk_data rockchip_clks[RK3568_MAX_CLKS]; ++ u8 txclk_tapnum; ++}; ++ + struct dwcmshc_priv { + struct clk *bus_clk; ++ int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */ ++ void *priv; /* pointer to SoC private stuff */ + }; + + /* +@@ -100,6 +143,107 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + } + ++static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc, ++ struct mmc_ios *ios) ++{ ++ u32 vendor; ++ struct sdhci_host *host = mmc_priv(mmc); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL; ++ ++ vendor = sdhci_readl(host, reg); ++ if (ios->enhanced_strobe) ++ vendor |= DWCMSHC_ENHANCED_STROBE; ++ else ++ vendor &= ~DWCMSHC_ENHANCED_STROBE; ++ ++ sdhci_writel(host, vendor, reg); ++} ++ ++static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); ++ struct rk3568_priv *priv = dwc_priv->priv; ++ u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; ++ u32 extra, reg; ++ int err; ++ ++ host->mmc->actual_clock = 0; ++ ++ /* ++ * DO NOT TOUCH THIS SETTING. RX clk inverter unit is enabled ++ * by default, but it shouldn't be enabled. We should anyway ++ * disable it before issuing any cmds. ++ */ ++ extra = DWCMSHC_EMMC_DLL_DLYENA | ++ DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; ++ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); ++ ++ if (clock == 0) ++ return; ++ ++ /* Rockchip platform only support 375KHz for identify mode */ ++ if (clock <= 400000) ++ clock = 375000; ++ ++ err = clk_set_rate(pltfm_host->clk, clock); ++ if (err) ++ dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock); ++ ++ sdhci_set_clock(host, clock); ++ ++ /* Disable cmd conflict check */ ++ reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3; ++ extra = sdhci_readl(host, reg); ++ extra &= ~BIT(0); ++ sdhci_writel(host, extra, reg); ++ ++ if (clock <= 400000) { ++ /* Disable DLL to reset sample clock */ ++ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); ++ return; ++ } ++ ++ /* Reset DLL */ ++ sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL); ++ udelay(1); ++ sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL); ++ ++ /* Init DLL settings */ ++ extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | ++ 0x2 << DWCMSHC_EMMC_DLL_INC | ++ DWCMSHC_EMMC_DLL_START; ++ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL); ++ err = readl_poll_timeout(host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0, ++ extra, DLL_LOCK_WO_TMOUT(extra), 1, ++ 500 * USEC_PER_MSEC); ++ if (err) { ++ dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n"); ++ return; ++ } ++ ++ extra = 0x1 << 16 | /* tune clock stop en */ ++ 0x2 << 17 | /* pre-change delay */ ++ 0x3 << 19; /* post-change delay */ ++ sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); ++ ++ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 || ++ host->mmc->ios.timing == MMC_TIMING_MMC_HS400) ++ txclk_tapnum = priv->txclk_tapnum; ++ ++ extra = DWCMSHC_EMMC_DLL_DLYENA | ++ DLL_TXCLK_TAPNUM_FROM_SW | ++ txclk_tapnum; ++ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); ++ ++ extra = DWCMSHC_EMMC_DLL_DLYENA | ++ DLL_STRBIN_TAPNUM_DEFAULT | ++ DLL_STRBIN_TAPNUM_FROM_SW; ++ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); ++} ++ + static const struct sdhci_ops sdhci_dwcmshc_ops = { + .set_clock = sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, +@@ -109,21 +253,93 @@ static const struct sdhci_ops sdhci_dwcmshc_ops = { + .adma_write_desc = dwcmshc_adma_write_desc, + }; + ++static const struct sdhci_ops sdhci_dwcmshc_rk3568_ops = { ++ .set_clock = dwcmshc_rk3568_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .set_uhs_signaling = dwcmshc_set_uhs_signaling, ++ .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .reset = sdhci_reset, ++ .adma_write_desc = dwcmshc_adma_write_desc, ++}; ++ + static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { + .ops = &sdhci_dwcmshc_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, + }; + ++static const struct sdhci_pltfm_data sdhci_dwcmshc_rk3568_pdata = { ++ .ops = &sdhci_dwcmshc_rk3568_ops, ++ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | ++ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, ++}; ++ ++static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) ++{ ++ int err; ++ struct rk3568_priv *priv = dwc_priv->priv; ++ ++ priv->rockchip_clks[0].id = "axi"; ++ priv->rockchip_clks[1].id = "block"; ++ priv->rockchip_clks[2].id = "timer"; ++ err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK3568_MAX_CLKS, ++ priv->rockchip_clks); ++ if (err) { ++ dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err); ++ return err; ++ } ++ ++ err = clk_bulk_prepare_enable(RK3568_MAX_CLKS, priv->rockchip_clks); ++ if (err) { ++ dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err); ++ return err; ++ } ++ ++ if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum", ++ &priv->txclk_tapnum)) ++ priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; ++ ++ /* Disable cmd conflict check */ ++ sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3); ++ /* Reset previous settings */ ++ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); ++ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN); ++ ++ return 0; ++} ++ ++static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { ++ { ++ .compatible = "rockchip,rk3568-dwcmshc", ++ .data = &sdhci_dwcmshc_rk3568_pdata, ++ }, ++ { ++ .compatible = "snps,dwcmshc-sdhci", ++ .data = &sdhci_dwcmshc_pdata, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); ++ + static int dwcmshc_probe(struct platform_device *pdev) + { + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_host *host; + struct dwcmshc_priv *priv; ++ struct rk3568_priv *rk_priv = NULL; ++ const struct sdhci_pltfm_data *pltfm_data; + int err; + u32 extra; + +- host = sdhci_pltfm_init(pdev, &sdhci_dwcmshc_pdata, ++ pltfm_data = of_device_get_match_data(&pdev->dev); ++ if (!pltfm_data) { ++ dev_err(&pdev->dev, "Error: No device match data found\n"); ++ return -ENODEV; ++ } ++ ++ host = sdhci_pltfm_init(pdev, pltfm_data, + sizeof(struct dwcmshc_priv)); + if (IS_ERR(host)) + return PTR_ERR(host); +@@ -159,7 +375,23 @@ static int dwcmshc_probe(struct platform_device *pdev) + + sdhci_get_of_property(pdev); + ++ priv->vendor_specific_area1 = ++ sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK; ++ + host->mmc_host_ops.request = dwcmshc_request; ++ host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe; ++ ++ if (pltfm_data == &sdhci_dwcmshc_rk3568_pdata) { ++ rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk3568_priv), GFP_KERNEL); ++ if (!rk_priv) ++ goto err_clk; ++ ++ priv->priv = rk_priv; ++ ++ err = dwcmshc_rk3568_init(host, priv); ++ if (err) ++ goto err_clk; ++ } + + err = sdhci_add_host(host); + if (err) +@@ -170,6 +402,9 @@ static int dwcmshc_probe(struct platform_device *pdev) + err_clk: + clk_disable_unprepare(pltfm_host->clk); + clk_disable_unprepare(priv->bus_clk); ++ if (rk_priv) ++ clk_bulk_disable_unprepare(RK3568_MAX_CLKS, ++ rk_priv->rockchip_clks); + free_pltfm: + sdhci_pltfm_free(pdev); + return err; +@@ -180,12 +415,15 @@ static int dwcmshc_remove(struct platform_device *pdev) + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ struct rk3568_priv *rk_priv = priv->priv; + + sdhci_remove_host(host, 0); + + clk_disable_unprepare(pltfm_host->clk); + clk_disable_unprepare(priv->bus_clk); +- ++ if (rk_priv) ++ clk_bulk_disable_unprepare(RK3568_MAX_CLKS, ++ rk_priv->rockchip_clks); + sdhci_pltfm_free(pdev); + + return 0; +@@ -197,6 +435,7 @@ static int dwcmshc_suspend(struct device *dev) + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ struct rk3568_priv *rk_priv = priv->priv; + int ret; + + ret = sdhci_suspend_host(host); +@@ -207,6 +446,10 @@ static int dwcmshc_suspend(struct device *dev) + if (!IS_ERR(priv->bus_clk)) + clk_disable_unprepare(priv->bus_clk); + ++ if (rk_priv) ++ clk_bulk_disable_unprepare(RK3568_MAX_CLKS, ++ rk_priv->rockchip_clks); ++ + return ret; + } + +@@ -215,6 +458,7 @@ static int dwcmshc_resume(struct device *dev) + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ struct rk3568_priv *rk_priv = priv->priv; + int ret; + + ret = clk_prepare_enable(pltfm_host->clk); +@@ -227,18 +471,19 @@ static int dwcmshc_resume(struct device *dev) + return ret; + } + ++ if (rk_priv) { ++ ret = clk_bulk_prepare_enable(RK3568_MAX_CLKS, ++ rk_priv->rockchip_clks); ++ if (ret) ++ return ret; ++ } ++ + return sdhci_resume_host(host); + } + #endif + + static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume); + +-static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { +- { .compatible = "snps,dwcmshc-sdhci" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); +- + static struct platform_driver sdhci_dwcmshc_driver = { + .driver = { + .name = "sdhci-dwcmshc", +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0252-mmc-sdhci-of-dwcmshc-add-ACPI-support-for-BlueField-.patch b/platform/mellanox/non-upstream-patches/patches/0252-mmc-sdhci-of-dwcmshc-add-ACPI-support-for-BlueField-.patch new file mode 100644 index 0000000000..e6d3107e84 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0252-mmc-sdhci-of-dwcmshc-add-ACPI-support-for-BlueField-.patch @@ -0,0 +1,130 @@ +From 44448fdaef6bbd1b1fd42e41b072d4960d163708 Mon Sep 17 00:00:00 2001 +From: Liming Sun +Date: Mon, 22 Mar 2021 18:46:51 -0400 +Subject: [PATCH backport 5.10 54/63] mmc: sdhci-of-dwcmshc: add ACPI support + for BlueField-3 SoC + +This commit adds ACPI support in the sdhci-of-dwcmshc driver for +BlueField-3 SoC. It has changes to only use the clock hierarchy +for Deviec Tree since the clk is not supported by ACPI. Instead, +ACPI can define 'clock-frequency' which is parsed by existing +sdhci_get_property(). This clock value will be returned in function +dwcmshc_get_max_clock(). + +Signed-off-by: Liming Sun +Reviewed-by: Khalil Blaiech +Link: https://lore.kernel.org/r/1616453211-275165-1-git-send-email-limings@nvidia.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 50 +++++++++++++++++++++-------- + 1 file changed, 36 insertions(+), 14 deletions(-) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index 06873686d..1113a56fe 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -7,6 +7,7 @@ + * Author: Jisheng Zhang + */ + ++#include + #include + #include + #include +@@ -94,6 +95,16 @@ static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc, + sdhci_adma_write_desc(host, desc, addr, len, cmd); + } + ++static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ ++ if (pltfm_host->clk) ++ return sdhci_pltfm_clk_get_max_clock(host); ++ else ++ return pltfm_host->clock; ++} ++ + static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc, + struct mmc_request *mrq) + { +@@ -248,7 +259,7 @@ static const struct sdhci_ops sdhci_dwcmshc_ops = { + .set_clock = sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, +- .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .get_max_clock = dwcmshc_get_max_clock, + .reset = sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, + }; +@@ -323,8 +334,16 @@ static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + }; + MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); + ++#ifdef CONFIG_ACPI ++static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = { ++ { .id = "MLNXBF30" }, ++ {} ++}; ++#endif ++ + static int dwcmshc_probe(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_host *host; + struct dwcmshc_priv *priv; +@@ -347,7 +366,7 @@ static int dwcmshc_probe(struct platform_device *pdev) + /* + * extra adma table cnt for cross 128M boundary handling. + */ +- extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M); ++ extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M); + if (extra > SDHCI_MAX_SEGS) + extra = SDHCI_MAX_SEGS; + host->adma_table_cnt += extra; +@@ -355,19 +374,21 @@ static int dwcmshc_probe(struct platform_device *pdev) + pltfm_host = sdhci_priv(host); + priv = sdhci_pltfm_priv(pltfm_host); + +- pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); +- if (IS_ERR(pltfm_host->clk)) { +- err = PTR_ERR(pltfm_host->clk); +- dev_err(&pdev->dev, "failed to get core clk: %d\n", err); +- goto free_pltfm; +- } +- err = clk_prepare_enable(pltfm_host->clk); +- if (err) +- goto free_pltfm; ++ if (dev->of_node) { ++ pltfm_host->clk = devm_clk_get(dev, "core"); ++ if (IS_ERR(pltfm_host->clk)) { ++ err = PTR_ERR(pltfm_host->clk); ++ dev_err(dev, "failed to get core clk: %d\n", err); ++ goto free_pltfm; ++ } ++ err = clk_prepare_enable(pltfm_host->clk); ++ if (err) ++ goto free_pltfm; + +- priv->bus_clk = devm_clk_get(&pdev->dev, "bus"); +- if (!IS_ERR(priv->bus_clk)) +- clk_prepare_enable(priv->bus_clk); ++ priv->bus_clk = devm_clk_get(dev, "bus"); ++ if (!IS_ERR(priv->bus_clk)) ++ clk_prepare_enable(priv->bus_clk); ++ } + + err = mmc_of_parse(host->mmc); + if (err) +@@ -489,6 +510,7 @@ static struct platform_driver sdhci_dwcmshc_driver = { + .name = "sdhci-dwcmshc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .of_match_table = sdhci_dwcmshc_dt_ids, ++ .acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids), + .pm = &dwcmshc_pmops, + }, + .probe = dwcmshc_probe, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0253-mmc-sdhci-of-dwcmshc-fix-error-return-code-in-dwcmsh.patch b/platform/mellanox/non-upstream-patches/patches/0253-mmc-sdhci-of-dwcmshc-fix-error-return-code-in-dwcmsh.patch new file mode 100644 index 0000000000..7f49a35cc8 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0253-mmc-sdhci-of-dwcmshc-fix-error-return-code-in-dwcmsh.patch @@ -0,0 +1,37 @@ +From 72d369a9be4bc4b92ab1e006dc36c612f0305b46 Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Tue, 23 Mar 2021 11:29:56 +0000 +Subject: [PATCH backport 5.10 55/63] mmc: sdhci-of-dwcmshc: fix error return + code in dwcmshc_probe() + +Fix to return negative error code -ENOMEM from the error handling +case instead of 0, as done elsewhere in this function. + +Fixes: c2c4da37837e ("mmc: sdhci-of-dwcmshc: add rockchip platform support") +Reported-by: Hulk Robot +Signed-off-by: Wei Yongjun +Link: https://lore.kernel.org/r/20210323112956.1016884-1-weiyongjun1@huawei.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index 1113a56fe..34d26e388 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -404,8 +404,10 @@ static int dwcmshc_probe(struct platform_device *pdev) + + if (pltfm_data == &sdhci_dwcmshc_rk3568_pdata) { + rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk3568_priv), GFP_KERNEL); +- if (!rk_priv) ++ if (!rk_priv) { ++ err = -ENOMEM; + goto err_clk; ++ } + + priv->priv = rk_priv; + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0254-mmc-sdhci-of-dwcmshc-set-MMC_CAP_WAIT_WHILE_BUSY.patch b/platform/mellanox/non-upstream-patches/patches/0254-mmc-sdhci-of-dwcmshc-set-MMC_CAP_WAIT_WHILE_BUSY.patch new file mode 100644 index 0000000000..04b8970ebb --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0254-mmc-sdhci-of-dwcmshc-set-MMC_CAP_WAIT_WHILE_BUSY.patch @@ -0,0 +1,32 @@ +From 17e98239da6fd921a76cbee7ac8dcc3c437ad5d6 Mon Sep 17 00:00:00 2001 +From: Jisheng Zhang +Date: Wed, 24 Mar 2021 15:47:21 +0800 +Subject: [PATCH backport 5.10 56/63] mmc: sdhci-of-dwcmshc: set + MMC_CAP_WAIT_WHILE_BUSY + +The host supports HW busy detection of the device busy signaling over +dat0 line. Set MMC_CAP_wAIT_WHILE_BUSY host capability. + +Signed-off-by: Jisheng Zhang +Link: https://lore.kernel.org/r/20210324154703.69f97fde@xhacker.debian +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index 34d26e388..bac874ab0 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -416,6 +416,8 @@ static int dwcmshc_probe(struct platform_device *pdev) + goto err_clk; + } + ++ host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; ++ + err = sdhci_add_host(host); + if (err) + goto err_clk; +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0255-mmc-sdhci-of-dwcmshc-Re-enable-support-for-the-BlueF.patch b/platform/mellanox/non-upstream-patches/patches/0255-mmc-sdhci-of-dwcmshc-Re-enable-support-for-the-BlueF.patch new file mode 100644 index 0000000000..6f5e690511 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0255-mmc-sdhci-of-dwcmshc-Re-enable-support-for-the-BlueF.patch @@ -0,0 +1,77 @@ +From 990bb46dc1f0fd103e9d01d8e87c046fbe879d53 Mon Sep 17 00:00:00 2001 +From: Liming Sun +Date: Tue, 9 Aug 2022 13:37:42 -0400 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: Re-enable support for the BlueField-3 + SoC +X-NVConfidentiality: public + +BugLink: https://bugs.launchpad.net/bugs/1991831 + +[ Upstream commit a0753ef66c34c1739580219dca664eda648164b7 ] + +The commit 08f3dff799d4 (mmc: sdhci-of-dwcmshc: add rockchip platform +support") introduces the use of_device_get_match_data() to check for some +chips. Unfortunately, it also breaks the BlueField-3 FW, which uses ACPI. + +To fix the problem, let's add the ACPI match data and the corresponding +quirks to re-enable the support for the BlueField-3 SoC. + +Reviewed-by: David Woods +Signed-off-by: Liming Sun +Acked-by: Adrian Hunter +Fixes: 08f3dff799d4 ("mmc: sdhci-of-dwcmshc: add rockchip platform support") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20220809173742.178440-1-limings@nvidia.com +[Ulf: Clarified the commit message a bit] +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +Signed-off-by: Kamal Mostafa +Signed-off-by: Stefan Bader +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index bac874ab0..a0c73ddaa 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -279,6 +279,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, + }; + ++#ifdef CONFIG_ACPI ++static const struct sdhci_pltfm_data sdhci_dwcmshc_bf3_pdata = { ++ .ops = &sdhci_dwcmshc_ops, ++ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_ACMD23_BROKEN, ++}; ++#endif ++ + static const struct sdhci_pltfm_data sdhci_dwcmshc_rk3568_pdata = { + .ops = &sdhci_dwcmshc_rk3568_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | +@@ -336,7 +345,10 @@ MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); + + #ifdef CONFIG_ACPI + static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = { +- { .id = "MLNXBF30" }, ++ { ++ .id = "MLNXBF30", ++ .driver_data = (kernel_ulong_t)&sdhci_dwcmshc_bf3_pdata, ++ }, + {} + }; + #endif +@@ -352,7 +364,7 @@ static int dwcmshc_probe(struct platform_device *pdev) + int err; + u32 extra; + +- pltfm_data = of_device_get_match_data(&pdev->dev); ++ pltfm_data = device_get_match_data(&pdev->dev); + if (!pltfm_data) { + dev_err(&pdev->dev, "Error: No device match data found\n"); + return -ENODEV; +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0256-UBUNTU-SAUCE-Support-BlueField-3-GPIO-driver.patch b/platform/mellanox/non-upstream-patches/patches/0256-UBUNTU-SAUCE-Support-BlueField-3-GPIO-driver.patch new file mode 100644 index 0000000000..976dadb851 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0256-UBUNTU-SAUCE-Support-BlueField-3-GPIO-driver.patch @@ -0,0 +1,402 @@ +From a97cbefdc2d699a53b9717f4c11aadba176b7987 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Thu, 27 Oct 2022 12:36:19 -0400 +Subject: [PATCH 02/12] UBUNTU: SAUCE: Support BlueField-3 GPIO driver +X-NVConfidentiality: public + +BugLink: https://bugs.launchpad.net/bugs/1994897 + +This patch adds support for the BlueField-3 SoC GPIO driver which allows: +- setting certain GPIOs as interrupts from other dependent drivers +- ability to manipulate certain GPIO values from user space + +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Cory Todd +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/gpio/Kconfig | 7 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-mlxbf3.c | 340 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 348 insertions(+) + create mode 100644 drivers/gpio/gpio-mlxbf3.c + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index d1300fc00..bf1b2b787 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1459,6 +1459,13 @@ config GPIO_MLXBF2 + help + Say Y here if you want GPIO support on Mellanox BlueField 2 SoC. + ++config GPIO_MLXBF3 ++ tristate "Mellanox BlueField 3 SoC GPIO" ++ depends on (MELLANOX_PLATFORM && ARM64 && ACPI) || (64BIT && COMPILE_TEST) ++ select GPIO_GENERIC ++ help ++ Say Y here if you want GPIO support on Mellanox BlueField 3 SoC. ++ + config GPIO_ML_IOH + tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" + depends on X86 || COMPILE_TEST +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index 09dada80a..f11a9cf0b 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -96,6 +96,7 @@ obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o + obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o + obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o + obj-$(CONFIG_GPIO_MLXBF2) += gpio-mlxbf2.o ++obj-$(CONFIG_GPIO_MLXBF3) += gpio-mlxbf3.o + obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o + obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o + obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o +diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c +new file mode 100644 +index 000000000..45f0946ac +--- /dev/null ++++ b/drivers/gpio/gpio-mlxbf3.c +@@ -0,0 +1,340 @@ ++// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause ++ ++/* ++ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_VERSION "1.0" ++ ++/* ++ * There are 2 YU GPIO blocks: ++ * gpio[0]: HOST_GPIO0->HOST_GPIO31 ++ * gpio[1]: HOST_GPIO32->HOST_GPIO55 ++ */ ++#define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 ++ ++/* ++ * fw_gpio[x] block registers and their offset ++ */ ++#define YU_GPIO_FW_CONTROL_SET 0x00 ++#define YU_GPIO_FW_OUTPUT_ENABLE_SET 0x04 ++#define YU_GPIO_FW_DATA_OUT_SET 0x08 ++#define YU_GPIO_FW_CONTROL_CLEAR 0x14 ++#define YU_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x18 ++#define YU_GPIO_FW_DATA_OUT_CLEAR 0x1c ++#define YU_GPIO_CAUSE_RISE_EN 0x28 ++#define YU_GPIO_CAUSE_FALL_EN 0x2c ++#define YU_GPIO_READ_DATA_IN 0x30 ++#define YU_GPIO_READ_OUTPUT_ENABLE 0x34 ++#define YU_GPIO_READ_DATA_OUT 0x38 ++#define YU_GPIO_READ_FW_CONTROL 0x44 ++ ++#define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00 ++#define YU_GPIO_CAUSE_OR_EVTEN0 0x14 ++#define YU_GPIO_CAUSE_OR_CLRCAUSE 0x18 ++ ++/* BlueField-3 gpio block context structure. */ ++struct mlxbf3_gpio_context { ++ struct gpio_chip gc; ++ struct irq_chip irq_chip; ++ ++ /* YU GPIO blocks address */ ++ void __iomem *gpio_io; ++ ++ /* YU GPIO cause block address */ ++ void __iomem *gpio_cause_io; ++ ++ uint32_t ctrl_gpio_mask; ++}; ++ ++static void mlxbf3_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) ++{ ++ struct mlxbf3_gpio_context *gs = gpiochip_get_data(chip); ++ ++ /* Software can only control GPIO pins defined by ctrl_gpio_mask */ ++ if (!(BIT(offset) & gs->ctrl_gpio_mask)) ++ return; ++ ++ if (val) { ++ writel(BIT(offset), gs->gpio_io + YU_GPIO_FW_DATA_OUT_SET); ++ } else { ++ writel(BIT(offset), gs->gpio_io + YU_GPIO_FW_DATA_OUT_CLEAR); ++ } ++ ++ wmb(); ++ ++ /* This needs to be done last to avoid glitches */ ++ writel(BIT(offset), gs->gpio_io + YU_GPIO_FW_CONTROL_SET); ++} ++ ++static int mlxbf3_gpio_direction_input(struct gpio_chip *chip, ++ unsigned int offset) ++{ ++ struct mlxbf3_gpio_context *gs = gpiochip_get_data(chip); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ ++ writel(BIT(offset), gs->gpio_io + YU_GPIO_FW_OUTPUT_ENABLE_CLEAR); ++ writel(BIT(offset), gs->gpio_io + YU_GPIO_FW_CONTROL_CLEAR); ++ ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++ ++ return 0; ++} ++ ++static int mlxbf3_gpio_direction_output(struct gpio_chip *chip, ++ unsigned int offset, ++ int value) ++{ ++ struct mlxbf3_gpio_context *gs = gpiochip_get_data(chip); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ ++ writel(BIT(offset), gs->gpio_io + YU_GPIO_FW_OUTPUT_ENABLE_SET); ++ ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++ ++ return 0; ++} ++ ++static void mlxbf3_gpio_irq_enable(struct irq_data *irqd) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); ++ struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); ++ int offset = irqd_to_hwirq(irqd); ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ writel(BIT(offset), gs->gpio_cause_io + YU_GPIO_CAUSE_OR_CLRCAUSE); ++ ++ val = readl(gs->gpio_cause_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ val |= BIT(offset); ++ writel(val, gs->gpio_cause_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++} ++ ++static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); ++ struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); ++ int offset = irqd_to_hwirq(irqd); ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ val = readl(gs->gpio_cause_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ val &= ~BIT(offset); ++ writel(val, gs->gpio_cause_io + YU_GPIO_CAUSE_OR_EVTEN0); ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++} ++ ++static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr) ++{ ++ struct mlxbf3_gpio_context *gs = ptr; ++ struct gpio_chip *gc = &gs->gc; ++ unsigned long pending; ++ u32 level; ++ ++ pending = readl(gs->gpio_cause_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0); ++ writel(pending, gs->gpio_cause_io + YU_GPIO_CAUSE_OR_CLRCAUSE); ++ ++ for_each_set_bit(level, &pending, gc->ngpio) { ++ int gpio_irq = irq_find_mapping(gc->irq.domain, level); ++ generic_handle_irq(gpio_irq); ++ } ++ ++ return IRQ_RETVAL(pending); ++} ++ ++static int ++mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); ++ struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); ++ int offset = irqd_to_hwirq(irqd); ++ unsigned long flags; ++ bool fall = false; ++ bool rise = false; ++ u32 val; ++ ++ switch (type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_BOTH: ++ fall = true; ++ rise = true; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ rise = true; ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ fall = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&gs->gc.bgpio_lock, flags); ++ if (fall) { ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); ++ val |= BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); ++ } ++ ++ if (rise) { ++ val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); ++ val |= BIT(offset); ++ writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); ++ } ++ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); ++ ++ return 0; ++} ++ ++/* BlueField-3 GPIO driver initialization routine. */ ++static int ++mlxbf3_gpio_probe(struct platform_device *pdev) ++{ ++ struct mlxbf3_gpio_context *gs; ++ struct device *dev = &pdev->dev; ++ struct gpio_irq_chip *girq; ++ struct gpio_chip *gc; ++ unsigned int npins; ++ const char *name; ++ int ret, irq; ++ ++ name = dev_name(dev); ++ ++ gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); ++ if (!gs) ++ return -ENOMEM; ++ ++ /* YU GPIO block address */ ++ gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(gs->gpio_io)) ++ return PTR_ERR(gs->gpio_io); ++ ++ /* YU GPIO block address */ ++ gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(gs->gpio_cause_io)) ++ return PTR_ERR(gs->gpio_cause_io); ++ ++ if (device_property_read_u32(dev, "npins", &npins)) ++ npins = MLXBF3_GPIO_MAX_PINS_PER_BLOCK; ++ ++ if (device_property_read_u32(dev, "ctrl_gpio_mask", &gs->ctrl_gpio_mask)) ++ gs->ctrl_gpio_mask = 0x0; ++ ++ gc = &gs->gc; ++ ++ /* To set the direction to input, just give control to HW by setting ++ * YU_GPIO_FW_CONTROL_CLEAR. ++ * If the GPIO is controlled by HW, read its value via read_data_in register. ++ * ++ * When the direction = output, the GPIO is controlled by SW and ++ * datain=dataout. If software modifies the value of the GPIO pin, ++ * the value can be read from read_data_in without changing the direction. ++ */ ++ ret = bgpio_init(gc, dev, 4, ++ gs->gpio_io + YU_GPIO_READ_DATA_IN, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ 0); ++ ++ gc->set = mlxbf3_gpio_set; ++ gc->direction_input = mlxbf3_gpio_direction_input; ++ gc->direction_output = mlxbf3_gpio_direction_output; ++ ++ gc->ngpio = npins; ++ gc->owner = THIS_MODULE; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq >= 0) { ++ gs->irq_chip.name = name; ++ gs->irq_chip.irq_set_type = mlxbf3_gpio_irq_set_type; ++ gs->irq_chip.irq_enable = mlxbf3_gpio_irq_enable; ++ gs->irq_chip.irq_disable = mlxbf3_gpio_irq_disable; ++ ++ girq = &gs->gc.irq; ++ girq->chip = &gs->irq_chip; ++ girq->handler = handle_simple_irq; ++ girq->default_type = IRQ_TYPE_NONE; ++ /* This will let us handle the parent IRQ in the driver */ ++ girq->num_parents = 0; ++ girq->parents = NULL; ++ girq->parent_handler = NULL; ++ ++ /* ++ * Directly request the irq here instead of passing ++ * a flow-handler because the irq is shared. ++ */ ++ ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler, ++ IRQF_SHARED, name, gs); ++ if (ret) { ++ dev_err(dev, "failed to request IRQ"); ++ return ret; ++ } ++ } ++ ++ platform_set_drvdata(pdev, gs); ++ ++ ret = devm_gpiochip_add_data(dev, &gs->gc, gs); ++ if (ret) { ++ dev_err(dev, "Failed adding memory mapped gpiochip\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mlxbf3_gpio_remove(struct platform_device *pdev) ++{ ++ struct mlxbf3_gpio_context *gs = platform_get_drvdata(pdev); ++ ++ /* Set the GPIO control back to HW */ ++ writel(gs->ctrl_gpio_mask, gs->gpio_io + YU_GPIO_FW_CONTROL_CLEAR); ++ ++ return 0; ++} ++ ++static const struct acpi_device_id __maybe_unused mlxbf3_gpio_acpi_match[] = { ++ { "MLNXBF33", 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match); ++ ++static struct platform_driver mlxbf3_gpio_driver = { ++ .driver = { ++ .name = "mlxbf3_gpio", ++ .acpi_match_table = mlxbf3_gpio_acpi_match, ++ }, ++ .probe = mlxbf3_gpio_probe, ++ .remove = mlxbf3_gpio_remove, ++}; ++ ++module_platform_driver(mlxbf3_gpio_driver); ++ ++MODULE_DESCRIPTION("Mellanox BlueField-3 GPIO Driver"); ++MODULE_AUTHOR("Asmaa Mnebhi "); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(DRV_VERSION); +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0257-regmap-debugfs-Enable-writing-to-the-regmap-debugfs-.patch b/platform/mellanox/non-upstream-patches/patches/0257-regmap-debugfs-Enable-writing-to-the-regmap-debugfs-.patch new file mode 100644 index 0000000000..53813dbaf5 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0257-regmap-debugfs-Enable-writing-to-the-regmap-debugfs-.patch @@ -0,0 +1,27 @@ +From 5a6717305bc0ee08d08dc27f8f3415c4bb1c34c3 Mon Sep 17 00:00:00 2001 +From: Felix Radensky +Date: Sun, 20 Nov 2022 15:25:58 +0200 +Subject: [PATCH backport 5.10 59/63] regmap: debugfs: Enable writing to the + regmap debugfs registers + +Signed-off-by: Felix Radensky +--- + drivers/base/regmap/regmap-debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c +index 211a335a6..ee3cccaf5 100644 +--- a/drivers/base/regmap/regmap-debugfs.c ++++ b/drivers/base/regmap/regmap-debugfs.c +@@ -290,7 +290,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf, + count, ppos); + } + +-#undef REGMAP_ALLOW_WRITE_DEBUGFS ++#define REGMAP_ALLOW_WRITE_DEBUGFS + #ifdef REGMAP_ALLOW_WRITE_DEBUGFS + /* + * This can be dangerous especially when we have clients such as +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0258-UBUNTU-SAUCE-mlx-bootctl-support-icm-carveout-eeprom.patch b/platform/mellanox/non-upstream-patches/patches/0258-UBUNTU-SAUCE-mlx-bootctl-support-icm-carveout-eeprom.patch new file mode 100644 index 0000000000..6448866c0e --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0258-UBUNTU-SAUCE-mlx-bootctl-support-icm-carveout-eeprom.patch @@ -0,0 +1,118 @@ +From 02aa895d298c83e5e6e0f6e64f04895e50235a33 Mon Sep 17 00:00:00 2001 +From: Asmaa Mnebhi +Date: Mon, 31 Oct 2022 12:18:52 -0400 +Subject: [PATCH backport 5.10 60/63] UBUNTU: SAUCE: mlx-bootctl: support icm + carveout eeprom region read/write + +BugLink: https://bugs.launchpad.net/bugs/1995296 + +The BlueField-3 ICM carveout feature will enable NIC FW to bypass the SMMU block +to access DRAM memory. The amount of memory accessible by FW will be controlled by ARM. +This patch enables setting the size of the large ICM carveout from +userspace. The max size is 1TB, has a granularity of 128MB and will be passed +and printed in hex. The size unit is MB. + +Signed-off-by: Asmaa Mnebhi +Acked-by: Tim Gardner +Acked-by: Cory Todd +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/platform/mellanox/mlxbf-bootctl.c | 40 +++++++++++++++++++++++ + drivers/platform/mellanox/mlxbf-bootctl.h | 9 +++++ + 2 files changed, 49 insertions(+) + +diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c +index 2302e1e09..e8877a19d 100644 +--- a/drivers/platform/mellanox/mlxbf-bootctl.c ++++ b/drivers/platform/mellanox/mlxbf-bootctl.c +@@ -104,6 +104,7 @@ enum { + + /* This mutex is used to serialize MFG write and lock operations. */ + static DEFINE_MUTEX(mfg_ops_lock); ++static DEFINE_MUTEX(icm_ops_lock); + + #define MLNX_MFG_OOB_MAC_LEN ETH_ALEN + #define MLNX_MFG_OPN_VAL_LEN 24 +@@ -383,6 +384,43 @@ static ssize_t oob_mac_store(struct device_driver *drv, const char *buf, + return res.a0 ? -EPERM : count; + } + ++static ssize_t large_icm_show(struct device_driver *drv, char *buf) ++{ ++ char icm_str[MAX_ICM_BUFFER_SIZE] = { 0 }; ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(MLNX_HANDLE_GET_ICM_INFO, 0, 0, 0, 0, ++ 0, 0, 0, &res); ++ if (res.a0) ++ return -EPERM; ++ ++ sprintf(icm_str, "0x%lx", res.a1); ++ ++ return snprintf(buf, sizeof(icm_str), "%s", icm_str); ++} ++ ++static ssize_t large_icm_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ struct arm_smccc_res res; ++ unsigned long icm_data; ++ int err; ++ ++ err = kstrtoul(buf, 16, &icm_data); ++ if (err) ++ return err; ++ ++ if (((icm_data != 0) && (icm_data < 0x80)) || ++ (icm_data > 0x100000) || (icm_data % 128)) ++ return -EPERM; ++ ++ mutex_lock(&icm_ops_lock); ++ arm_smccc_smc(MLNX_HANDLE_SET_ICM_INFO, icm_data, 0, 0, 0, 0, 0, 0, &res); ++ mutex_unlock(&icm_ops_lock); ++ ++ return res.a0 ? -EPERM : count; ++} ++ + static ssize_t opn_show(struct device_driver *drv, char *buf) + { + u64 opn_data[MLNX_MFG_VAL_QWORD_CNT(OPN)] = { 0 }; +@@ -1170,6 +1208,7 @@ static DRIVER_ATTR_RW(uuid); + static DRIVER_ATTR_RW(rev); + static DRIVER_ATTR_WO(mfg_lock); + static DRIVER_ATTR_RW(rsh_log); ++static DRIVER_ATTR_RW(large_icm); + + static struct attribute *mbc_dev_attrs[] = { + &driver_attr_post_reset_wdog.attr, +@@ -1187,6 +1226,7 @@ static struct attribute *mbc_dev_attrs[] = { + &driver_attr_rev.attr, + &driver_attr_mfg_lock.attr, + &driver_attr_rsh_log.attr, ++ &driver_attr_large_icm.attr, + NULL + }; + +diff --git a/drivers/platform/mellanox/mlxbf-bootctl.h b/drivers/platform/mellanox/mlxbf-bootctl.h +index 3e9dda829..c70204770 100644 +--- a/drivers/platform/mellanox/mlxbf-bootctl.h ++++ b/drivers/platform/mellanox/mlxbf-bootctl.h +@@ -95,6 +95,15 @@ + #define MLNX_HANDLE_GET_MFG_INFO 0x8200000F + #define MLNX_HANDLE_LOCK_MFG_INFO 0x82000011 + ++/* ++ * SMC function IDs to set and get the large ICM carveout size ++ * stored in the eeprom. ++ */ ++#define MLNX_HANDLE_SET_ICM_INFO 0x82000012 ++#define MLNX_HANDLE_GET_ICM_INFO 0x82000013 ++ ++#define MAX_ICM_BUFFER_SIZE 10 ++ + /* SMC function IDs for SiP Service queries */ + #define MLNX_SIP_SVC_CALL_COUNT 0x8200ff00 + #define MLNX_SIP_SVC_UID 0x8200ff01 +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0259-mmc-sdhci-of-dwcmshc-Enable-host-V4-support-for-Blue.patch b/platform/mellanox/non-upstream-patches/patches/0259-mmc-sdhci-of-dwcmshc-Enable-host-V4-support-for-Blue.patch new file mode 100644 index 0000000000..34103898d3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0259-mmc-sdhci-of-dwcmshc-Enable-host-V4-support-for-Blue.patch @@ -0,0 +1,35 @@ +From 8650b784688c0822951993d98f196e1c7689a5cc Mon Sep 17 00:00:00 2001 +From: Liming Sun +Date: Fri, 25 Nov 2022 22:29:23 -0500 +Subject: [PATCH backport 5.10 61/63] mmc: sdhci-of-dwcmshc: Enable host V4 + support for BlueField-3 SoC + +This commit enables SDHCI Host V4 support on Bluefield-3 SoC to be +consistent with UEFI setting. + +Change-Id: I4d5ea43ca5f36c6c642443b9335c321924cca2ed +Signed-off-by: Liming Sun +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index 173a9167a..ea972bd3c 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -426,6 +426,12 @@ static int dwcmshc_probe(struct platform_device *pdev) + goto err_clk; + } + ++#ifdef CONFIG_ACPI ++ if (pltfm_data == &sdhci_dwcmshc_bf3_pdata) { ++ sdhci_enable_v4_mode(host); ++ } ++#endif ++ + host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + + err = sdhci_add_host(host); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0260-UBUNTU-SAUCE-mlxbf-pka-Fix-kernel-crash-with-pka-TRN.patch b/platform/mellanox/non-upstream-patches/patches/0260-UBUNTU-SAUCE-mlxbf-pka-Fix-kernel-crash-with-pka-TRN.patch new file mode 100644 index 0000000000..6196e707d9 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0260-UBUNTU-SAUCE-mlxbf-pka-Fix-kernel-crash-with-pka-TRN.patch @@ -0,0 +1,67 @@ +From 9d0cd0fb6fbdf825454b3d9f9518d8b569b0cdea Mon Sep 17 00:00:00 2001 +From: Shih-Yi Chen +Date: Wed, 4 Jan 2023 10:03:06 -0500 +Subject: [PATCH backport 5.10 1/6] UBUNTU: SAUCE: mlxbf-pka: Fix kernel crash + with pka TRNG ioctl call + +BugLink: https://bugs.launchpad.net/bugs/2001564 + +Bluefield encounters kernel crash/oops when HTTPS client uses OpenSSL +with PKA engine during TLS handshake. The issue is with TRNG ioctl call. +The kernel logs show the following errors. + +Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000ffffce65d328 + +Signed-off-by: Shih-Yi Chen +Acked-by: Tim Gardner +Acked-by: Cengiz Can +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c +index b8b5a465e..9e26ccf21 100644 +--- a/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c ++++ b/drivers/platform/mellanox/mlxbf_pka/mlxbf_pka_drv.c +@@ -467,7 +467,7 @@ static long pka_drv_ring_ioctl(void *device_data, + } else if (cmd == PKA_CLEAR_RING_COUNTERS) { + return pka_dev_clear_ring_counters(ring_dev->ring); + } else if (cmd == PKA_GET_RANDOM_BYTES) { +- pka_dev_trng_info_t *trng_data; ++ pka_dev_trng_info_t trng_data; + pka_dev_shim_t *shim; + bool trng_present; + uint32_t byte_cnt; +@@ -476,12 +476,17 @@ static long pka_drv_ring_ioctl(void *device_data, + + ret = -ENOENT; + shim = ring_dev->ring->shim; +- trng_data = (pka_dev_trng_info_t *)arg; ++ ret = copy_from_user(&trng_data, (void __user *)(arg), sizeof(pka_dev_trng_info_t)); ++ if (ret) { ++ PKA_DEBUG(PKA_DRIVER, "Failed to copy user request.\n"); ++ return -EFAULT; ++ } ++ + /* + * We need byte count which is multiple of 4 as + * required by pka_dev_trng_read() interface. + */ +- byte_cnt = round_up(trng_data->count, 4); ++ byte_cnt = round_up(trng_data.count, 4); + + data = kzalloc(byte_cnt, GFP_KERNEL); + if (data == NULL) { +@@ -502,7 +507,7 @@ static long pka_drv_ring_ioctl(void *device_data, + return ret; + } + +- ret = copy_to_user((void __user *)(trng_data->data), data, trng_data->count); ++ ret = copy_to_user((void __user *)(trng_data.data), data, trng_data.count); + kfree(data); + return ret ? -EFAULT : 0; + } +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0261-mlxbf-ptm-power-and-thermal-management-debugfs-drive.patch b/platform/mellanox/non-upstream-patches/patches/0261-mlxbf-ptm-power-and-thermal-management-debugfs-drive.patch new file mode 100644 index 0000000000..a58881c4a7 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0261-mlxbf-ptm-power-and-thermal-management-debugfs-drive.patch @@ -0,0 +1,256 @@ +From 1193879b92e665c100056085385ffdb4ab2715cb Mon Sep 17 00:00:00 2001 +From: Jitendra Lanka +Date: Fri, 13 Jan 2023 15:21:02 -0500 +Subject: [PATCH backport 5.10 2/6] mlxbf-ptm: power and thermal management + debugfs driver + +mlxbf-ptm driver implements debugfs interface for Bluefield +devices power and thermal management. It provides some parameters +that can be monitored by system software. + +Change-Id: I241e1406962548cef9b33c4b3dea925e675c3c88 +Signed-off-by: Jitendra Lanka +--- + drivers/platform/mellanox/Kconfig | 10 ++ + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/mellanox/mlxbf-ptm.c | 195 ++++++++++++++++++++++++++ + 3 files changed, 206 insertions(+) + create mode 100644 drivers/platform/mellanox/mlxbf-ptm.c + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index a5231c23a..48bd61f61 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -106,6 +106,16 @@ config MLXBF_TRIO + This driver supports the TRIO PCIe root complex interface on + Mellanox BlueField SoCs. + ++config MLXBF_PTM ++ tristate "BlueField Power and Thermal Management debugfs interface" ++ depends on ARM64 ++ depends on DEBUG_FS ++ help ++ If you say yes to this option, support will be added for the ++ mlxbf-ptm driver. This driver provides debugfs interface ++ to userspace with information related to power and thermal ++ management of the Bluefield device. ++ + source "drivers/platform/mellanox/mlxbf_pka/Kconfig" + + config NVSW_SN2201 +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index 7c6393ebe..6aa0ab157 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o + obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o + obj-$(CONFIG_MLXBF_TRIO) += mlx-trio.o + obj-$(CONFIG_MLXBF_LIVEFISH) += mlxbf-livefish.o ++obj-$(CONFIG_MLXBF_PTM) += mlxbf-ptm.o + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o + obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o +diff --git a/drivers/platform/mellanox/mlxbf-ptm.c b/drivers/platform/mellanox/mlxbf-ptm.c +new file mode 100644 +index 000000000..307ba1f33 +--- /dev/null ++++ b/drivers/platform/mellanox/mlxbf-ptm.c +@@ -0,0 +1,195 @@ ++// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause ++/* ++ * Copyright (C) 2023 NVIDIA Corporation & Affiliates. ++ * ++ * Nvidia Bluefield power and thermal debugfs driver ++ * This driver provides a debugfs interface for systems management ++ * software to monitor power and thermal actions. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++/* SMC IDs */ ++#define MLNX_PTM_GET_VR0_POWER 0x82000101 ++#define MLNX_PTM_GET_VR1_POWER 0x82000102 ++#define MLNX_PTM_GET_THROTTLE_STATE 0x82000103 ++#define MLNX_PTM_GET_DDR_THLD 0x82000104 ++#define MLNX_PTM_GET_STATUS_REG 0x82000105 ++#define MLNX_PTM_GET_PTHROTTLE 0x82000106 ++#define MLNX_PTM_GET_TTHROTTLE 0x82000107 ++#define MLNX_PTM_GET_MAX_TEMP 0x82000108 ++#define MLNX_PTM_GET_PWR_EVT_CNT 0x82000109 ++#define MLNX_PTM_GET_TEMP_EVT_CNT 0x8200010A ++ ++#define MLNX_POWER_ERROR 300 ++ ++struct dentry *monitors; ++ ++static int smc_call1(unsigned int smc_op, int smc_arg) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(smc_op, smc_arg, 0, 0, 0, 0, 0, 0, &res); ++ ++ return res.a0; ++} ++ ++#define smc_call0(smc_op) smc_call1(smc_op, 0) ++ ++static int throttling_state_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_THROTTLE_STATE); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(throttling_state_fops, ++ throttling_state_show, NULL, "%llu\n"); ++ ++static int pthrottling_state_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_PTHROTTLE); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(pthrottling_state_fops, ++ pthrottling_state_show, NULL, "%llu\n"); ++ ++static int tthrottling_state_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_TTHROTTLE); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(tthrottling_state_fops, ++ tthrottling_state_show, NULL, "%llu\n"); ++ ++static int core_temp_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_MAX_TEMP); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(core_temp_fops, ++ core_temp_show, NULL, "%lld\n"); ++ ++static int pwr_evt_counter_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_PWR_EVT_CNT); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(pwr_evt_counter_fops, ++ pwr_evt_counter_show, NULL, "%llu\n"); ++ ++static int temp_evt_counter_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_TEMP_EVT_CNT); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(temp_evt_counter_fops, ++ temp_evt_counter_show, NULL, "%llu\n"); ++ ++static int vr0_power_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_VR0_POWER); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(vr0_power_fops, vr0_power_show, NULL, "%llu\n"); ++ ++static int vr1_power_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_VR1_POWER); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(vr1_power_fops, vr1_power_show, NULL, "%llu\n"); ++ ++static int total_power_show(void *data, u64 *val) ++{ ++ u64 v0, v1; ++ ++ v0 = smc_call0(MLNX_PTM_GET_VR0_POWER); ++ if (v0 > MLNX_POWER_ERROR) ++ v0 = 0; ++ v1 = smc_call0(MLNX_PTM_GET_VR1_POWER); ++ if (v1 > MLNX_POWER_ERROR) ++ v1 = 0; ++ *val = (v0 + v1); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(total_power_fops, total_power_show, NULL, "%llu\n"); ++ ++static int ddr_thld_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_DDR_THLD); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(ddr_thld_fops, ddr_thld_show, NULL, "%llu\n"); ++ ++static int error_status_show(void *data, u64 *val) ++{ ++ *val = smc_call0(MLNX_PTM_GET_STATUS_REG); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(error_status_fops, ++ error_status_show, NULL, "%llu\n"); ++ ++ ++static int __init mlxbf_ptm_init(void) ++{ ++ struct dentry *ptm_root, *status; ++ ++ ptm_root = debugfs_lookup("mlxbf-ptm", NULL); ++ if (!ptm_root) ++ ptm_root = debugfs_create_dir("mlxbf-ptm", NULL); ++ ++ monitors = debugfs_create_dir("monitors", ptm_root); ++ status = debugfs_create_dir("status", monitors); ++ ++ debugfs_create_file("vr0_power", S_IRUGO, status, NULL, ++ &vr0_power_fops); ++ debugfs_create_file("vr1_power", S_IRUGO, status, NULL, ++ &vr1_power_fops); ++ debugfs_create_file("total_power", S_IRUGO, status, NULL, ++ &total_power_fops); ++ debugfs_create_file("ddr_temp", S_IRUGO, status, ++ NULL, &ddr_thld_fops); ++ debugfs_create_file("core_temp", S_IRUGO, status, ++ NULL, &core_temp_fops); ++ debugfs_create_file("power_throttling_event_count", S_IRUGO, status, ++ NULL, &pwr_evt_counter_fops); ++ debugfs_create_file("thermal_throttling_event_count", S_IRUGO, status, ++ NULL, &temp_evt_counter_fops); ++ debugfs_create_file("throttling_state", S_IRUGO, status, ++ NULL, &throttling_state_fops); ++ debugfs_create_file("power_throttling_state", S_IRUGO, status, ++ NULL, &pthrottling_state_fops); ++ debugfs_create_file("thermal_throttling_state", S_IRUGO, status, ++ NULL, &tthrottling_state_fops); ++ debugfs_create_file("error_state", S_IRUGO, status, ++ NULL, &error_status_fops); ++ ++ return 0; ++} ++ ++static void __exit mlxbf_ptm_exit(void) ++{ ++ debugfs_remove_recursive(monitors); ++} ++ ++module_init(mlxbf_ptm_init); ++module_exit(mlxbf_ptm_exit); ++ ++MODULE_AUTHOR("Jitendra Lanka "); ++MODULE_DESCRIPTION("Nvidia Bluefield power and thermal debugfs driver"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION("1.0"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0262-UBUNTU-SAUCE-mlxbf-pmc-Fix-event-string-typo.patch b/platform/mellanox/non-upstream-patches/patches/0262-UBUNTU-SAUCE-mlxbf-pmc-Fix-event-string-typo.patch new file mode 100644 index 0000000000..21783e2730 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0262-UBUNTU-SAUCE-mlxbf-pmc-Fix-event-string-typo.patch @@ -0,0 +1,36 @@ +From 127bcf5d9412ee246b6620d9b38b7fca6fe4d66d Mon Sep 17 00:00:00 2001 +From: James Hurley +Date: Tue, 6 Dec 2022 11:31:55 -0500 +Subject: [PATCH backport 5.10 3/6] UBUNTU: SAUCE: mlxbf-pmc: Fix event string + typo + +BugLink: https://bugs.launchpad.net/bugs/1998863 + +Fix event string typo so that the proper events are displayed. + +Signed-off-by: James hurley +Reviewed-by: David Thompson +Signed-off-by: James hurley +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/platform/mellanox/mlxbf-pmc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.h b/drivers/platform/mellanox/mlxbf-pmc.h +index 894c3cc88..a6f7aade4 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.h ++++ b/drivers/platform/mellanox/mlxbf-pmc.h +@@ -364,7 +364,7 @@ struct mlxbf_pmc_events mlxbf2_hnfnet_events[] = { + {0x32, "DDN_DIAG_W_INGRESS"}, + {0x33, "DDN_DIAG_C_INGRESS"}, + {0x34, "DDN_DIAG_CORE_SENT"}, +-{0x35, "NDN_DIAG_S_OUT_OF_CRED"}, ++{0x35, "NDN_DIAG_N_OUT_OF_CRED"}, + {0x36, "NDN_DIAG_S_OUT_OF_CRED"}, + {0x37, "NDN_DIAG_E_OUT_OF_CRED"}, + {0x38, "NDN_DIAG_W_OUT_OF_CRED"}, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0263-UBUNTU-SAUCE-mlxbf-pmc-Support-for-BlueField-3-perfo.patch b/platform/mellanox/non-upstream-patches/patches/0263-UBUNTU-SAUCE-mlxbf-pmc-Support-for-BlueField-3-perfo.patch new file mode 100644 index 0000000000..f461a89e47 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0263-UBUNTU-SAUCE-mlxbf-pmc-Support-for-BlueField-3-perfo.patch @@ -0,0 +1,929 @@ +From 9325ac1c6648be97da5b6e2504b70a3f31a66690 Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Wed, 11 Jan 2023 04:49:23 -0500 +Subject: [PATCH backport 5.10 4/6] UBUNTU: SAUCE: mlxbf-pmc: Support for + BlueField-3 performance counters + +BugLink: https://bugs.launchpad.net/bugs/2002501 + +Add new mechanism for programming and reading the counters in +BlueField-3, along with the updated event list supported in each block. +Read llt_enable and mss_enable info from the ACPI table entry to +identify the enabled blocks. + +Signed-off-by: Shravan Kumar Ramani +Acked-by: Bartlomiej Zolnierkiewicz +Acked-by: Tim Gardner +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/platform/mellanox/mlxbf-pmc.c | 252 +++++++++++++-- + drivers/platform/mellanox/mlxbf-pmc.h | 445 +++++++++++++++++++++++++- + 2 files changed, 658 insertions(+), 39 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 106acea8c..285b7433e 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -243,17 +243,32 @@ struct mlxbf_pmc_events *mlxbf_pmc_event_list(char *blk) + break; + } + else if (strstr(blk, "mss")) +- events = mlxbf_mss_events; ++ switch (pmc->event_set) { ++ case MLNX_EVENT_SET_BF1: ++ case MLNX_EVENT_SET_BF2: ++ events = mlxbf_mss_events; ++ break; ++ case MLNX_EVENT_SET_BF3: ++ events = mlxbf3_mss_events; ++ break; ++ default: ++ events = NULL; ++ break; ++ } + else if (strstr(blk, "ecc")) + events = mlxbf_ecc_events; + else if (strstr(blk, "pcie")) + events = mlxbf_pcie_events; + else if (strstr(blk, "l3cache")) + events = mlxbf_l3cache_events; +- else if (strstr(blk, "gic")) ++ else if (strstr(blk, "gic")) + events = mlxbf_smgen_events; +- else if (strstr(blk, "smmu")) ++ else if (strstr(blk, "smmu")) + events = mlxbf_smgen_events; ++ else if (strstr(blk, "llt_miss")) ++ events = mlxbf3_llt_miss_events; ++ else if (strstr(blk, "llt")) ++ events = mlxbf3_llt_events; + else + events = NULL; + +@@ -378,6 +393,46 @@ int mlxbf_program_l3_counter(int blk_num, uint32_t cnt_num, uint32_t evt) + return mlxbf_pmc_writel(*wordaddr, pmcaddr); + } + ++/* Method to handle crspace counter programming */ ++int mlxbf_program_crspace_counter(int blk_num, uint32_t cnt_num, uint32_t evt) ++{ ++ int reg_num, ret; ++ uint32_t word; ++ void *addr; ++ ++ reg_num = (cnt_num / 2); ++ addr = pmc->block[blk_num].mmio_base + (reg_num * 4); ++ ++ ret = mlxbf_pmc_readl(&word, addr); ++ if (ret) ++ return ret; ++ ++ switch(cnt_num % 2) { ++ case 0: ++ word &= ~MLXBF_CRSPACE_PERFSEL0; ++ word |= FIELD_PREP(MLXBF_CRSPACE_PERFSEL0, evt); ++ break; ++ case 1: ++ word &= ~MLXBF_CRSPACE_PERFSEL1; ++ word |= FIELD_PREP(MLXBF_CRSPACE_PERFSEL1, evt); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return mlxbf_pmc_writel(word, addr); ++} ++ ++int mlxbf_clear_crspace_counter(int blk_num, uint32_t cnt_num) ++{ ++ void *addr; ++ ++ addr = pmc->block[blk_num].mmio_base + MLXBF_CRSPACE_PERFMON_VAL0 + ++ (cnt_num * 4); ++ ++ return mlxbf_pmc_writel(0x0, addr); ++} ++ + /* Method to program a counter to monitor an event */ + int mlxbf_program_counter(int blk_num, uint32_t cnt_num, uint32_t evt, + bool is_l3) +@@ -390,6 +445,9 @@ int mlxbf_program_counter(int blk_num, uint32_t cnt_num, uint32_t evt, + if (is_l3) + return mlxbf_program_l3_counter(blk_num, cnt_num, evt); + ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) ++ return mlxbf_program_crspace_counter(blk_num, cnt_num, evt); ++ + /* Configure the counter */ + perfctl = 0; + perfctl |= FIELD_PREP(MLXBF_GEN_PERFCTL__EN0, 1); +@@ -467,6 +525,22 @@ int mlxbf_read_l3_counter(int blk_num, uint32_t cnt_num, uint64_t *result) + return 0; + } + ++/* Method to handle crspace counter reads */ ++int mlxbf_read_crspace_counter(int blk_num, uint32_t cnt_num, uint64_t *result) ++{ ++ uint32_t value; ++ int status = 0; ++ ++ status = mlxbf_pmc_readl(&value, pmc->block[blk_num].mmio_base + ++ MLXBF_CRSPACE_PERFMON_VAL0 + (cnt_num * 4)); ++ if (status) ++ return status; ++ ++ *result = value; ++ ++ return 0; ++} ++ + /* Method to read the counter value */ + int mlxbf_read_counter(int blk_num, uint32_t cnt_num, bool is_l3, + uint64_t *result) +@@ -481,6 +555,9 @@ int mlxbf_read_counter(int blk_num, uint32_t cnt_num, bool is_l3, + if (is_l3) + return mlxbf_read_l3_counter(blk_num, cnt_num, result); + ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) ++ return mlxbf_read_crspace_counter(blk_num, cnt_num, result); ++ + perfcfg_offset = cnt_num * 8; + perfval_offset = perfcfg_offset + pmc->block[blk_num].counters * 8; + +@@ -557,6 +634,34 @@ int mlxbf_read_l3_event(int blk_num, uint32_t cnt_num, uint64_t *result) + return 0; + } + ++int mlxbf_read_crspace_event(int blk_num, uint32_t cnt_num, uint64_t *result) ++{ ++ uint32_t word, evt; ++ int reg_num, ret; ++ void *addr; ++ ++ reg_num = (cnt_num / 2); ++ addr = pmc->block[blk_num].mmio_base + (reg_num * 4); ++ ++ ret = mlxbf_pmc_readl(&word, addr); ++ if (ret) ++ return ret; ++ ++ switch(cnt_num % 2) { ++ case 0: ++ evt = FIELD_GET(MLXBF_CRSPACE_PERFSEL0, word); ++ break; ++ case 1: ++ evt = FIELD_GET(MLXBF_CRSPACE_PERFSEL1, word); ++ break; ++ default: ++ return -EINVAL; ++ } ++ *result = evt; ++ ++ return 0; ++} ++ + /* Method to find the event currently being monitored by a counter */ + int mlxbf_read_event(int blk_num, uint32_t cnt_num, bool is_l3, + uint64_t *result) +@@ -570,6 +675,10 @@ int mlxbf_read_event(int blk_num, uint32_t cnt_num, bool is_l3, + if (is_l3) + return mlxbf_read_l3_event(blk_num, cnt_num, result); + ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) ++ return mlxbf_read_crspace_event(blk_num, cnt_num, result); ++ ++ + perfcfg_offset = cnt_num * 8; + perfval_offset = perfcfg_offset + pmc->block[blk_num].counters * 8; + +@@ -645,7 +754,8 @@ static ssize_t mlxbf_counter_read(struct kobject *ko, + if (strstr(ko->name, "l3cache")) + is_l3 = true; + +- if (pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) { ++ if ((pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) || ++ (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE)) { + err = sscanf(attr->attr.name, "counter%d", &cnt_num); + if (err < 0) + return -EINVAL; +@@ -706,6 +816,11 @@ static ssize_t mlxbf_counter_clear(struct kobject *ko, + err = mlxbf_write_reg(blk_num, offset, data); + if (err < 0) + return -EINVAL; ++ } else if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) { ++ err = sscanf(attr->attr.name, "counter%d", &cnt_num); ++ if (err < 0) ++ return -EINVAL; ++ err = mlxbf_clear_crspace_counter(blk_num, cnt_num); + } else + return -EINVAL; + +@@ -738,7 +853,8 @@ static ssize_t mlxbf_event_find(struct kobject *ko, + + evt_name = mlxbf_pmc_get_event_name((char *)ko->name, evt_num); + +- return snprintf(buf, PAGE_SIZE, "0x%llx: %s\n", evt_num, evt_name); ++ return snprintf(buf, PAGE_SIZE, ++ "0x%llx: %s\n", evt_num, evt_name); + } + + /* Store function for "event" sysfs files */ +@@ -806,32 +922,41 @@ static ssize_t mlxbf_print_event_list(struct kobject *ko, + return ret; + } + +-/* Show function for "enable" sysfs files - only for l3cache */ ++/* Show function for "enable" sysfs files - only for l3cache and crspace */ + static ssize_t mlxbf_show_counter_state(struct kobject *ko, + struct kobj_attribute *attr, char *buf) + { +- uint32_t perfcnt_cfg; +- int blk_num, value; ++ uint32_t perfcnt_cfg, word; ++ int blk_num, value, err; + + blk_num = mlxbf_pmc_get_block_num(ko->name); + if (blk_num < 0) + return -EINVAL; + +- if (mlxbf_pmc_readl(&perfcnt_cfg, +- pmc->block[blk_num].mmio_base + MLXBF_L3C_PERF_CNT_CFG)) +- return -EINVAL; ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) { ++ err = mlxbf_pmc_readl(&word, pmc->block[blk_num].mmio_base + ++ MLXBF_CRSPACE_PERFMON_CTL); ++ if (err) ++ return -EINVAL; ++ value = FIELD_GET(MLXBF_CRSPACE_PERFMON_EN, word); ++ } else { ++ if (mlxbf_pmc_readl(&perfcnt_cfg, pmc->block[blk_num].mmio_base ++ + MLXBF_L3C_PERF_CNT_CFG)) ++ return -EINVAL; + +- value = FIELD_GET(MLXBF_L3C_PERF_CNT_CFG__EN, perfcnt_cfg); ++ value = FIELD_GET(MLXBF_L3C_PERF_CNT_CFG__EN, perfcnt_cfg); ++ } + + return snprintf(buf, PAGE_SIZE, "%d\n", value); + } + +-/* Store function for "enable" sysfs files - only for l3cache */ ++/* Store function for "enable" sysfs files - only for l3cache and crspace */ + static ssize_t mlxbf_enable_counters(struct kobject *ko, + struct kobj_attribute *attr, + const char *buf, size_t count) + { + int err, en, blk_num; ++ uint32_t word; + + blk_num = mlxbf_pmc_get_block_num(ko->name); + if (blk_num < 0) +@@ -840,20 +965,32 @@ static ssize_t mlxbf_enable_counters(struct kobject *ko, + err = sscanf(buf, "%x\n", &en); + if (err < 0) + return err; +- +- if (en == 0) { +- err = mlxbf_config_l3_counters(blk_num, false, false); +- if (err) +- return err; +- } else if (en == 1) { +- err = mlxbf_config_l3_counters(blk_num, false, true); +- if (err) +- return err; +- err = mlxbf_config_l3_counters(blk_num, true, false); ++ if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) { ++ err = mlxbf_pmc_readl(&word, pmc->block[blk_num].mmio_base + ++ MLXBF_CRSPACE_PERFMON_CTL); + if (err) +- return err; +- } else +- return -EINVAL; ++ return -EINVAL; ++ word &= ~MLXBF_CRSPACE_PERFMON_EN; ++ word |= FIELD_PREP(MLXBF_CRSPACE_PERFMON_EN, en); ++ if (en) ++ word |= FIELD_PREP(MLXBF_CRSPACE_PERFMON_CLR, 1); ++ mlxbf_pmc_writel(word, pmc->block[blk_num].mmio_base + ++ MLXBF_CRSPACE_PERFMON_CTL); ++ } else { ++ if (en == 0) { ++ err = mlxbf_config_l3_counters(blk_num, false, false); ++ if (err) ++ return err; ++ } else if (en == 1) { ++ err = mlxbf_config_l3_counters(blk_num, false, true); ++ if (err) ++ return err; ++ err = mlxbf_config_l3_counters(blk_num, true, false); ++ if (err) ++ return err; ++ } else ++ return -EINVAL; ++ } + + return count; + } +@@ -871,7 +1008,8 @@ int mlxbf_pmc_create_sysfs(struct device *dev, struct kobject *ko, int blk_num) + return -EFAULT; + } + +- if (pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) { ++ if ((pmc->block[blk_num].type == MLXBF_PERFTYPE_COUNTER) || ++ (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE)) { + pmc->block[blk_num].attr_event_list.attr.mode = 0444; + pmc->block[blk_num].attr_event_list.show = + mlxbf_print_event_list; +@@ -888,7 +1026,8 @@ int mlxbf_pmc_create_sysfs(struct device *dev, struct kobject *ko, int blk_num) + return err; + } + +- if (strstr(pmc->block_name[blk_num], "l3cache")) { ++ if ((strstr(pmc->block_name[blk_num], "l3cache")) || ++ (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE)) { + pmc->block[blk_num].attr_enable.attr.mode = + 0644; + pmc->block[blk_num].attr_enable.show = +@@ -1092,6 +1231,8 @@ static int mlxbf_pmc_probe(struct platform_device *pdev) + pmc->event_set = MLNX_EVENT_SET_BF1; + else if (strcmp(hid, "MLNXBFD1") == 0) + pmc->event_set = MLNX_EVENT_SET_BF2; ++ else if (strcmp(hid, "MLNXBFD2") == 0) ++ pmc->event_set = MLNX_EVENT_SET_BF3; + else { + dev_err(dev, "Invalid device ID %s\n", hid); + err = -ENODEV; +@@ -1115,13 +1256,23 @@ static int mlxbf_pmc_probe(struct platform_device *pdev) + } + + if (device_property_read_u32(dev, "tile_num", &pmc->tile_count)) { +- dev_err(dev, "Number of tiles undefined\n"); +- err = -EINVAL; +- goto error; ++ if (device_property_read_u8(dev, "llt_enable", ++ &pmc->llt_enable)) { ++ dev_err(dev, "Number of tiles/LLTs undefined\n"); ++ err = -EINVAL; ++ goto error; ++ } ++ if (device_property_read_u8(dev, "mss_enable", ++ &pmc->mss_enable)) { ++ dev_err(dev, "Number of tiles/MSSs undefined\n"); ++ err = -EINVAL; ++ goto error; ++ } + } + + /* Map the Performance Counters from the varios blocks */ + for (i = 0; i < pmc->total_blocks; ++i) { ++ /* Check if block number is within tile_count */ + if (strstr(pmc->block_name[i], "tile")) { + int tile_num; + +@@ -1133,6 +1284,44 @@ static int mlxbf_pmc_probe(struct platform_device *pdev) + if (tile_num >= pmc->tile_count) + continue; + } ++ ++ /* Create sysfs directories only for enabled MSS blocks */ ++ if (strstr(pmc->block_name[i], "mss") && ++ pmc->event_set == MLNX_EVENT_SET_BF3) { ++ int mss_num; ++ ++ ret = sscanf(pmc->block_name[i], "mss%d", &mss_num); ++ if (ret < 0) { ++ err = -EINVAL; ++ goto error; ++ } ++ if (!((pmc->mss_enable >> mss_num) & 0x1)) ++ continue; ++ } ++ ++ /* Create sysfs directories only for enabled LLTs */ ++ if (strstr(pmc->block_name[i], "llt_miss")) { ++ int llt_num; ++ ++ ret = sscanf(pmc->block_name[i], "llt_miss%d", &llt_num); ++ if (ret < 0) { ++ err = -EINVAL; ++ goto error; ++ } ++ if (!((pmc->llt_enable >> llt_num) & 0x1)) ++ continue; ++ } else if (strstr(pmc->block_name[i], "llt")) { ++ int llt_num; ++ ++ ret = sscanf(pmc->block_name[i], "llt%d", &llt_num); ++ if (ret < 0) { ++ err = -EINVAL; ++ goto error; ++ } ++ if (!((pmc->llt_enable >> llt_num) & 0x1)) ++ continue; ++ } ++ + err = device_property_read_u64_array(dev, pmc->block_name[i], + info, 4); + if (err) { +@@ -1215,6 +1404,7 @@ static int mlxbf_pmc_remove(struct platform_device *pdev) + static const struct acpi_device_id pmc_acpi_ids[] = { + {"MLNXBFD0", 0}, + {"MLNXBFD1", 0}, ++ {"MLNXBFD2", 0}, + {}, + }; + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.h b/drivers/platform/mellanox/mlxbf-pmc.h +index a6f7aade4..fe2516616 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.h ++++ b/drivers/platform/mellanox/mlxbf-pmc.h +@@ -16,6 +16,7 @@ + + #define MLNX_EVENT_SET_BF1 0 + #define MLNX_EVENT_SET_BF2 1 ++#define MLNX_EVENT_SET_BF3 2 + + #define MLNX_PMC_SVC_REQ_MAJOR 0 + #define MLNX_PMC_SVC_MIN_MINOR 3 +@@ -55,6 +56,8 @@ struct mlxbf_pmc_block_info { + * @pdev: The kernel structure representing the device + * @total_blocks: Total number of blocks + * @tile_count: Number of tiles in the system ++ * @llt_enable: Info on enabled LLTs ++ * @mss_enable: Info on enabled MSSs + * @hwmon_dev: Hwmon device for bfperf + * @ko: Kobject for bfperf + * @block_name: Block name +@@ -67,6 +70,8 @@ struct mlxbf_pmc_context { + struct platform_device *pdev; + uint32_t total_blocks; + uint32_t tile_count; ++ uint8_t llt_enable; ++ uint8_t mss_enable; + struct device *hwmon_dev; + struct kobject *ko; + const char *block_name[MLXBF_PMC_MAX_BLOCKS]; +@@ -76,16 +81,17 @@ struct mlxbf_pmc_context { + unsigned int event_set; + }; + +-#define MLXBF_PERFTYPE_COUNTER 1 + #define MLXBF_PERFTYPE_REGISTER 0 ++#define MLXBF_PERFTYPE_COUNTER 1 ++#define MLXBF_PERFTYPE_CRSPACE 2 + +-#define MLXBF_PERFCTL 0 +-#define MLXBF_PERFEVT 1 +-#define MLXBF_PERFVALEXT 2 +-#define MLXBF_PERFACC0 4 +-#define MLXBF_PERFACC1 5 +-#define MLXBF_PERFMVAL0 6 +-#define MLXBF_PERFMVAL1 7 ++#define MLXBF_PERFCTL 0 ++#define MLXBF_PERFEVT 1 ++#define MLXBF_PERFVALEXT 2 ++#define MLXBF_PERFACC0 4 ++#define MLXBF_PERFACC1 5 ++#define MLXBF_PERFMVAL0 6 ++#define MLXBF_PERFMVAL1 7 + + #define MLXBF_GEN_PERFMON_CONFIG__WR_R_B BIT(0) + #define MLXBF_GEN_PERFMON_CONFIG__STROBE BIT(1) +@@ -143,6 +149,14 @@ struct mlxbf_pmc_context { + #define MLXBF_L3C_PERF_CNT_LOW__VAL GENMASK(31, 0) + #define MLXBF_L3C_PERF_CNT_HIGH__VAL GENMASK(24, 0) + ++#define MLXBF_CRSPACE_PERFMON_REG0 0x0 ++#define MLXBF_CRSPACE_PERFSEL0 GENMASK(23, 16) ++#define MLXBF_CRSPACE_PERFSEL1 GENMASK(7, 0) ++#define MLXBF_CRSPACE_PERFMON_CTL 0x40 ++#define MLXBF_CRSPACE_PERFMON_EN BIT(30) ++#define MLXBF_CRSPACE_PERFMON_CLR BIT(28) ++#define MLXBF_CRSPACE_PERFMON_VAL0 0x4c ++ + struct mlxbf_pmc_events { + uint32_t evt_num; + char *evt_name; +@@ -431,4 +445,419 @@ struct mlxbf_pmc_events mlxbf_l3cache_events[] = { + {-1, NULL} + }; + ++struct mlxbf_pmc_events mlxbf3_llt_events[] = { ++{0, "HNF0_CYCLES"}, ++{1, "HNF0_REQS_RECEIVED"}, ++{2, "HNF0_REQS_PROCESSED"}, ++{3, "HNF0_DIR_HIT"}, ++{4, "HNF0_DIR_MISS"}, ++{5, "HNF0_DIR_RD_ALLOC"}, ++{6, "HNF0_DIR_WR_ALLOC"}, ++{7, "HNF0_DIR_VICTIM"}, ++{8, "HNF0_CL_HAZARD"}, ++{9, "HNF0_ALL_HAZARD"}, ++{10, "HNF0_PIPE_STALLS"}, ++{11, "HNF0_MEM_READS"}, ++{12, "HNF0_MEM_WRITES"}, ++{13, "HNF0_MEM_ACCESS"}, ++{14, "HNF0_DCL_READ"}, ++{15, "HNF0_DCL_INVAL"}, ++{16, "HNF0_CHI_RXDAT"}, ++{17, "HNF0_CHI_RXRSP"}, ++{18, "HNF0_CHI_TXDAT"}, ++{19, "HNF0_CHI_TXRSP"}, ++{20, "HNF0_CHI_TXSNP"}, ++{21, "HNF0_DCT_SNP"}, ++{22, "HNF0_SNP_FWD_DATA"}, ++{23, "HNF0_SNP_FWD_RSP"}, ++{24, "HNF0_SNP_RSP"}, ++{25, "HNF0_EXCL_FULL"}, ++{26, "HNF0_EXCL_WRITE_F"}, ++{27, "HNF0_EXCL_WRITE_S"}, ++{28, "HNF0_EXCL_WRITE"}, ++{29, "HNF0_EXCL_READ"}, ++{30, "HNF0_REQ_BUF_EMPTY"}, ++{31, "HNF0_ALL_MAFS_BUSY"}, ++{32, "HNF0_TXDAT_NO_LCRD"}, ++{33, "HNF0_TXSNP_NO_LCRD"}, ++{34, "HNF0_TXRSP_NO_LCRD"}, ++{35, "HNF0_TXREQ_NO_LCRD"}, ++{36, "HNF0_WRITE"}, ++{37, "HNF0_READ"}, ++{38, "HNF0_ACCESS"}, ++{39, "HNF0_MAF_N_BUSY"}, ++{40, "HNF0_MAF_N_REQS"}, ++{41, "HNF0_SEL_OPCODE"}, ++{42, "HNF1_CYCLES"}, ++{43, "HNF1_REQS_RECEIVED"}, ++{44, "HNF1_REQS_PROCESSED"}, ++{45, "HNF1_DIR_HIT"}, ++{46, "HNF1_DIR_MISS"}, ++{47, "HNF1_DIR_RD_ALLOC"}, ++{48, "HNF1_DIR_WR_ALLOC"}, ++{49, "HNF1_DIR_VICTIM"}, ++{50, "HNF1_CL_HAZARD"}, ++{51, "HNF1_ALL_HAZARD"}, ++{52, "HNF1_PIPE_STALLS"}, ++{53, "HNF1_MEM_READS"}, ++{54, "HNF1_MEM_WRITES"}, ++{55, "HNF1_MEM_ACCESS"}, ++{56, "HNF1_DCL_READ"}, ++{57, "HNF1_DCL_INVAL"}, ++{58, "HNF1_CHI_RXDAT"}, ++{59, "HNF1_CHI_RXRSP"}, ++{60, "HNF1_CHI_TXDAT"}, ++{61, "HNF1_CHI_TXRSP"}, ++{62, "HNF1_CHI_TXSNP"}, ++{63, "HNF1_DCT_SNP"}, ++{64, "HNF1_SNP_FWD_DATA"}, ++{65, "HNF1_SNP_FWD_RSP"}, ++{66, "HNF1_SNP_RSP"}, ++{67, "HNF1_EXCL_FULL"}, ++{68, "HNF1_EXCL_WRITE_F"}, ++{69, "HNF1_EXCL_WRITE_S"}, ++{70, "HNF1_EXCL_WRITE"}, ++{71, "HNF1_EXCL_READ"}, ++{72, "HNF1_REQ_BUF_EMPTY"}, ++{73, "HNF1_ALL_MAFS_BUSY"}, ++{74, "HNF1_TXDAT_NO_LCRD"}, ++{75, "HNF1_TXSNP_NO_LCRD"}, ++{76, "HNF1_TXRSP_NO_LCRD"}, ++{77, "HNF1_TXREQ_NO_LCRD"}, ++{78, "HNF1_WRITE"}, ++{79, "HNF1_READ"}, ++{80, "HNF1_ACCESS"}, ++{81, "HNF1_MAF_N_BUSY"}, ++{82, "HNF1_MAF_N_REQS"}, ++{83, "HNF1_SEL_OPCODE"}, ++{84, "GDC_BANK0_RD_REQ"}, ++{85, "GDC_BANK0_WR_REQ"}, ++{86, "GDC_BANK0_ALLOCATE"}, ++{87, "GDC_BANK0_HIT"}, ++{88, "GDC_BANK0_MISS"}, ++{89, "GDC_BANK0_INVALIDATE"}, ++{90, "GDC_BANK0_EVICT"}, ++{91, "GDC_BANK0_RD_RESP"}, ++{92, "GDC_BANK0_WR_ACK"}, ++{93, "GDC_BANK0_SNOOP"}, ++{94, "GDC_BANK0_SNOOP_NORMAL"}, ++{95, "GDC_BANK0_SNOOP_FWD"}, ++{96, "GDC_BANK0_SNOOP_STASH"}, ++{97, "GDC_BANK0_SNOOP_STASH_INDPND_RD"}, ++{98, "GDC_BANK0_FOLLOWER"}, ++{99, "GDC_BANK0_FW"}, ++{100, "GDC_BANK0_HIT_DCL_BOTH"}, ++{101, "GDC_BANK0_HIT_DCL_PARTIAL"}, ++{102, "GDC_BANK0_EVICT_DCL"}, ++{103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA0"}, ++{103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"}, ++{105, "GDC_BANK0_ARB_STRB"}, ++{106, "GDC_BANK0_ARB_WAIT"}, ++{107, "GDC_BANK0_GGA_STRB"}, ++{108, "GDC_BANK0_GGA_WAIT"}, ++{109, "GDC_BANK0_FW_STRB"}, ++{110, "GDC_BANK0_FW_WAIT"}, ++{111, "GDC_BANK0_SNP_STRB"}, ++{112, "GDC_BANK0_SNP_WAIT"}, ++{113, "GDC_BANK0_MISS_INARB_STRB"}, ++{114, "GDC_BANK0_MISS_INARB_WAIT"}, ++{115, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD0"}, ++{116, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD1"}, ++{117, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD2"}, ++{118, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD3"}, ++{119, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR0"}, ++{120, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR1"}, ++{121, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR2"}, ++{122, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR3"}, ++{123, "GDC_BANK1_RD_REQ"}, ++{124, "GDC_BANK1_WR_REQ"}, ++{125, "GDC_BANK1_ALLOCATE"}, ++{126, "GDC_BANK1_HIT"}, ++{127, "GDC_BANK1_MISS"}, ++{128, "GDC_BANK1_INVALIDATE"}, ++{129, "GDC_BANK1_EVICT"}, ++{130, "GDC_BANK1_RD_RESP"}, ++{131, "GDC_BANK1_WR_ACK"}, ++{132, "GDC_BANK1_SNOOP"}, ++{133, "GDC_BANK1_SNOOP_NORMAL"}, ++{134, "GDC_BANK1_SNOOP_FWD"}, ++{135, "GDC_BANK1_SNOOP_STASH"}, ++{136, "GDC_BANK1_SNOOP_STASH_INDPND_RD"}, ++{137, "GDC_BANK1_FOLLOWER"}, ++{138, "GDC_BANK1_FW"}, ++{139, "GDC_BANK1_HIT_DCL_BOTH"}, ++{140, "GDC_BANK1_HIT_DCL_PARTIAL"}, ++{141, "GDC_BANK1_EVICT_DCL"}, ++{142, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA0"}, ++{143, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA1"}, ++{144, "GDC_BANK1_ARB_STRB"}, ++{145, "GDC_BANK1_ARB_WAIT"}, ++{146, "GDC_BANK1_GGA_STRB"}, ++{147, "GDC_BANK1_GGA_WAIT"}, ++{148, "GDC_BANK1_FW_STRB"}, ++{149, "GDC_BANK1_FW_WAIT"}, ++{150, "GDC_BANK1_SNP_STRB"}, ++{151, "GDC_BANK1_SNP_WAIT"}, ++{152, "GDC_BANK1_MISS_INARB_STRB"}, ++{153, "GDC_BANK1_MISS_INARB_WAIT"}, ++{154, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD0"}, ++{155, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD1"}, ++{156, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD2"}, ++{157, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD3"}, ++{158, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR0"}, ++{159, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR1"}, ++{160, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR2"}, ++{161, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR3"}, ++{162, "HISTOGRAM_HISTOGRAM_BIN0"}, ++{163, "HISTOGRAM_HISTOGRAM_BIN1"}, ++{164, "HISTOGRAM_HISTOGRAM_BIN2"}, ++{165, "HISTOGRAM_HISTOGRAM_BIN3"}, ++{166, "HISTOGRAM_HISTOGRAM_BIN4"}, ++{167, "HISTOGRAM_HISTOGRAM_BIN5"}, ++{168, "HISTOGRAM_HISTOGRAM_BIN6"}, ++{169, "HISTOGRAM_HISTOGRAM_BIN7"}, ++{170, "HISTOGRAM_HISTOGRAM_BIN8"}, ++{171, "HISTOGRAM_HISTOGRAM_BIN9"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf3_llt_miss_events[] = { ++{0, "GDC_MISS_MACHINE_RD_REQ"}, ++{1, "GDC_MISS_MACHINE_WR_REQ"}, ++{2, "GDC_MISS_MACHINE_SNP_REQ"}, ++{3, "GDC_MISS_MACHINE_EVICT_REQ"}, ++{4, "GDC_MISS_MACHINE_FW_REQ"}, ++{5, "GDC_MISS_MACHINE_RD_RESP"}, ++{6, "GDC_MISS_MACHINE_WR_RESP"}, ++{7, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP"}, ++{8, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP_TXDAT"}, ++{9, "GDC_MISS_MACHINE_CHI_TXREQ"}, ++{10, "GDC_MISS_MACHINE_CHI_RXRSP"}, ++{11, "GDC_MISS_MACHINE_CHI_TXDAT"}, ++{12, "GDC_MISS_MACHINE_CHI_RXDAT"}, ++{13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"}, ++{14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "}, ++{15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"}, ++{16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "}, ++{17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "}, ++{18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "}, ++{19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "}, ++{20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "}, ++{21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"}, ++{22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"}, ++{23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"}, ++{24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"}, ++{25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "}, ++{26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"}, ++{27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"}, ++{28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"}, ++{29, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_0"}, ++{30, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_1"}, ++{31, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_2"}, ++{32, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_3"}, ++{33, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_4"}, ++{34, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_5"}, ++{35, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_6"}, ++{36, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_0"}, ++{37, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_1"}, ++{38, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_0"}, ++{39, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_1"}, ++{40, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_0"}, ++{41, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_1"}, ++{42, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_0"}, ++{43, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_1"}, ++{44, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_0"}, ++{45, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_1"}, ++{46, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_2"}, ++{47, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_3"}, ++{48, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_0"}, ++{49, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_1"}, ++{50, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_0"}, ++{51, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_1"}, ++{52, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_0"}, ++{53, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_1"}, ++{54, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_0"}, ++{55, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_1"}, ++{56, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_2"}, ++{57, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_3"}, ++{58, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_0"}, ++{59, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_1"}, ++{60, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_2"}, ++{61, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_3"}, ++{62, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_4"}, ++{63, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_5"}, ++{64, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_6"}, ++{65, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_7"}, ++{66, "HISTOGRAM_HISTOGRAM_BIN0"}, ++{67, "HISTOGRAM_HISTOGRAM_BIN1"}, ++{68, "HISTOGRAM_HISTOGRAM_BIN2"}, ++{69, "HISTOGRAM_HISTOGRAM_BIN3"}, ++{70, "HISTOGRAM_HISTOGRAM_BIN4"}, ++{71, "HISTOGRAM_HISTOGRAM_BIN5"}, ++{72, "HISTOGRAM_HISTOGRAM_BIN6"}, ++{73, "HISTOGRAM_HISTOGRAM_BIN7"}, ++{74, "HISTOGRAM_HISTOGRAM_BIN8"}, ++{75, "HISTOGRAM_HISTOGRAM_BIN9"}, ++{-1, NULL} ++}; ++ ++struct mlxbf_pmc_events mlxbf3_mss_events[] = { ++{0, "SKYLIB_CDN_TX_FLITS"}, ++{1, "SKYLIB_DDN_TX_FLITS"}, ++{2, "SKYLIB_NDN_TX_FLITS"}, ++{3, "SKYLIB_SDN_TX_FLITS"}, ++{4, "SKYLIB_UDN_TX_FLITS"}, ++{5, "SKYLIB_CDN_RX_FLITS"}, ++{6, "SKYLIB_DDN_RX_FLITS"}, ++{7, "SKYLIB_NDN_RX_FLITS"}, ++{8, "SKYLIB_SDN_RX_FLITS"}, ++{9, "SKYLIB_UDN_RX_FLITS"}, ++{10, "SKYLIB_CDN_TX_STALL"}, ++{11, "SKYLIB_DDN_TX_STALL"}, ++{12, "SKYLIB_NDN_TX_STALL"}, ++{13, "SKYLIB_SDN_TX_STALL"}, ++{14, "SKYLIB_UDN_TX_STALL"}, ++{15, "SKYLIB_CDN_RX_STALL"}, ++{16, "SKYLIB_DDN_RX_STALL"}, ++{17, "SKYLIB_NDN_RX_STALL"}, ++{18, "SKYLIB_SDN_RX_STALL"}, ++{19, "SKYLIB_UDN_RX_STALL"}, ++{20, "SKYLIB_CHI_REQ0_TX_FLITS"}, ++{21, "SKYLIB_CHI_DATA0_TX_FLITS"}, ++{22, "SKYLIB_CHI_RESP0_TX_FLITS"}, ++{23, "SKYLIB_CHI_SNP0_TX_FLITS"}, ++{24, "SKYLIB_CHI_REQ1_TX_FLITS"}, ++{25, "SKYLIB_CHI_DATA1_TX_FLITS"}, ++{26, "SKYLIB_CHI_RESP1_TX_FLITS"}, ++{27, "SKYLIB_CHI_SNP1_TX_FLITS"}, ++{28, "SKYLIB_CHI_REQ2_TX_FLITS"}, ++{29, "SKYLIB_CHI_DATA2_TX_FLITS"}, ++{30, "SKYLIB_CHI_RESP2_TX_FLITS"}, ++{31, "SKYLIB_CHI_SNP2_TX_FLITS"}, ++{32, "SKYLIB_CHI_REQ3_TX_FLITS"}, ++{33, "SKYLIB_CHI_DATA3_TX_FLITS"}, ++{34, "SKYLIB_CHI_RESP3_TX_FLITS"}, ++{35, "SKYLIB_CHI_SNP3_TX_FLITS"}, ++{36, "SKYLIB_TLP_REQ_TX_FLITS"}, ++{37, "SKYLIB_TLP_RESP_TX_FLITS"}, ++{38, "SKYLIB_TLP_META_TX_FLITS"}, ++{39, "SKYLIB_AXIS_DATA_TX_FLITS"}, ++{40, "SKYLIB_AXIS_CRED_TX_FLITS"}, ++{41, "SKYLIB_APB_TX_FLITS"}, ++{42, "SKYLIB_VW_TX_FLITS"}, ++{43, "SKYLIB_GGA_MSN_W_TX_FLITS"}, ++{44, "SKYLIB_GGA_MSN_N_TX_FLITS"}, ++{45, "SKYLIB_CR_REQ_TX_FLITS"}, ++{46, "SKYLIB_CR_RESP_TX_FLITS"}, ++{47, "SKYLIB_MSN_PRNF_TX_FLITS"}, ++{48, "SKYLIB_DBG_DATA_TX_FLITS"}, ++{49, "SKYLIB_DBG_CRED_TX_FLITS"}, ++{50, "SKYLIB_CHI_REQ0_RX_FLITS"}, ++{51, "SKYLIB_CHI_DATA0_RX_FLITS"}, ++{52, "SKYLIB_CHI_RESP0_RX_FLITS"}, ++{53, "SKYLIB_CHI_SNP0_RX_FLITS"}, ++{54, "SKYLIB_CHI_REQ1_RX_FLITS"}, ++{55, "SKYLIB_CHI_DATA1_RX_FLITS"}, ++{56, "SKYLIB_CHI_RESP1_RX_FLITS"}, ++{57, "SKYLIB_CHI_SNP1_RX_FLITS"}, ++{58, "SKYLIB_CHI_REQ2_RX_FLITS"}, ++{59, "SKYLIB_CHI_DATA2_RX_FLITS"}, ++{60, "SKYLIB_CHI_RESP2_RX_FLITS"}, ++{61, "SKYLIB_CHI_SNP2_RX_FLITS"}, ++{62, "SKYLIB_CHI_REQ3_RX_FLITS"}, ++{63, "SKYLIB_CHI_DATA3_RX_FLITS"}, ++{64, "SKYLIB_CHI_RESP3_RX_FLITS"}, ++{65, "SKYLIB_CHI_SNP3_RX_FLITS"}, ++{66, "SKYLIB_TLP_REQ_RX_FLITS"}, ++{67, "SKYLIB_TLP_RESP_RX_FLITS"}, ++{68, "SKYLIB_TLP_META_RX_FLITS"}, ++{69, "SKYLIB_AXIS_DATA_RX_FLITS"}, ++{70, "SKYLIB_AXIS_CRED_RX_FLITS"}, ++{71, "SKYLIB_APB_RX_FLITS"}, ++{72, "SKYLIB_VW_RX_FLITS"}, ++{73, "SKYLIB_GGA_MSN_W_RX_FLITS"}, ++{74, "SKYLIB_GGA_MSN_N_RX_FLITS"}, ++{75, "SKYLIB_CR_REQ_RX_FLITS"}, ++{76, "SKYLIB_CR_RESP_RX_FLITS"}, ++{77, "SKYLIB_MSN_PRNF_RX_FLITS"}, ++{78, "SKYLIB_DBG_DATA_RX_FLITS"}, ++{79, "SKYLIB_DBG_CRED_RX_FLITS"}, ++{80, "SKYLIB_CHI_REQ0_TX_STALL"}, ++{81, "SKYLIB_CHI_DATA0_TX_STALL"}, ++{82, "SKYLIB_CHI_RESP0_TX_STALL"}, ++{83, "SKYLIB_CHI_SNP0_TX_STALL"}, ++{84, "SKYLIB_CHI_REQ1_TX_STALL"}, ++{85, "SKYLIB_CHI_DATA1_TX_STALL"}, ++{86, "SKYLIB_CHI_RESP1_TX_STALL"}, ++{87, "SKYLIB_CHI_SNP1_TX_STALL"}, ++{88, "SKYLIB_CHI_REQ2_TX_STALL"}, ++{89, "SKYLIB_CHI_DATA2_TX_STALL"}, ++{90, "SKYLIB_CHI_RESP2_TX_STALL"}, ++{91, "SKYLIB_CHI_SNP2_TX_STALL"}, ++{92, "SKYLIB_CHI_REQ3_TX_STALL"}, ++{93, "SKYLIB_CHI_DATA3_TX_STALL"}, ++{94, "SKYLIB_CHI_RESP3_TX_STALL"}, ++{95, "SKYLIB_CHI_SNP3_TX_STALL"}, ++{96, "SKYLIB_TLP_REQ_TX_STALL"}, ++{97, "SKYLIB_TLP_RESP_TX_STALL"}, ++{98, "SKYLIB_TLP_META_TX_STALL"}, ++{99, "SKYLIB_AXIS_DATA_TX_STALL"}, ++{100, "SKYLIB_AXIS_CRED_TX_STALL"}, ++{101, "SKYLIB_APB_TX_STALL"}, ++{102, "SKYLIB_VW_TX_STALL"}, ++{103, "SKYLIB_GGA_MSN_W_TX_STALL"}, ++{104, "SKYLIB_GGA_MSN_N_TX_STALL"}, ++{105, "SKYLIB_CR_REQ_TX_STALL"}, ++{106, "SKYLIB_CR_RESP_TX_STALL"}, ++{107, "SKYLIB_MSN_PRNF_TX_STALL"}, ++{108, "SKYLIB_DBG_DATA_TX_STALL"}, ++{109, "SKYLIB_DBG_CRED_TX_STALL"}, ++{110, "SKYLIB_CHI_REQ0_RX_STALL"}, ++{111, "SKYLIB_CHI_DATA0_RX_STALL"}, ++{112, "SKYLIB_CHI_RESP0_RX_STALL"}, ++{113, "SKYLIB_CHI_SNP0_RX_STALL"}, ++{114, "SKYLIB_CHI_REQ1_RX_STALL"}, ++{115, "SKYLIB_CHI_DATA1_RX_STALL"}, ++{116, "SKYLIB_CHI_RESP1_RX_STALL"}, ++{117, "SKYLIB_CHI_SNP1_RX_STALL"}, ++{118, "SKYLIB_CHI_REQ2_RX_STALL"}, ++{119, "SKYLIB_CHI_DATA2_RX_STALL"}, ++{120, "SKYLIB_CHI_RESP2_RX_STALL"}, ++{121, "SKYLIB_CHI_SNP2_RX_STALL"}, ++{122, "SKYLIB_CHI_REQ3_RX_STALL"}, ++{123, "SKYLIB_CHI_DATA3_RX_STALL"}, ++{124, "SKYLIB_CHI_RESP3_RX_STALL"}, ++{125, "SKYLIB_CHI_SNP3_RX_STALL"}, ++{126, "SKYLIB_TLP_REQ_RX_STALL"}, ++{127, "SKYLIB_TLP_RESP_RX_STALL"}, ++{128, "SKYLIB_TLP_META_RX_STALL"}, ++{129, "SKYLIB_AXIS_DATA_RX_STALL"}, ++{130, "SKYLIB_AXIS_CRED_RX_STALL"}, ++{131, "SKYLIB_APB_RX_STALL"}, ++{132, "SKYLIB_VW_RX_STALL"}, ++{133, "SKYLIB_GGA_MSN_W_RX_STALL"}, ++{134, "SKYLIB_GGA_MSN_N_RX_STALL"}, ++{135, "SKYLIB_CR_REQ_RX_STALL"}, ++{136, "SKYLIB_CR_RESP_RX_STALL"}, ++{137, "SKYLIB_MSN_PRNF_RX_STALL"}, ++{138, "SKYLIB_DBG_DATA_RX_STALL"}, ++{139, "SKYLIB_DBG_CRED_RX_STALL"}, ++{140, "SKYLIB_CDN_LOOPBACK_FLITS"}, ++{141, "SKYLIB_DDN_LOOPBACK_FLITS"}, ++{142, "SKYLIB_NDN_LOOPBACK_FLITS"}, ++{143, "SKYLIB_SDN_LOOPBACK_FLITS"}, ++{144, "SKYLIB_UDN_LOOPBACK_FLITS"}, ++{145, "HISTOGRAM_HISTOGRAM_BIN0"}, ++{146, "HISTOGRAM_HISTOGRAM_BIN1"}, ++{147, "HISTOGRAM_HISTOGRAM_BIN2"}, ++{148, "HISTOGRAM_HISTOGRAM_BIN3"}, ++{149, "HISTOGRAM_HISTOGRAM_BIN4"}, ++{150, "HISTOGRAM_HISTOGRAM_BIN5"}, ++{151, "HISTOGRAM_HISTOGRAM_BIN6"}, ++{152, "HISTOGRAM_HISTOGRAM_BIN7"}, ++{153, "HISTOGRAM_HISTOGRAM_BIN8"}, ++{154, "HISTOGRAM_HISTOGRAM_BIN9"}, ++{-1, NULL} ++}; ++ + #endif /* __MLXBF_PMC_H__ */ +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0264-UBUNTU-SAUCE-platform-mellanox-Add-ctrl-message-and-.patch b/platform/mellanox/non-upstream-patches/patches/0264-UBUNTU-SAUCE-platform-mellanox-Add-ctrl-message-and-.patch new file mode 100644 index 0000000000..14a9941288 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0264-UBUNTU-SAUCE-platform-mellanox-Add-ctrl-message-and-.patch @@ -0,0 +1,275 @@ +From cafef2e9c3fc7113396fb53f55e0b6dfa6115e6a Mon Sep 17 00:00:00 2001 +From: Liming Sun +Date: Thu, 12 Jan 2023 13:58:47 -0500 +Subject: [PATCH backport 5.10 5/6] UBUNTU: SAUCE: platform/mellanox: Add ctrl + message and MAC configuration + +BugLink: https://bugs.launchpad.net/bugs/2002689 + +This commit adds control message support and MAC configuration +based on the control message. + +Signed-off-by: Liming Sun +Acked-by: Bartlomiej Zolnierkiewicz +Acked-by: Tim Gardner +[bzolnier: use a short URL version for BugLink] +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/platform/mellanox/mlxbf-tmfifo.c | 172 ++++++++++++++++++++--- + 1 file changed, 151 insertions(+), 21 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c +index f401bbbd0..97956c9c9 100644 +--- a/drivers/platform/mellanox/mlxbf-tmfifo.c ++++ b/drivers/platform/mellanox/mlxbf-tmfifo.c +@@ -159,7 +159,9 @@ struct mlxbf_tmfifo_irq_info { + * @timer: background timer + * @vring: Tx/Rx ring + * @spin_lock: Tx/Rx spin lock ++ * @ctrl_mac: MAC address received in control message + * @is_ready: ready flag ++ * @send_ctrl: flag to send control message when ready + */ + struct mlxbf_tmfifo { + struct mlxbf_tmfifo_vdev *vdev[MLXBF_TMFIFO_VDEV_MAX]; +@@ -180,7 +182,16 @@ struct mlxbf_tmfifo { + struct timer_list timer; + struct mlxbf_tmfifo_vring *vring[2]; + spinlock_t spin_lock[2]; /* spin lock */ +- bool is_ready; ++ u8 ctrl_mac[ETH_ALEN]; ++ u32 is_ready : 1; ++ u32 send_ctrl : 1; ++}; ++ ++/* Internal message types defined in reverse order starting from 0xFF. */ ++enum { ++ MLXBF_TMFIFO_MSG_CTRL_REQ = 0xFD, ++ MLXBF_TMFIFO_MSG_MAC_1 = 0xFE, ++ MLXBF_TMFIFO_MSG_MAC_2 = 0xFF + }; + + /** +@@ -190,11 +201,17 @@ struct mlxbf_tmfifo { + * will be read by the other side as data stream in the same byte order. + * The length needs to be encoded into network order so both sides + * could understand it. ++ * @mac: first or second half of the MAC address depending on the type. ++ * @checksum: checksum of the message header (only control message for now). + */ + struct mlxbf_tmfifo_msg_hdr { + u8 type; + __be16 len; +- u8 unused[5]; ++ union { ++ u8 mac[3]; ++ u8 unused[4]; ++ } __packed; ++ u8 checksum; + } __packed __aligned(sizeof(u64)); + + /* +@@ -491,6 +508,8 @@ static int mlxbf_tmfifo_get_rx_avail(struct mlxbf_tmfifo *fifo) + return FIELD_GET(MLXBF_TMFIFO_RX_STS__COUNT_MASK, sts); + } + ++ ++ + /* Get the number of available words in the TmFifo for sending. */ + static int mlxbf_tmfifo_get_tx_avail(struct mlxbf_tmfifo *fifo, int vdev_id) + { +@@ -509,6 +528,127 @@ static int mlxbf_tmfifo_get_tx_avail(struct mlxbf_tmfifo *fifo, int vdev_id) + return fifo->tx_fifo_size - tx_reserve - count; + } + ++/* Read the configured network MAC address from efi variable. */ ++static void mlxbf_tmfifo_get_cfg_mac(u8 *mac) ++{ ++ efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID; ++ unsigned long size = ETH_ALEN; ++ u8 buf[ETH_ALEN]; ++ efi_status_t rc; ++ ++ rc = efi.get_variable(mlxbf_tmfifo_efi_name, &guid, NULL, &size, buf); ++ if (rc == EFI_SUCCESS && size == ETH_ALEN) ++ ether_addr_copy(mac, buf); ++ else ++ ether_addr_copy(mac, mlxbf_tmfifo_net_default_mac); ++} ++ ++/* Set the configured network MAC address into efi variable. */ ++static efi_status_t mlxbf_tmfifo_set_cfg_mac(u8 *mac) ++{ ++ efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID; ++ efi_status_t status = EFI_SUCCESS; ++ u8 old_mac[ETH_ALEN] = {0}; ++ ++ mlxbf_tmfifo_get_cfg_mac(old_mac); ++ ++ if (memcmp(old_mac, mac, ETH_ALEN)) { ++ status = efi.set_variable(mlxbf_tmfifo_efi_name, &guid, ++ EFI_VARIABLE_NON_VOLATILE | ++ EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ EFI_VARIABLE_RUNTIME_ACCESS, ++ ETH_ALEN, mac); ++ } ++ ++ return status; ++} ++ ++/* Just adds up all the bytes of the header. */ ++static u8 mlxbf_tmfifo_ctrl_checksum(struct mlxbf_tmfifo_msg_hdr *hdr) ++{ ++ u8 checksum = 0; ++ int i; ++ ++ for (i = 0; i < sizeof(*hdr); i++) ++ checksum += ((u8 *)hdr)[i]; ++ ++ return checksum; ++} ++ ++static void mlxbf_tmfifo_ctrl_update_checksum(struct mlxbf_tmfifo_msg_hdr *hdr) ++{ ++ u8 checksum; ++ ++ hdr->checksum = 0; ++ checksum = mlxbf_tmfifo_ctrl_checksum(hdr); ++ hdr->checksum = ~checksum + 1; ++} ++ ++static bool mlxbf_tmfifo_ctrl_verify_checksum(struct mlxbf_tmfifo_msg_hdr *hdr) ++{ ++ u8 checksum = mlxbf_tmfifo_ctrl_checksum(hdr); ++ ++ return checksum ? false : true; ++} ++ ++static void mlxbf_tmfifo_ctrl_rx(struct mlxbf_tmfifo *fifo, ++ struct mlxbf_tmfifo_msg_hdr *hdr) ++{ ++ if (!mlxbf_tmfifo_ctrl_verify_checksum(hdr)) ++ return; ++ ++ switch (hdr->type) { ++ case MLXBF_TMFIFO_MSG_CTRL_REQ: ++ /* ++ * Set a flag to send the MAC address later. It can't be sent ++ * here since another packet might be still in the middle of ++ * transmission. ++ */ ++ fifo->send_ctrl = 1; ++ test_and_set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events); ++ schedule_work(&fifo->work); ++ break; ++ case MLXBF_TMFIFO_MSG_MAC_1: ++ /* Get the first half of the MAC address. */ ++ memcpy(fifo->ctrl_mac, hdr->mac, sizeof(hdr->mac)); ++ break; ++ case MLXBF_TMFIFO_MSG_MAC_2: ++ /* Get the second half of the MAC address and update. */ ++ memcpy(fifo->ctrl_mac + sizeof(hdr->mac), hdr->mac, ++ sizeof(hdr->mac)); ++ mlxbf_tmfifo_set_cfg_mac(fifo->ctrl_mac); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void mlxbf_tmfifo_ctrl_tx(struct mlxbf_tmfifo *fifo, int *num_avail) ++{ ++ struct mlxbf_tmfifo_msg_hdr hdr; ++ u8 mac[ETH_ALEN] = { 0 }; ++ ++ /* Send the MAC address with two control messages. */ ++ if (fifo->send_ctrl && *num_avail >= 2) { ++ mlxbf_tmfifo_get_cfg_mac(mac); ++ ++ hdr.type = MLXBF_TMFIFO_MSG_MAC_1; ++ hdr.len = 0; ++ memcpy(hdr.mac, mac, sizeof(hdr.mac)); ++ mlxbf_tmfifo_ctrl_update_checksum(&hdr); ++ writeq(*(u64 *)&hdr, fifo->tx_data); ++ (*num_avail)--; ++ ++ hdr.type = MLXBF_TMFIFO_MSG_MAC_2; ++ memcpy(hdr.mac, mac + sizeof(hdr.mac), sizeof(hdr.mac)); ++ mlxbf_tmfifo_ctrl_update_checksum(&hdr); ++ writeq(*(u64 *)&hdr, fifo->tx_data); ++ (*num_avail)--; ++ ++ fifo->send_ctrl = 0; ++ } ++} ++ + /* Console Tx (move data from the output buffer into the TmFifo). */ + static void mlxbf_tmfifo_console_tx(struct mlxbf_tmfifo *fifo, int avail) + { +@@ -634,9 +774,11 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring, + /* Drain one word from the FIFO. */ + *(u64 *)&hdr = readq(fifo->rx_data); + +- /* Skip the length 0 packets (keepalive). */ +- if (hdr.len == 0) ++ /* Handle the zero-length packets (control msg). */ ++ if (hdr.len == 0) { ++ mlxbf_tmfifo_ctrl_rx(fifo, &hdr); + return; ++ } + + /* Check packet type. */ + if (hdr.type == VIRTIO_ID_NET) { +@@ -804,6 +946,9 @@ static void mlxbf_tmfifo_rxtx(struct mlxbf_tmfifo_vring *vring, bool is_rx) + + /* Console output always comes from the Tx buffer. */ + if (!is_rx && devid == VIRTIO_ID_CONSOLE) { ++ /* Check if there is any control data to send. */ ++ mlxbf_tmfifo_ctrl_tx(fifo, &avail); ++ + mlxbf_tmfifo_console_tx(fifo, avail); + break; + } +@@ -1149,21 +1294,6 @@ static int mlxbf_tmfifo_delete_vdev(struct mlxbf_tmfifo *fifo, int vdev_id) + return 0; + } + +-/* Read the configured network MAC address from efi variable. */ +-static void mlxbf_tmfifo_get_cfg_mac(u8 *mac) +-{ +- efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID; +- unsigned long size = ETH_ALEN; +- u8 buf[ETH_ALEN]; +- efi_status_t rc; +- +- rc = efi.get_variable(mlxbf_tmfifo_efi_name, &guid, NULL, &size, buf); +- if (rc == EFI_SUCCESS && size == ETH_ALEN) +- ether_addr_copy(mac, buf); +- else +- ether_addr_copy(mac, mlxbf_tmfifo_net_default_mac); +-} +- + /* Set TmFifo thresolds which is used to trigger interrupts. */ + static void mlxbf_tmfifo_set_threshold(struct mlxbf_tmfifo *fifo) + { +@@ -1196,7 +1326,7 @@ static void mlxbf_tmfifo_cleanup(struct mlxbf_tmfifo *fifo) + { + int i; + +- fifo->is_ready = false; ++ fifo->is_ready = 0; + del_timer_sync(&fifo->timer); + mlxbf_tmfifo_disable_irqs(fifo); + cancel_work_sync(&fifo->work); +@@ -1296,7 +1426,7 @@ static int mlxbf_tmfifo_probe(struct platform_device *pdev) + + mod_timer(&fifo->timer, jiffies + MLXBF_TMFIFO_TIMER_INTERVAL); + +- fifo->is_ready = true; ++ fifo->is_ready = 1; + return 0; + + fail: +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0266-UBUNTU-SAUCE-mlxbf-pmc-Bug-fix-for-BlueField-3-count.patch b/platform/mellanox/non-upstream-patches/patches/0266-UBUNTU-SAUCE-mlxbf-pmc-Bug-fix-for-BlueField-3-count.patch new file mode 100644 index 0000000000..12bd08f7da --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0266-UBUNTU-SAUCE-mlxbf-pmc-Bug-fix-for-BlueField-3-count.patch @@ -0,0 +1,94 @@ +From 8cceb490410ba87b8f50ecbc5576f8eaab9f31bd Mon Sep 17 00:00:00 2001 +From: Shravan Kumar Ramani +Date: Tue, 31 Jan 2023 03:20:57 -0500 +Subject: [PATCH 11/12] UBUNTU: SAUCE: mlxbf-pmc: Bug fix for BlueField-3 + counter offsets +X-NVConfidentiality: public + +BugLink: https://bugs.launchpad.net/bugs/2004235 + +The performance counter modules inside each HW block are not +identical and are dependent on the number of counters present +in each case. Hence the offsets for the control and data regs +should be calculated accordingly. + +Signed-off-by: Shravan Kumar Ramani +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/platform/mellanox/mlxbf-pmc.c | 12 +++++++----- + drivers/platform/mellanox/mlxbf-pmc.h | 4 ++-- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 285b7433e..9be5a2d68 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -427,7 +427,8 @@ int mlxbf_clear_crspace_counter(int blk_num, uint32_t cnt_num) + { + void *addr; + +- addr = pmc->block[blk_num].mmio_base + MLXBF_CRSPACE_PERFMON_VAL0 + ++ addr = pmc->block[blk_num].mmio_base + ++ MLXBF_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) + + (cnt_num * 4); + + return mlxbf_pmc_writel(0x0, addr); +@@ -532,7 +533,8 @@ int mlxbf_read_crspace_counter(int blk_num, uint32_t cnt_num, uint64_t *result) + int status = 0; + + status = mlxbf_pmc_readl(&value, pmc->block[blk_num].mmio_base + +- MLXBF_CRSPACE_PERFMON_VAL0 + (cnt_num * 4)); ++ MLXBF_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) + ++ (cnt_num * 4)); + if (status) + return status; + +@@ -935,7 +937,7 @@ static ssize_t mlxbf_show_counter_state(struct kobject *ko, + + if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) { + err = mlxbf_pmc_readl(&word, pmc->block[blk_num].mmio_base + +- MLXBF_CRSPACE_PERFMON_CTL); ++ MLXBF_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters)); + if (err) + return -EINVAL; + value = FIELD_GET(MLXBF_CRSPACE_PERFMON_EN, word); +@@ -967,7 +969,7 @@ static ssize_t mlxbf_enable_counters(struct kobject *ko, + return err; + if (pmc->block[blk_num].type == MLXBF_PERFTYPE_CRSPACE) { + err = mlxbf_pmc_readl(&word, pmc->block[blk_num].mmio_base + +- MLXBF_CRSPACE_PERFMON_CTL); ++ MLXBF_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters)); + if (err) + return -EINVAL; + word &= ~MLXBF_CRSPACE_PERFMON_EN; +@@ -975,7 +977,7 @@ static ssize_t mlxbf_enable_counters(struct kobject *ko, + if (en) + word |= FIELD_PREP(MLXBF_CRSPACE_PERFMON_CLR, 1); + mlxbf_pmc_writel(word, pmc->block[blk_num].mmio_base + +- MLXBF_CRSPACE_PERFMON_CTL); ++ MLXBF_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters)); + } else { + if (en == 0) { + err = mlxbf_config_l3_counters(blk_num, false, false); +diff --git a/drivers/platform/mellanox/mlxbf-pmc.h b/drivers/platform/mellanox/mlxbf-pmc.h +index fe2516616..2ee7efc3b 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.h ++++ b/drivers/platform/mellanox/mlxbf-pmc.h +@@ -152,10 +152,10 @@ struct mlxbf_pmc_context { + #define MLXBF_CRSPACE_PERFMON_REG0 0x0 + #define MLXBF_CRSPACE_PERFSEL0 GENMASK(23, 16) + #define MLXBF_CRSPACE_PERFSEL1 GENMASK(7, 0) +-#define MLXBF_CRSPACE_PERFMON_CTL 0x40 ++#define MLXBF_CRSPACE_PERFMON_CTL(n) (n * 2) + #define MLXBF_CRSPACE_PERFMON_EN BIT(30) + #define MLXBF_CRSPACE_PERFMON_CLR BIT(28) +-#define MLXBF_CRSPACE_PERFMON_VAL0 0x4c ++#define MLXBF_CRSPACE_PERFMON_VAL0(n) (MLXBF_CRSPACE_PERFMON_CTL(n) + 0xc) + + struct mlxbf_pmc_events { + uint32_t evt_num; +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0267-UBUNTU-SAUCE-mmc-sdhci-of-dwcmshc-add-the-missing-de.patch b/platform/mellanox/non-upstream-patches/patches/0267-UBUNTU-SAUCE-mmc-sdhci-of-dwcmshc-add-the-missing-de.patch new file mode 100644 index 0000000000..c61486cf28 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0267-UBUNTU-SAUCE-mmc-sdhci-of-dwcmshc-add-the-missing-de.patch @@ -0,0 +1,36 @@ +From 51ec31f1bfb39fd87dea8861b4642d03cbd6c887 Mon Sep 17 00:00:00 2001 +From: Liming Sun +Date: Fri, 3 Feb 2023 07:52:18 -0500 +Subject: [PATCH 12/12] UBUNTU: SAUCE: mmc: sdhci-of-dwcmshc: add the missing + device table IDs for acpi +X-NVConfidentiality: public + +BugLink: https://bugs.launchpad.net/bugs/2004645 + +This commit adds the missing MODULE_DEVICE_TABLE for acpi, or else +it won't be loaded automatically when compiled as a kernel module. + +Signed-off-by: Liming Sun +Acked-by: Tim Gardner +Acked-by: Bartlomiej Zolnierkiewicz +[bzolnier: use a short URL version for BugLink] +Signed-off-by: Bartlomiej Zolnierkiewicz +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c +index ea972bd3c..565489ee7 100644 +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -349,6 +349,7 @@ static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = { + }, + {} + }; ++MODULE_DEVICE_TABLE(acpi, sdhci_dwcmshc_acpi_ids); + #endif + + static int dwcmshc_probe(struct platform_device *pdev) +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0268-DS-mlxsw-core_linecards-Disable-firmware-bundling-ma.patch b/platform/mellanox/non-upstream-patches/patches/0268-DS-mlxsw-core_linecards-Disable-firmware-bundling-ma.patch new file mode 100644 index 0000000000..aa09114820 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0268-DS-mlxsw-core_linecards-Disable-firmware-bundling-ma.patch @@ -0,0 +1,30 @@ +From a98a8781b6a6fad632a0fcaa3c78a05007b15f2e Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 20 Feb 2023 15:15:46 +0200 +Subject: [PATCH net backport 5.10 1/1] DS: mlxsw: core_linecards: Disable + firmware bundling macros + +Remove line card firmware bundling flow in non upstream environment to +avoid warning in case path /lib/firmware/mellanox is not available. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core_linecards.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +index 30665a6f3..4bae0643a 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +@@ -1501,5 +1501,7 @@ void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core, + } + } + EXPORT_SYMBOL(mlxsw_linecards_event_ops_unregister); +- ++/* Skip for non-upstream flow. */ ++#if 0 + MODULE_FIRMWARE(MLXSW_LINECARDS_INI_BUNDLE_FILE); ++#endif +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0269-platform-mellanox-Cosmetic-changes.patch b/platform/mellanox/non-upstream-patches/patches/0269-platform-mellanox-Cosmetic-changes.patch new file mode 100644 index 0000000000..18dc177ede --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0269-platform-mellanox-Cosmetic-changes.patch @@ -0,0 +1,74 @@ +From da7c9365e155de2a038cbc1cded3a56ea9a363aa Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 27 Feb 2023 15:24:43 +0000 +Subject: [PATCH backport 5.10 1/3] platform: mellanox: Cosmetic changes + +Fix routines and labels names by s/topology/topology. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 849fdf5de..656056089 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -6876,7 +6876,7 @@ mlxplat_i2c_mux_complition_notify(void *handle, struct i2c_adapter *parent, + return 0; + } + +-static int mlxplat_i2c_mux_topolgy_init(struct mlxplat_priv *priv) ++static int mlxplat_i2c_mux_topology_init(struct mlxplat_priv *priv) + { + int i, err; + +@@ -6921,7 +6921,7 @@ static int mlxplat_i2c_mux_topolgy_init(struct mlxplat_priv *priv) + return err; + } + +-static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv) ++static void mlxplat_i2c_mux_topology_exit(struct mlxplat_priv *priv) + { + int i; + +@@ -6937,7 +6937,7 @@ static int mlxplat_i2c_main_complition_notify(void *handle, int id) + { + struct mlxplat_priv *priv = handle; + +- return mlxplat_i2c_mux_topolgy_init(priv); ++ return mlxplat_i2c_mux_topology_init(priv); + } + + static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) +@@ -6964,14 +6964,14 @@ static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) + } + + if (priv->i2c_main_init_status == MLXPLAT_I2C_MAIN_BUS_NOTIFIED) { +- err = mlxplat_i2c_mux_topolgy_init(priv); ++ err = mlxplat_i2c_mux_topology_init(priv); + if (err) +- goto fail_mlxplat_i2c_mux_topolgy_init; ++ goto fail_mlxplat_i2c_mux_topology_init; + } + + return 0; + +-fail_mlxplat_i2c_mux_topolgy_init: ++fail_mlxplat_i2c_mux_topology_init: + fail_platform_i2c_register: + fail_mlxplat_mlxcpld_verify_bus_topology: + return err; +@@ -6979,7 +6979,7 @@ static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) + + static void mlxplat_i2c_main_exit(struct mlxplat_priv *priv) + { +- mlxplat_i2c_mux_topolgy_exit(priv); ++ mlxplat_i2c_mux_topology_exit(priv); + if (priv->pdev_i2c) + platform_device_unregister(priv->pdev_i2c); + } +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0270-platform-mellanox-Fix-order-in-exit-flow.patch b/platform/mellanox/non-upstream-patches/patches/0270-platform-mellanox-Fix-order-in-exit-flow.patch new file mode 100644 index 0000000000..4bbbe389aa --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0270-platform-mellanox-Fix-order-in-exit-flow.patch @@ -0,0 +1,39 @@ +From 89d0e497e62b90e8faa2b67c298cedeab47b8f8b Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 27 Feb 2023 16:09:17 +0000 +Subject: [PATCH backport 5.10 2/3] platform: mellanox: Fix order in exit flow + +Fix exit flow order: call mlxplat_post_exit() after +mlxplat_i2c_main_exit() in order to unregister main i2c driver before +to "mlxplat" driver. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 656056089..42fd7e4e0 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -6929,8 +6929,6 @@ static void mlxplat_i2c_mux_topology_exit(struct mlxplat_priv *priv) + if (priv->pdev_mux[i]) + platform_device_unregister(priv->pdev_mux[i]); + } +- +- mlxplat_post_exit(); + } + + static int mlxplat_i2c_main_complition_notify(void *handle, int id) +@@ -7068,6 +7066,7 @@ static void __exit mlxplat_exit(void) + unregister_reboot_notifier(mlxplat_reboot_nb); + mlxplat_pre_exit(priv); + mlxplat_i2c_main_exit(priv); ++ mlxplat_post_exit(); + } + module_exit(mlxplat_exit); + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0271-platform-mellanox-Add-new-attributes.patch b/platform/mellanox/non-upstream-patches/patches/0271-platform-mellanox-Add-new-attributes.patch new file mode 100644 index 0000000000..92044c45bf --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0271-platform-mellanox-Add-new-attributes.patch @@ -0,0 +1,49 @@ +From 6cb8f4e432f8209a3775877d690a979a2e786afc Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 27 Feb 2023 18:56:09 +0000 +Subject: [PATCH backport 5.10 3/3] platform: mellanox: Add new attributes + +Add two new attributes: +"lid_open" - to indicate system intrusion detection. +"reset_long_pwr_pb" - to indicate that system has been reset due to +long press of power button. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 42fd7e4e0..4eb327720 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -4067,6 +4067,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0444, + }, ++ { ++ .label = "lid_open", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, + { + .label = "clk_brd1_boot_fail", + .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, +@@ -4706,6 +4712,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_chassis_blade_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(6), + .mode = 0444, + }, ++ { ++ .label = "reset_long_pwr_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, + { + .label = "pwr_cycle", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0272-platform-mellanox-Change-register-offset-addresses.patch b/platform/mellanox/non-upstream-patches/patches/0272-platform-mellanox-Change-register-offset-addresses.patch new file mode 100644 index 0000000000..a5596171c9 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0272-platform-mellanox-Change-register-offset-addresses.patch @@ -0,0 +1,43 @@ +From 020ab13e16f943bb66da221507f83634a7d9ca05 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 1 Mar 2023 17:21:48 +0000 +Subject: [PATCH backport 5.10 4/5] platform: mellanox: Change register offset + addresses + +Move debug register offsets to different location due to hardware changes. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 4eb327720..b5d51673f 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -66,10 +66,6 @@ + #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 + #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a + #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b +-#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0x3c +-#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0x3d +-#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0x3e +-#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0x3f + #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 + #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 + #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 +@@ -130,6 +126,10 @@ + #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa + #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab + #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2 ++#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0xb6 ++#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0xb7 ++#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0xb8 ++#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0xb9 + #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 + #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 + #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0273-platform-mellanox-Add-field-upgrade-capability-regis.patch b/platform/mellanox/non-upstream-patches/patches/0273-platform-mellanox-Add-field-upgrade-capability-regis.patch new file mode 100644 index 0000000000..0e1c1b469c --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0273-platform-mellanox-Add-field-upgrade-capability-regis.patch @@ -0,0 +1,72 @@ +From 96de5181b880adf2fd65fa85fbc3e0c74f976788 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 1 Mar 2023 17:49:08 +0000 +Subject: [PATCH backport 5.10 5/6] platform: mellanox: Add field upgrade + capability register + +Add new register to indicate the method of FPGA/CPLD field upgrade +supported on the specific system. +Currently two masks are available: +b00 - field upgrade through LPC gateway (new method introduced to + accelerate field upgrade process). +b11 - field upgrade through CPU GPIO pins (old method). + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index b5d51673f..f674d9173 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -66,6 +66,7 @@ + #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 + #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a + #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b ++#define MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET 0x3c + #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 + #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 + #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 +@@ -241,6 +242,7 @@ + #define MLXPLAT_CPLD_VOLTREG_UPD_MASK GENMASK(5, 4) + #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) + #define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) ++#define MLXPLAT_CPLD_FU_CAP_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) + #define MLXPLAT_CPLD_LATCH_RST_MASK BIT(5) + #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) +@@ -3956,6 +3958,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(5), + .mode = 0200, + }, ++ { ++ .label = "jtag_cap", ++ .reg = MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET, ++ .mask = MLXPLAT_CPLD_FU_CAP_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, + { + .label = "jtag_enable", + .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, +@@ -5424,6 +5433,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: +@@ -5582,6 +5592,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0274-platform-mellanox-Modify-reset-causes-description.patch b/platform/mellanox/non-upstream-patches/patches/0274-platform-mellanox-Modify-reset-causes-description.patch new file mode 100644 index 0000000000..62b5635661 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0274-platform-mellanox-Modify-reset-causes-description.patch @@ -0,0 +1,53 @@ +From f8a0954053e6e06070ed399e1810bea089ba36bd Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 2 Mar 2023 12:28:11 +0000 +Subject: [PATCH backport v.5.10 4/8] platform: mellanox: Modify reset causes + description + +Link: https://patchwork.kernel.org/project/platform-driver-x86/patch/20230814203406.12399-4-vadimp@nvidia.com/ + +For system of classes VMOD0005, VMOD0010: +- remove "reset_from_comex", since this cause doesn't define specific + reason. +- add more speicific reason "reset_sw_reset", which is set along with + removed "reset_from_comex". + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 486a3e8da..67865636e 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -3832,12 +3832,6 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(2), + .mode = 0444, + }, +- { +- .label = "reset_from_comex", +- .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, +- .mask = GENMASK(7, 0) & ~BIT(4), +- .mode = 0444, +- }, + { + .label = "reset_from_asic", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, +@@ -3856,6 +3850,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mask = GENMASK(7, 0) & ~BIT(7), + .mode = 0444, + }, ++ { ++ .label = "reset_sw_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, + { + .label = "reset_comex_pwr_fail", + .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0275-mlxsw-Use-u16-for-local_port-field-instead-of-u8.patch b/platform/mellanox/non-upstream-patches/patches/0275-mlxsw-Use-u16-for-local_port-field-instead-of-u8.patch new file mode 100644 index 0000000000..02c1a875ea --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0275-mlxsw-Use-u16-for-local_port-field-instead-of-u8.patch @@ -0,0 +1,61 @@ +From 2aa5016c277751bcc11c6874a58abbe194708f9f Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 9 Mar 2023 22:37:40 +0000 +Subject: [PATCH backport v.5.10 2/3] mlxsw: Use u16 for local_port field + instead of u8 + +Currently, local_port field is saved as u8, which means that maximum 256 +ports can be used. + +As preparation for Spectrum-4, which will support more than 256 ports, +local_port field should be extended. + +Save local_port as u16 to allow use of additional ports. + +Signed-off-by: Amit Cohen +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 4 ++-- + drivers/net/ethernet/mellanox/mlxsw/core.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index a26c6d880..9475cd656 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -2842,7 +2842,7 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, + } + EXPORT_SYMBOL(mlxsw_core_res_get); + +-static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, ++static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, + enum devlink_port_flavour flavour, + u8 slot_index, u32 port_number, bool split, + u32 split_port_subnumber, +@@ -2892,7 +2892,7 @@ static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port) + memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); + } + +-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, ++int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, + u8 slot_index, u32 port_number, bool split, + u32 split_port_subnumber, + bool splittable, u32 lanes, +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h +index b09f9013d..842f365eb 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.h +@@ -213,7 +213,7 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core, + u16 lag_id, u8 local_port); + + void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port); +-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port, ++int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, + u8 slot_index, u32 port_number, bool split, + u32 split_port_subnumber, + bool splittable, u32 lanes, +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0276-mlxsw-minimal-Change-type-for-local-port.patch b/platform/mellanox/non-upstream-patches/patches/0276-mlxsw-minimal-Change-type-for-local-port.patch new file mode 100644 index 0000000000..0a2b7f6188 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0276-mlxsw-minimal-Change-type-for-local-port.patch @@ -0,0 +1,41 @@ +From 299ee861fd4b081f0ab5d168048c9696a12de2f5 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 9 Mar 2023 09:05:38 +0000 +Subject: [PATCH backport v.5.10 1/3] mlxsw: minimal: Change type for local + port + +Since maximum port number available on system has been increased from +128 to 258, change relevant types from u8 to u16: +- 'max_ports' field in structure 'mlxsw_m'; +- 'local_port' argument in mlxsw_m_port_mapping_get(). + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +index 5fd319697..9f74ca704 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c +@@ -31,7 +31,7 @@ struct mlxsw_m { + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; + u8 base_mac[ETH_ALEN]; +- u8 max_ports; ++ u16 max_ports; + u8 max_module_count; /* Maximum number of modules per-slot. */ + u8 num_of_slots; /* Including the main board. */ + struct mlxsw_m_line_card **line_cards; +@@ -230,7 +230,7 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) + + static struct + mlxsw_m_port_mapping *mlxsw_m_port_mapping_get(struct mlxsw_m *mlxsw_m, +- u8 slot_index, u8 local_port) ++ u8 slot_index, u16 local_port) + { + return &mlxsw_m->line_cards[slot_index]->port_mapping[local_port]; + } +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0277-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch b/platform/mellanox/non-upstream-patches/patches/0277-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch new file mode 100644 index 0000000000..7f3a514307 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0277-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch @@ -0,0 +1,41 @@ +From b66ec3f67d61b7e380c61a12771cc2fee2f0a10e Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 9 Mar 2023 09:16:33 +0000 +Subject: [PATCH backport v.5.10 3/3] mlxsw: i2c: Fix chunk size setting in + output mailbox buffer + +Set output mailbox buffer size multiple of minimal chunk size (32). + +Full buffer size is 256 bytes, while chunk size, which can be sent to +device on some controllers could be for example 32 + 4, 64 + 4, 128 + +4. Thus, last chunk maybe missed, and transaction tail will be lost. + +For example, if transaction size is 256 bytes and chunk size is 64 + 4, +only 204 (68 * 3) bytes will be read instead of 256. + +With this fix chunk size will be multiple of 2^n (where n could be 5, 6, +7) and last chunk will be handled. + +Fixes: 95b75cbd1bc5 ("mlxsw: i2c: Extend input parameters list of command API") +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/i2c.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +index ba31540f1..e04557afc 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c +@@ -466,7 +466,8 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size, + } else { + /* No input mailbox is case of initialization query command. */ + reg_size = MLXSW_I2C_MAX_DATA_SIZE; +- num = reg_size / mlxsw_i2c->block_size; ++ num = reg_size / (mlxsw_i2c->block_size - ++ (mlxsw_i2c->block_size % MLXSW_I2C_BLK_DEF)); + + if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { + dev_err(&client->dev, "Could not acquire lock"); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0278-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch b/platform/mellanox/non-upstream-patches/patches/0278-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch new file mode 100644 index 0000000000..72e4b19bb3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0278-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch @@ -0,0 +1,43 @@ +From 8b83fb501ac77d60e1cc30fac63e71f469ba0992 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Fri, 10 Mar 2023 09:15:35 +0000 +Subject: [PATCH backport v.5.10 1/1] platform: mellanox: mlx-platform: Modify + graceful shutdown callback and power down mask + +Use kernel_power_off() instead of kernel_halt() to pass through +machine_power_off() -> pm_power_off(), otherwise axillary power does +not go off. + +Change "power down" bitmask. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 67865636e..55afb4c90 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -227,7 +227,7 @@ + MLXPLAT_CPLD_AGGR_MASK_LC_SDWN) + #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 + #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2) +-#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT BIT(4) ++#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT GENMASK(5,4) + #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6) + #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) +@@ -2509,7 +2509,7 @@ mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_k + u8 action) + { + dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); +- kernel_halt(); ++ kernel_power_off(); + return 0; + } + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0279-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch b/platform/mellanox/non-upstream-patches/patches/0279-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch new file mode 100644 index 0000000000..6cd5cddd15 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0279-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch @@ -0,0 +1,59 @@ +From 6720a3b49d3c0bb26d18bfe651bd9101dde34fc8 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 15 Mar 2023 19:23:20 +0000 +Subject: [PATCH backport v.5.10 1/3] platform: mellanox: mlx-platform: Fix + signals polarity and latch mask + +Change polarity of chassis health and power signals and fix latch reset +mask for L1 switch. + +Fixes: dd635e33b5c9 ("platform: mellanox: Introduce support of new Nvidia L1 switch") +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index fa2e539b6..2bc3720a4 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -244,7 +244,7 @@ + #define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_FU_CAP_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) +-#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(5) ++#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(6) + #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) + #define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4) + #define MLXPLAT_CPLD_INTRUSION_MASK BIT(6) +@@ -2631,7 +2631,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = { + .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, + .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, + .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data), +- .inversed = 0, ++ .inversed = 1, + .health = false, + }, + { +@@ -2640,7 +2640,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = { + .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, + .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK, + .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data), +- .inversed = 0, ++ .inversed = 1, + .health = false, + .ind = 8, + }, +@@ -3958,7 +3958,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + { + .label = "latch_reset", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, +- .mask = GENMASK(7, 0) & ~BIT(5), ++ .mask = GENMASK(7, 0) & ~BIT(6), + .mode = 0200, + }, + { +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0280-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch b/platform/mellanox/non-upstream-patches/patches/0280-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch new file mode 100644 index 0000000000..68f8a792df --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0280-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch @@ -0,0 +1,33 @@ +From 6531f28d37beb20fb423f4835eab47beaaf002bb Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 19 Mar 2023 15:04:26 +0000 +Subject: [PATCH backport v.5.10 2/3] platform/mellanox: mlxreg-hotplug: Extend + condition for notification callback processing + +Allow processing of notification callback in routine +mlxreg_hotplug_device_create() in case hotplug object is configured +with action "MLXREG_HOTPLUG_DEVICE_NO_ACTION" in case no I2C parent bus +is specified. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlxreg-hotplug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c +index b7dcc64cd..c5abedd35 100644 +--- a/drivers/platform/mellanox/mlxreg-hotplug.c ++++ b/drivers/platform/mellanox/mlxreg-hotplug.c +@@ -113,7 +113,7 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, + * Return if adapter number is negative. It could be in case hotplug + * event is not associated with hotplug device. + */ +- if (data->hpdev.nr < 0) ++ if (data->hpdev.nr < 0 && data->hpdev.action != MLXREG_HOTPLUG_DEVICE_NO_ACTION) + return 0; + + pdata = dev_get_platdata(&priv->pdev->dev); +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0281-platform-mellanox-mlx-platform-Modify-health-and-pow.patch b/platform/mellanox/non-upstream-patches/patches/0281-platform-mellanox-mlx-platform-Modify-health-and-pow.patch new file mode 100644 index 0000000000..f6b38f9712 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0281-platform-mellanox-mlx-platform-Modify-health-and-pow.patch @@ -0,0 +1,40 @@ +From 718681c7948f3191fe7ab7cc0a5f96b6454c3a0b Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Sun, 19 Mar 2023 15:36:19 +0000 +Subject: [PATCH backport v.5.10 3/3] platform: mellanox: mlx-platform: Modify + health and power hotplug action + +Set explicitly hotplug event action for health and power signals for +L1 switch as "MLXREG_HOTPLUG_DEVICE_NO_ACTION" in order to allow +processing of notification callback even I2C parent bus is not +specified. + +Signed-off-by: Vadim Pasternak +Reviewed-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 2bc3720a4..605d57e95 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -2527,6 +2527,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_pwr_events_items_data[] + .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, + .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, + .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_pwr_events_notifier, + }, + }; +@@ -2587,6 +2588,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_health_events_items_dat + .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, + .mask = MLXPLAT_CPLD_INTRUSION_MASK, + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, + .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_intrusion_events_notifier, + }, + { +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0282-platform-mellanox-mlx-platform-add-support-of-5th-CP.patch b/platform/mellanox/non-upstream-patches/patches/0282-platform-mellanox-mlx-platform-add-support-of-5th-CP.patch new file mode 100644 index 0000000000..24f024a822 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0282-platform-mellanox-mlx-platform-add-support-of-5th-CP.patch @@ -0,0 +1,129 @@ +From b37820018a651f9f8bfe3a9c3fe0e90e49add58b Mon Sep 17 00:00:00 2001 +From: Michael Shych +Date: Tue, 9 May 2023 11:06:39 +0000 +Subject: [PATCH v1 1/1] platform: mellanox: mlx-platform: add support of 5th + CPLD. + +Add 5th CPLD version, PN and minimal version registers. + +Signed-off-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 33 ++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 605d57e95..dc6b7ad2c 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -99,6 +99,9 @@ + #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 + #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 + #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a ++#define MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET 0x8e ++#define MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET 0x8f ++#define MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET 0x90 + #define MLXPLAT_CPLD_LPC_REG_EROT_OFFSET 0x91 + #define MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET 0x92 + #define MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET 0x93 +@@ -133,6 +136,7 @@ + #define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0xb9 + #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 + #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 ++#define MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET 0xc4 + #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 + #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8 + #define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9 +@@ -3713,6 +3717,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .bit = GENMASK(7, 0), + .mode = 0444, + }, ++ { ++ .label = "cpld5_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, + { + .label = "cpld1_pn", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, +@@ -3741,6 +3751,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .mode = 0444, + .regnum = 2, + }, ++ { ++ .label = "cpld5_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, + { + .label = "cpld1_version_min", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, +@@ -3765,6 +3782,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + .bit = GENMASK(7, 0), + .mode = 0444, + }, ++ { ++ .label = "cpld5_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, + { + .label = "asic_reset", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, +@@ -5404,6 +5427,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: +@@ -5412,6 +5436,8 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: +@@ -5524,6 +5550,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: +@@ -5565,14 +5592,15 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD1_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET: +- case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: +- case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: +@@ -5677,6 +5705,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0283-mlxsw-core_hwmon-Align-modules-label-name-assignment.patch b/platform/mellanox/non-upstream-patches/patches/0283-mlxsw-core_hwmon-Align-modules-label-name-assignment.patch new file mode 100644 index 0000000000..15d55ab0c3 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0283-mlxsw-core_hwmon-Align-modules-label-name-assignment.patch @@ -0,0 +1,50 @@ +From 41dd6c60de14f70908fc03ed2c20aa35ae0d1596 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 19 Jun 2023 09:53:41 +0000 +Subject: [PATCH backport 5.10 3/3] mlxsw: core_hwmon: Align modules label name + assignment according to the MTCAP sensor counter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For some new devices MTCAP register provides the counter of ASIC +ambient sensors plus additional number of platform sensors. +In such case 'sensor count' will be greater then 1 and modules labels +will be shifted by the number of platform sensors. + +Thus utilities sensors will expose incorrect modules labels. +For example, temperatures for module#1, module#2 will be exposed like: +front panel 002: +37.0°C (crit = +70.0°C, emerg = +75.0°C) +front panel 003: +47.0°C (crit = +70.0°C, emerg = +75.0°C) +instead of: +front panel 001: +37.0°C (crit = +70.0°C, emerg = +75.0°C) +front panel 002: +47.0°C (crit = +70.0°C, emerg = +75.0°C) + +Set 'index' used in label name according to the 'sensor_count' value. + +Signed-off-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +index a27146cca..f80050cec 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +@@ -412,6 +412,13 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, + int index = mlxsw_hwmon_attr->type_index; + + mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; ++ /* For some devices 'sensor count' provides the number of ASIC sensor ++ * plus additional platform sensors. Set 'index' used in label name ++ * according to the 'sensor_count' value to align label name with the ++ * module index. ++ */ ++ if (mlxsw_hwmon_dev->sensor_count > 1) ++ index += 1 - mlxsw_hwmon_dev->sensor_count; + if (strlen(mlxsw_hwmon_dev->name)) + index += 1; + +-- +2.20.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/0284-platform-mellanox-mlx-platform-fix-CPLD4-PN-report.patch b/platform/mellanox/non-upstream-patches/patches/0284-platform-mellanox-mlx-platform-fix-CPLD4-PN-report.patch new file mode 100644 index 0000000000..72f021eee4 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/0284-platform-mellanox-mlx-platform-fix-CPLD4-PN-report.patch @@ -0,0 +1,32 @@ +From 21cafe13f2452a7c41c623dc63af9cbaa301108d Mon Sep 17 00:00:00 2001 +From: Michael Shych +Date: Wed, 28 Jun 2023 12:23:43 +0000 +Subject: [PATCH v1 1/1] platform: mellanox: mlx-platform: fix CPLD4 PN report. + +Add two lines from upstream commits: +[9045512ca6cdb221cd1ed32d483eac3c30c53bed] +[ae1aabf44bd672a07c4fa3ef56f069ed7daa7823] + +Fix PN report of CPLD4. + +Signed-off-by: Michael Shych +--- + drivers/platform/mellanox/mlx-platform.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index 00e62366b..641e7fe1f 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -5605,6 +5605,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD2_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/patches/9002-TMP-fix-for-fan-minimum-speed.patch b/platform/mellanox/non-upstream-patches/patches/9002-TMP-fix-for-fan-minimum-speed.patch new file mode 100644 index 0000000000..fa47c1c914 --- /dev/null +++ b/platform/mellanox/non-upstream-patches/patches/9002-TMP-fix-for-fan-minimum-speed.patch @@ -0,0 +1,26 @@ +From 91a6100aaadcea0a30d91a32897ef21452e48460 Mon Sep 17 00:00:00 2001 +From: Oleksandr Shamray +Date: Tue, 4 Apr 2023 09:56:48 +0000 +Subject: [PATCH] TMP fix for fan minimum speed + +Signed-off-by: Oleksandr Shamray +--- + drivers/hwmon/mlxreg-fan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c +index 5a93fc0..b999ca6 100644 +--- a/drivers/hwmon/mlxreg-fan.c ++++ b/drivers/hwmon/mlxreg-fan.c +@@ -364,7 +364,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, + * For configuration non-zero value is to be returned to avoid thermal + * statistics update. + */ +- config = 1; ++ config = 0; /*1*/; + state -= MLXREG_FAN_MAX_STATE; + for (i = 0; i < state; i++) + pwm->cooling_levels[i] = state; +-- +2.14.1 + diff --git a/platform/mellanox/non-upstream-patches/series.patch b/platform/mellanox/non-upstream-patches/series.patch index 80cb652afb..786c33ea9b 100644 --- a/platform/mellanox/non-upstream-patches/series.patch +++ b/platform/mellanox/non-upstream-patches/series.patch @@ -1,11 +1,22 @@ -diff --git a/patch/series b/patch/series -index e86f858..61144ff 100755 --- a/patch/series +++ b/patch/series -@@ -155,12 +155,71 @@ kernel-compat-always-include-linux-compat.h-from-net-compat.patch - 0097-hwmon-mlxreg-fan-Support-distinctive-names-per-.patch - 0999-Revert-mlxsw-thermal-Fix-out-of-bounds-memory-a.patch - 0098-mlxsw-i2c-Prevent-transaction-execution-for.patch +@@ -108,6 +108,9 @@ + 0045-i2c-mlxcpld-Fix-criteria-for-frequency-setting.patch + 0046-i2c-mlxcpld-Reduce-polling-time-for-performance-impr.patch + 0047-i2c-mlxcpld-Allow-flexible-polling-time-setting-for-.patch ++0049-leds-mlxreg-Provide-conversion-for-hardware-LED-colo.patch ++0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch ++0051-leds-mlxreg-Allow-multi-instantiation-of-same-name-L.patch + 0053-mlxsw-core-Avoid-creation-virtual-hwmon-objects-by-t.patch + 0054-mlxsw-minimal-Simplify-method-of-modules-number-dete.patch + 0055-platform_data-mlxreg-Add-new-type-to-support-modular.patch +@@ -155,7 +158,68 @@ + 0097-1-mlxsw-Use-u16-for-local_port-field.patch + 0097-2-mlxsw-i2c-Fix-chunk-size-setting.patch + 0097-3-mlxsw-core_hwmon-Adjust-module-label-names.patch ++0098-1-Revert-mlxsw-Use-u16-for-local_port-field.patch ++0098-2-Revert-mlxsw-i2c-Fix-chunk-size-setting.patch ++0098-3-Revert-mlxsw-core_hwmon-Adjust-module-label-names.patch +0099-mlxsw-core_hwmon-Fix-variable-names-for-hwmon-attrib.patch +0100-mlxsw-core_thermal-Rename-labels-according-to-naming.patch +0101-mlxsw-core_thermal-Remove-obsolete-API-for-query-res.patch @@ -60,6 +71,7 @@ index e86f858..61144ff 100755 +0150-mlxsw-core_hwmon-Add-interfaces-for-line-card-initia.patch +0151-mlxsw-minimal-Prepare-driver-for-modular-system-supp.patch +0152-mlxsw-core-Extend-bus-init-function-with-event-handl.patch + 0152-mlxsw-i2c-Prevent-transaction-execution-for-spec.patch +0153-mlxsw-i2c-Add-support-for-system-events-handling.patch +0154-mlxsw-core-Export-line-card-API.patch +0155-mlxsw-minimal-Add-system-event-handler.patch @@ -67,20 +79,129 @@ index e86f858..61144ff 100755 0157-platform-x86-mlx-platform-Make-activation-of-some-dr.patch 0158-platform-x86-mlx-platform-Add-cosmetic-changes-for-a.patch 0159-mlx-platform-Add-support-for-systems-equipped-with-t.patch - 0160-platform-mellanox-Introduce-support-for-COMe-NVSwitc.patch - 0161-platform-x86-mlx-platform-Add-support-for-new-system.patch - 0162-platform-mellanox-Add-COME-board-revision-register.patch -+0163-platform-mellanox-Introduce-support-for-rack-manager.patch +@@ -166,21 +230,125 @@ 0164-hwmon-jc42-Add-support-for-Seiko-Instruments-S-34TS0.patch 0165-platform-mellanox-mlxreg-io-Add-locking-for-io-opera.patch - 0167-leds-mlxreg-Send-udev-change-event.patch -@@ -168,6 +227,9 @@ kernel-compat-always-include-linux-compat.h-from-net-compat.patch - 0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch - 0173-core-Add-support-for-OSFP-transceiver-modules.patch + 0166-DS-leds-leds-mlxreg-Send-udev-event-from-leds-mlxreg.patch ++0167-DS-lan743x-Add-support-for-fixed-phy.patch ++0168-TMP-mlxsw-minimal-Ignore-error-reading-SPAD-register.patch + 0170-i2c-mlxcpld-Fix-register-setting-for-400KHz-frequenc.patch ++0171-platform-mellanox-mlxreg-lc-Fix-cleanup-on-failure-a.patch ++0172-DS-platform-mlx-platform-Add-SPI-path-for-rack-switc.patch + 0173-mlxsw-core-Add-support-for-OSFP-transceiver-modules.patch ++0174-DS-mlxsw-core_linecards-Skip-devlink-and-provisionin.patch 0175-hwmon-pmbus-Add-support-for-Infineon-Digital-Multi-p.patch -+0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch -+0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch -+0178-platform-mellanox-Introduce-support-for-next-generat.patch + 0176-platform-mellanox-fix-reset_pwr_converter_fail-attri.patch + 0177-Documentation-ABI-fix-description-of-fix-reset_pwr_c.patch + 0178-platform-mellanox-Introduce-support-for-next-generat.patch 0180-hwmon-pmbus-Fix-sensors-readouts-for-MPS-Multi-phase.patch ++0181-Revert-Fix-out-of-bounds-memory-accesses-in-thermal.patch ++0182-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch ++0183-platform-mellanox-Split-initialization-procedure.patch ++0184-platform-mellanox-Split-logic-in-init-and-exit-flow.patch ++0185-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch + 0186-platform-mellanox-mlxreg-hotplug-Allow-more-flexible.patch ++0187-platform_data-mlxreg-Add-field-with-mapped-resource-.patch ++0188-i2c-mux-Add-register-map-based-mux-driver.patch ++0189-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch ++0190-i2c-mlxcpld-Modify-base-address-type.patch ++0191-i2c-mlxcpld-Allow-to-configure-base-address-of-regis.patch ++0192-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch ++0193-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch ++0194-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch ++0195-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch + 0195-platform-x86-MLX_PLATFORM-select-REGMAP-instead-of-d.patch ++0196-platform-mellanox-Relocate-mlx-platform-driver.patch ++0197-platform-mellanox-Add-initial-support-for-PCIe-based.patch ++0198-platform-mellanox-Introduce-support-for-switches-bas.patch ++0199-platform-mellanox-mlx-platform-Add-reset-and-extend-.patch ++0200-dt-bindings-i2c-mellanox-i2c-mlxbf-convert-txt-to-YA.patch + 0201-i2c-mlxbf-incorrect-base-address-passed-during-io-wr.patch + 0202-i2c-mlxbf-prevent-stack-overflow-in-mlxbf_i2c_smbus_.patch ++0203-i2c-mlxbf-remove-IRQF_ONESHOT.patch + 0204-i2c-mlxbf-Fix-frequency-calculation.patch + 0205-i2c-mlxbf-support-lock-mechanism.patch ++0206-i2c-mlxbf-add-multi-slave-functionality.patch ++0207-i2c-mlxbf-support-BlueField-3-SoC.patch ++0208-i2c-mlxbf-remove-device-tree-support.patch ++0209-UBUNTU-SAUCE-i2c-mlxbf.c-Add-driver-version.patch ++0210-platform-mellanox-Typo-fix-in-the-file-mlxbf-bootctl.patch ++0211-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-boot.patch ++0212-platform-mellanox-mlxbf-pmc-Add-Mellanox-BlueField-P.patch ++0213-platform-mellanox-mlxbf-pmc-fix-kernel-doc-notation.patch ++0214-platform-mellanox-mlxbf-pmc-Fix-an-IS_ERR-vs-NULL-bu.patch ++0215-UBUNTU-SAUCE-platform-mellanox-Updates-to-mlxbf-pmc.patch ++0216-UBUNTU-SAUCE-mlxbf_pmc-Fix-references-to-sprintf.patch ++0217-UBUNTU-SAUCE-mlxbf-pmc-Fix-error-when-reading-unprog.patch ++0218-UBUNTU-SAUCE-platform-mellanox-Add-mlx-trio-driver.patch ++0219-UBUNTU-SAUCE-platform-mellanox-mlxbf-tmfifo-Add-Blue.patch ++0220-UBUNTU-SAUCE-pka-Add-pka-driver.patch ++0221-UBUNTU-SAUCE-platform-mellanox-Add-mlxbf-livefish-dr.patch ++0222-workqueue-Add-resource-managed-version-of-delayed-wo.patch ++0223-devm-helpers-Fix-devm_delayed_work_autocancel-kernel.patch ++0224-devm-helpers-Add-resource-managed-version-of-work-in.patch ++0225-UBUNTU-SAUCE-Add-support-to-pwr-mlxbf.c-driver.patch ++0226-Add-Mellanox-BlueField-Gigabit-Ethernet-driver.patch ++0227-mlxbf_gige-clear-valid_polarity-upon-open.patch ++0228-net-mellanox-mlxbf_gige-Replace-non-standard-interru.patch ++0229-mlxbf_gige-increase-MDIO-polling-rate-to-5us.patch ++0230-mlxbf_gige-remove-driver-managed-interrupt-counts.patch ++0231-mlxbf_gige-remove-own-module-name-define-and-use-KBU.patch ++0232-UBUNTU-SAUCE-mlxbf_gige-add-ethtool-mlxbf_gige_set_r.patch ++0233-UBUNTU-SAUCE-Fix-OOB-handling-RX-packets-in-heavy-tr.patch ++0234-UBUNTU-SAUCE-mlxbf_gige-add-validation-of-ACPI-table.patch ++0235-UBUNTU-SAUCE-mlxbf_gige-set-driver-version-to-1.27.patch ++0236-UBUNTU-SAUCE-mlxbf_gige-clear-MDIO-gateway-lock-afte.patch ++0237-mlxbf_gige-compute-MDIO-period-based-on-i1clk.patch ++0238-net-mlxbf_gige-Fix-an-IS_ERR-vs-NULL-bug-in-mlxbf_gi.patch ++0239-UBUNTU-SAUCE-mlxbf_gige-add-MDIO-support-for-BlueFie.patch ++0240-UBUNTU-SAUCE-mlxbf_gige-support-10M-100M-1G-speeds-o.patch ++0241-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-Serdes-confi.patch ++0242-UBUNTU-SAUCE-mlxbf_gige-add-BlueField-3-ethtool_ops.patch ++0243-UBUNTU-SAUCE-bluefield_edac-Add-SMC-support.patch ++0244-UBUNTU-SAUCE-bluefield_edac-Update-license-and-copyr.patch ++0245-gpio-mlxbf2-Convert-to-device-PM-ops.patch ++0246-gpio-mlxbf2-Drop-wrong-use-of-ACPI_PTR.patch ++0247-gpio-mlxbf2-Use-devm_platform_ioremap_resource.patch ++0248-gpio-mlxbf2-Use-DEFINE_RES_MEM_NAMED-helper-macro.patch ++0249-gpio-mlxbf2-Introduce-IRQ-support.patch ++0250-UBUNTU-SAUCE-gpio-mlxbf2.c-support-driver-version.patch ++0251-mmc-sdhci-of-dwcmshc-add-rockchip-platform-support.patch ++0252-mmc-sdhci-of-dwcmshc-add-ACPI-support-for-BlueField-.patch ++0253-mmc-sdhci-of-dwcmshc-fix-error-return-code-in-dwcmsh.patch ++0254-mmc-sdhci-of-dwcmshc-set-MMC_CAP_WAIT_WHILE_BUSY.patch ++0255-mmc-sdhci-of-dwcmshc-Re-enable-support-for-the-BlueF.patch ++0256-UBUNTU-SAUCE-Support-BlueField-3-GPIO-driver.patch ++0257-regmap-debugfs-Enable-writing-to-the-regmap-debugfs-.patch ++0258-UBUNTU-SAUCE-mlx-bootctl-support-icm-carveout-eeprom.patch ++0259-mmc-sdhci-of-dwcmshc-Enable-host-V4-support-for-Blue.patch ++0260-UBUNTU-SAUCE-mlxbf-pka-Fix-kernel-crash-with-pka-TRN.patch ++0261-mlxbf-ptm-power-and-thermal-management-debugfs-drive.patch ++0262-UBUNTU-SAUCE-mlxbf-pmc-Fix-event-string-typo.patch ++0263-UBUNTU-SAUCE-mlxbf-pmc-Support-for-BlueField-3-perfo.patch ++0264-UBUNTU-SAUCE-platform-mellanox-Add-ctrl-message-and-.patch + 0265-hwmon-mlxreg-fan-Return-zero-speed-for-broken-fan.patch ++0266-UBUNTU-SAUCE-mlxbf-pmc-Bug-fix-for-BlueField-3-count.patch ++0267-UBUNTU-SAUCE-mmc-sdhci-of-dwcmshc-add-the-missing-de.patch ++0268-DS-mlxsw-core_linecards-Disable-firmware-bundling-ma.patch ++0269-platform-mellanox-Cosmetic-changes.patch ++0270-platform-mellanox-Fix-order-in-exit-flow.patch ++0271-platform-mellanox-Add-new-attributes.patch ++0272-platform-mellanox-Change-register-offset-addresses.patch ++0273-platform-mellanox-Add-field-upgrade-capability-regis.patch ++0274-platform-mellanox-Modify-reset-causes-description.patch ++0275-mlxsw-Use-u16-for-local_port-field-instead-of-u8.patch ++0276-mlxsw-minimal-Change-type-for-local-port.patch ++0277-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch ++0278-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch ++0279-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch ++0280-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch ++0281-platform-mellanox-mlx-platform-Modify-health-and-pow.patch ++0282-platform-mellanox-mlx-platform-add-support-of-5th-CP.patch ++0283-mlxsw-core_hwmon-Align-modules-label-name-assignment.patch ++0284-platform-mellanox-mlx-platform-fix-CPLD4-PN-report.patch + 0285-platform-mellanox-nvsw-sn2201-change-fans-i2c-busses.patch ++9002-TMP-fix-for-fan-minimum-speed.patch ###-> mellanox_hw_mgmt-end + # Cisco patches for 5.10 kernel